Merge "Add target binderDriverInterfaceTest_IPC_32" into oreo-vts-dev
am: 9d332a7110  -s ours

Change-Id: Iee14266e4d59b4ad2b213e0d401d8cae6c843f97
diff --git a/Android.bp b/Android.bp
index cd05b21..de9ea86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8,8 +8,15 @@
 
 subdirs = [
     "cmds/*",
+    "headers",
     "libs/*",
     "opengl",
     "services/*",
     "vulkan",
 ]
+
+cc_library_headers {
+    name: "libandroid_sensor_headers",
+    vendor: true,
+    export_include_dirs: ["include_sensor"],
+}
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index 6c5869a..b3cbdef 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -7,15 +7,17 @@
     shared_libs: [
         "libbinder",
         "libhwbinder",
-        "android.hidl.manager@1.0",
         "libhidlbase",
         "libhidltransport",
         "liblog",
-        "libcutils",
         "libutils",
+        "libcutils",
         "libz",
         "libbase",
     ],
+    static_libs: [
+        "libpdx_default_transport",
+    ],
 
     init_rc: ["atrace.rc"],
 
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 47e04e7..9cdc9e9 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -26,7 +26,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/sendfile.h>
 #include <time.h>
 #include <unistd.h>
 #include <zlib.h>
@@ -40,18 +39,21 @@
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
-#include <cutils/properties.h>
 
+#include <pdx/default_transport/service_utility.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Tokenizer.h>
 #include <utils/Trace.h>
 #include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
 
 using namespace android;
+using pdx::default_transport::ServiceUtility;
 
 using std::string;
-#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
 
 #define MAX_SYS_FILES 10
 #define MAX_PACKAGES 16
@@ -61,6 +63,7 @@
 const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
 const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
 const char* k_coreServiceCategory = "core_services";
+const char* k_pdxServiceCategory = "pdx";
 const char* k_coreServicesProp = "ro.atrace.core.services";
 
 typedef enum { OPT, REQ } requiredness  ;
@@ -89,7 +92,9 @@
 
 /* Tracing categories */
 static const TracingCategory k_categories[] = {
-    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
+    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
+        { OPT,      "events/mdss/enable" },
+    } },
     { "input",      "Input",            ATRACE_TAG_INPUT, { } },
     { "view",       "View System",      ATRACE_TAG_VIEW, { } },
     { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
@@ -112,12 +117,14 @@
     { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
     { "adb",        "ADB",              ATRACE_TAG_ADB, { } },
     { k_coreServiceCategory, "Core services", 0, { } },
+    { k_pdxServiceCategory, "PDX services", 0, { } },
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "events/sched/sched_switch/enable" },
         { REQ,      "events/sched/sched_wakeup/enable" },
         { OPT,      "events/sched/sched_waking/enable" },
         { OPT,      "events/sched/sched_blocked_reason/enable" },
         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
+        { OPT,      "events/cgroup/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "events/irq/enable" },
@@ -174,6 +181,7 @@
         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
+        { REQ,      "events/lowmemorykiller/enable" },
     } },
     { "regulators",  "Voltage and Current Regulators", 0, {
         { REQ,      "events/regulator/enable" },
@@ -181,11 +189,12 @@
     { "binder_driver", "Binder Kernel driver", 0, {
         { REQ,      "events/binder/binder_transaction/enable" },
         { REQ,      "events/binder/binder_transaction_received/enable" },
+        { OPT,      "events/binder/binder_set_priority/enable" },
     } },
     { "binder_lock", "Binder global lock trace", 0, {
-        { REQ,      "events/binder/binder_lock/enable" },
-        { REQ,      "events/binder/binder_locked/enable" },
-        { REQ,      "events/binder/binder_unlock/enable" },
+        { OPT,      "events/binder/binder_lock/enable" },
+        { OPT,      "events/binder/binder_locked/enable" },
+        { OPT,      "events/binder/binder_unlock/enable" },
     } },
     { "pagecache",  "Page cache", 0, {
         { REQ,      "events/filemap/enable" },
@@ -205,8 +214,9 @@
 static const char* g_outputFile = nullptr;
 
 /* Global state */
+static bool g_tracePdx = false;
 static bool g_traceAborted = false;
-static bool g_categoryEnables[NELEM(k_categories)] = {};
+static bool g_categoryEnables[arraysize(k_categories)] = {};
 static std::string g_traceFolder;
 
 /* Sys file paths */
@@ -361,9 +371,11 @@
 static bool isCategorySupported(const TracingCategory& category)
 {
     if (strcmp(category.name, k_coreServiceCategory) == 0) {
-        char value[PROPERTY_VALUE_MAX];
-        property_get(k_coreServicesProp, value, "");
-        return strlen(value) != 0;
+        return !android::base::GetProperty(k_coreServicesProp, "").empty();
+    }
+
+    if (strcmp(category.name, k_pdxServiceCategory) == 0) {
+        return true;
     }
 
     bool ok = category.tags != 0;
@@ -378,7 +390,7 @@
                     ok = true;
                 }
             } else {
-                ok |= fileIsWritable(path);
+                ok = true;
             }
         }
     }
@@ -564,9 +576,8 @@
 // processes to pick up the new value.
 static bool setTagsProperty(uint64_t tags)
 {
-    char buf[PROPERTY_VALUE_MAX];
-    snprintf(buf, sizeof(buf), "%#" PRIx64, tags);
-    if (property_set(k_traceTagsProperty, buf) < 0) {
+    std::string value = android::base::StringPrintf("%#" PRIx64, tags);
+    if (!android::base::SetProperty(k_traceTagsProperty, value)) {
         fprintf(stderr, "error setting trace tags system property\n");
         return false;
     }
@@ -575,14 +586,13 @@
 
 static void clearAppProperties()
 {
-    char buf[PROPERTY_KEY_MAX];
     for (int i = 0; i < MAX_PACKAGES; i++) {
-        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
-        if (property_set(buf, "") < 0) {
-            fprintf(stderr, "failed to clear system property: %s\n", buf);
+        std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
+        if (!android::base::SetProperty(key, "")) {
+            fprintf(stderr, "failed to clear system property: %s\n", key.c_str());
         }
     }
-    if (property_set(k_traceAppsNumberProperty, "") < 0) {
+    if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
         fprintf(stderr, "failed to clear system property: %s",
               k_traceAppsNumberProperty);
     }
@@ -592,7 +602,6 @@
 // application-level tracing.
 static bool setAppCmdlineProperty(char* cmdline)
 {
-    char buf[PROPERTY_KEY_MAX];
     int i = 0;
     char* start = cmdline;
     while (start != NULL) {
@@ -606,9 +615,9 @@
             *end = '\0';
             end++;
         }
-        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
-        if (property_set(buf, start) < 0) {
-            fprintf(stderr, "error setting trace app %d property to %s\n", i, buf);
+        std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
+        if (!android::base::SetProperty(key, start)) {
+            fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
             clearAppProperties();
             return false;
         }
@@ -616,9 +625,9 @@
         i++;
     }
 
-    snprintf(buf, sizeof(buf), "%d", i);
-    if (property_set(k_traceAppsNumberProperty, buf) < 0) {
-        fprintf(stderr, "error setting trace app number property to %s\n", buf);
+    std::string value = android::base::StringPrintf("%d", i);
+    if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
+        fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
         clearAppProperties();
         return false;
     }
@@ -628,7 +637,7 @@
 // Disable all /sys/ enable files.
 static bool disableKernelTraceEvents() {
     bool ok = true;
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         const TracingCategory &c = k_categories[i];
         for (int j = 0; j < MAX_SYS_FILES; j++) {
             const char* path = c.sysfiles[j].path;
@@ -716,7 +725,7 @@
 
 static bool setCategoryEnable(const char* name, bool enable)
 {
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         const TracingCategory& c = k_categories[i];
         if (strcmp(name, c.name) == 0) {
             if (isCategorySupported(c)) {
@@ -778,7 +787,7 @@
 
     // Set up the tags property.
     uint64_t tags = 0;
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         if (g_categoryEnables[i]) {
             const TracingCategory &c = k_categories[i];
             tags |= c.tags;
@@ -787,31 +796,38 @@
     ok &= setTagsProperty(tags);
 
     bool coreServicesTagEnabled = false;
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
             coreServicesTagEnabled = g_categoryEnables[i];
         }
+
+        // Set whether to poke PDX services in this session.
+        if (strcmp(k_categories[i].name, k_pdxServiceCategory) == 0) {
+            g_tracePdx = g_categoryEnables[i];
+        }
     }
 
     std::string packageList(g_debugAppCmdLine);
     if (coreServicesTagEnabled) {
-        char value[PROPERTY_VALUE_MAX];
-        property_get(k_coreServicesProp, value, "");
         if (!packageList.empty()) {
             packageList += ",";
         }
-        packageList += value;
+        packageList += android::base::GetProperty(k_coreServicesProp, "");
     }
     ok &= setAppCmdlineProperty(&packageList[0]);
     ok &= pokeBinderServices();
     pokeHalServices();
 
+    if (g_tracePdx) {
+        ok &= ServiceUtility::PokeServices();
+    }
+
     // Disable all the sysfs enables.  This is done as a separate loop from
     // the enables to allow the same enable to exist in multiple categories.
     ok &= disableKernelTraceEvents();
 
     // Enable all the sysfs enables that are in an enabled category.
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         if (g_categoryEnables[i]) {
             const TracingCategory &c = k_categories[i];
             for (int j = 0; j < MAX_SYS_FILES; j++) {
@@ -843,6 +859,10 @@
     clearAppProperties();
     pokeBinderServices();
 
+    if (g_tracePdx) {
+        ServiceUtility::PokeServices();
+    }
+
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
@@ -976,11 +996,16 @@
             fprintf(stderr, "error cleaning up zlib: %d\n", result);
         }
     } else {
-        ssize_t sent = 0;
-        while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
-        if (sent == -1) {
-            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
-                    errno);
+        char buf[4096];
+        ssize_t rc;
+        while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
+            if (!android::base::WriteFully(outFd, buf, rc)) {
+                fprintf(stderr, "error writing trace: %s\n", strerror(errno));
+                break;
+            }
+        }
+        if (rc == -1) {
+            fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
         }
     }
 
@@ -1008,7 +1033,7 @@
 
 static void listSupportedCategories()
 {
-    for (int i = 0; i < NELEM(k_categories); i++) {
+    for (size_t i = 0; i < arraysize(k_categories); i++) {
         const TracingCategory& c = k_categories[i];
         if (isCategorySupported(c)) {
             printf("  %10s - %s\n", c.name, c.longname);
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d538145..3ea1d56 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -25,6 +25,8 @@
     chown root shell /sys/kernel/tracing/events/sched/sched_blocked_reason/enable
     chown root shell /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
     chown root shell /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
+    chown root shell /sys/kernel/debug/tracing/events/cgroup/enable
+    chown root shell /sys/kernel/tracing/events/cgroup/enable
     chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
     chown root shell /sys/kernel/tracing/events/power/cpu_frequency/enable
     chown root shell /sys/kernel/debug/tracing/events/power/cpu_idle/enable
@@ -53,6 +55,8 @@
     chown root shell /sys/kernel/tracing/events/binder/binder_locked/enable
     chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
     chown root shell /sys/kernel/tracing/events/binder/binder_unlock/enable
+    chown root shell /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chown root shell /sys/kernel/tracing/events/lowmemorykiller/enable
 
     chown root shell /sys/kernel/debug/tracing/tracing_on
     chown root shell /sys/kernel/tracing/tracing_on
@@ -75,6 +79,8 @@
     chmod 0664 /sys/kernel/tracing/events/sched/sched_blocked_reason/enable
     chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
     chmod 0664 /sys/kernel/tracing/events/sched/sched_cpu_hotplug/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/cgroup/enable
+    chmod 0664 /sys/kernel/tracing/events/cgroup/enable
     chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
     chmod 0664 /sys/kernel/tracing/events/power/cpu_frequency/enable
     chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
@@ -123,6 +129,8 @@
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_result/enable
     chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_reply/enable
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_reply/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chmod 0664 /sys/kernel/tracing/events/lowmemorykiller/enable
 
     # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
index 880bc75..10dda56 100644
--- a/cmds/bugreportz/Android.mk
+++ b/cmds/bugreportz/Android.mk
@@ -25,6 +25,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := bugreportz_test
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_CFLAGS := -Werror -Wall
diff --git a/cmds/bugreportz/AndroidTest.xml b/cmds/bugreportz/AndroidTest.xml
new file mode 100644
index 0000000..38b6276
--- /dev/null
+++ b/cmds/bugreportz/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for bugreportz_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="bugreportz_test->/data/local/tmp/bugreportz_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="bugreportz_test" />
+    </test>
+</configuration>
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 7e05d72..014c995 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -35,12 +35,11 @@
 #include <fcntl.h>
 #include <sys/time.h>
 #include <errno.h>
+#include <memory>
 
 #include "selinux/selinux.h"
 #include "selinux/android.h"
 
-#include <UniquePtr.h>
-
 #define DEBUG 0
 
 using namespace android;
@@ -55,7 +54,7 @@
         freecon(p);
     }
 };
-typedef UniquePtr<char[], SecurityContext_Delete> Unique_SecurityContext;
+typedef std::unique_ptr<char[], SecurityContext_Delete> Unique_SecurityContext;
 
 class MyShellCallback : public BnShellCallback
 {
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
new file mode 100644
index 0000000..f908cbf
--- /dev/null
+++ b/cmds/dumpstate/Android.bp
@@ -0,0 +1,130 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+    name: "dumpstate_defaults",
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-variable",
+        "-Wunused-parameter",
+    ],
+}
+
+cc_library_headers {
+    name: "dumpstate_headers",
+    vendor_available: true,
+    export_include_dirs: ["."],
+    header_libs: [
+        "libbase_headers",
+        "libutils_headers",
+    ],
+    export_header_lib_headers: [
+        "libbase_headers",
+        "libutils_headers",
+    ],
+}
+
+cc_library_shared {
+    name: "libdumpstateutil",
+    defaults: ["dumpstate_defaults"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    header_libs: ["dumpstate_headers"],
+    export_header_lib_headers: ["dumpstate_headers"],
+    srcs: [
+        "DumpstateInternal.cpp",
+        "DumpstateUtil.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+}
+
+cc_library_shared {
+    name: "libdumpstateaidl",
+    defaults: ["dumpstate_defaults"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+    aidl: {
+        local_include_dirs: ["binder"],
+        export_aidl_headers: true,
+    },
+    srcs: [
+        "binder/android/os/IDumpstate.aidl",
+        "binder/android/os/IDumpstateListener.aidl",
+        "binder/android/os/IDumpstateToken.aidl",
+    ],
+}
+
+cc_binary {
+    name: "dumpstate",
+    defaults: ["dumpstate_defaults"],
+    header_libs: ["dumpstate_headers"],
+    shared_libs: [
+        "android.hardware.dumpstate@1.0",
+        "libziparchive",
+        "libbase",
+        "libbinder",
+        "libcrypto",
+        "libcutils",
+        "libdebuggerd_client",
+        "libdumpstateaidl",
+        "libdumpstateutil",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    srcs: [
+        "DumpstateInternal.cpp",
+        "DumpstateService.cpp",
+        "utils.cpp",
+        "dumpstate.cpp",
+    ],
+    init_rc: ["dumpstate.rc"],
+}
+
+cc_test {
+    name: "dumpstate_test",
+    defaults: ["dumpstate_defaults"],
+    header_libs: ["dumpstate_headers"],
+    shared_libs: [
+        "libziparchive",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libdebuggerd_client",
+        "libdumpstateaidl",
+        "libdumpstateutil",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    srcs: [
+        "DumpstateInternal.cpp",
+        "DumpstateService.cpp",
+        "utils.cpp",
+        "tests/dumpstate_test.cpp",
+    ],
+    static_libs: ["libgmock"],
+}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index a407ea2..ea5fbf1 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -1,178 +1,22 @@
 LOCAL_PATH:= $(call my-dir)
 
-# ================#
-# Common settings #
-# ================#
-# ZipArchive support, the order matters here to get all symbols.
-COMMON_ZIP_LIBRARIES := libziparchive libz libcrypto
-
-# TODO: ideally the tests should depend on a shared dumpstate library, but currently libdumpstate
-# is used to define the device-specific HAL library. Instead, both dumpstate and dumpstate_test
-# shares a lot of common settings
-COMMON_LOCAL_CFLAGS := \
-       -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
-COMMON_SRC_FILES := \
-        DumpstateInternal.cpp \
-        utils.cpp
-COMMON_SHARED_LIBRARIES := \
-        android.hardware.dumpstate@1.0 \
-        android.hidl.manager@1.0 \
-        libhidlbase \
-        libbase \
-        libbinder \
-        libcutils \
-        libdebuggerd_client \
-        libdumpstateaidl \
-        libdumpstateutil \
-        liblog \
-        libselinux \
-        libutils \
-        $(COMMON_ZIP_LIBRARIES)
-
-# ====================#
-# libdumpstateutil #
-# ====================#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libdumpstateutil
-
-LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_SRC_FILES := \
-        DumpstateInternal.cpp \
-        DumpstateUtil.cpp
-LOCAL_SHARED_LIBRARIES := \
-        libbase \
-        liblog \
-
-include $(BUILD_SHARED_LIBRARY)
-
-# ====================#
-# libdumpstateheaders #
-# ====================#
-# TODO: this module is necessary so the device-specific libdumpstate implementations do not
-# need to add any other dependency (like libbase). Should go away once dumpstate HAL changes.
-include $(CLEAR_VARS)
-
-LOCAL_EXPORT_C_INCLUDE_DIRS = $(LOCAL_PATH)
-LOCAL_MODULE := libdumpstateheaders
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
-        $(COMMON_SHARED_LIBRARIES)
-LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := \
-        $(COMMON_STATIC_LIBRARIES)
-# Soong requires that whats is on LOCAL_EXPORTED_ is also on LOCAL_
-LOCAL_SHARED_LIBRARIES := $(LOCAL_EXPORT_SHARED_LIBRARY_HEADERS)
-LOCAL_STATIC_LIBRARIES := $(LOCAL_EXPORT_STATIC_LIBRARY_HEADERS)
-
-include $(BUILD_STATIC_LIBRARY)
-
-# ================ #
-# libdumpstateaidl #
-# =================#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libdumpstateaidl
-
-LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
-
-LOCAL_SHARED_LIBRARIES := \
-        libbinder \
-        libutils
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/binder
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/binder
-LOCAL_SRC_FILES := \
-        binder/android/os/IDumpstate.aidl \
-        binder/android/os/IDumpstateListener.aidl \
-        binder/android/os/IDumpstateToken.aidl
-
-include $(BUILD_SHARED_LIBRARY)
-
-# ==========#
-# dumpstate #
-# ==========#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \
-        DumpstateService.cpp \
-        dumpstate.cpp
-
-LOCAL_MODULE := dumpstate
-
-LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES)
-
-LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES)
-
-LOCAL_CFLAGS += $(COMMON_LOCAL_CFLAGS)
-
-LOCAL_INIT_RC := dumpstate.rc
-
-include $(BUILD_EXECUTABLE)
-
-# ===============#
-# dumpstate_test #
-# ===============#
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := dumpstate_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
-
-LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \
-        DumpstateService.cpp \
-        tests/dumpstate_test.cpp
-
-LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES) \
-        libgmock
-
-LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES)
-
-include $(BUILD_NATIVE_TEST)
-
 # =======================#
 # dumpstate_test_fixture #
 # =======================#
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := dumpstate_test_fixture
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS)
+LOCAL_CFLAGS := \
+       -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_SRC_FILES := \
         tests/dumpstate_test_fixture.cpp
 
-LOCAL_MODULE_CLASS := NATIVE_TESTS
-
-dumpstate_tests_intermediates := $(local-intermediates-dir)/DATA
-dumpstate_tests_subpath_from_data := nativetest/dumpstate_test_fixture
-dumpstate_tests_root_in_device := /data/$(dumpstate_tests_subpath_from_data)
-dumpstate_tests_root_for_test_zip := $(dumpstate_tests_intermediates)/$(dumpstate_tests_subpath_from_data)
-testdata_files := $(call find-subdir-files, testdata/*)
-
-# Copy test data files to intermediates/DATA for use with LOCAL_PICKUP_FILES
-GEN := $(addprefix $(dumpstate_tests_root_for_test_zip)/, $(testdata_files))
-$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
-$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@
-$(GEN): $(dumpstate_tests_root_for_test_zip)/testdata/% : $(LOCAL_PATH)/testdata/%
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-# Copy test data files again to $OUT/data so the tests can be run with adb sync
-# TODO: the build system should do this automatically
-GEN := $(addprefix $(TARGET_OUT_DATA)/$(dumpstate_tests_subpath_from_data)/, $(testdata_files))
-$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
-$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@
-$(GEN): $(TARGET_OUT_DATA)/$(dumpstate_tests_subpath_from_data)/testdata/% : $(LOCAL_PATH)/testdata/%
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-LOCAL_PICKUP_FILES := $(dumpstate_tests_intermediates)
+LOCAL_TEST_DATA := $(call find-test-data-in-subdirs, $(LOCAL_PATH), *, tests/testdata)
 
 include $(BUILD_NATIVE_TEST)
diff --git a/cmds/dumpstate/AndroidTest.xml b/cmds/dumpstate/AndroidTest.xml
new file mode 100644
index 0000000..f189489
--- /dev/null
+++ b/cmds/dumpstate/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for dumpstate_test_fixture">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="dumpstate_test_fixture->/data/local/tmp/dumpstate_test_fixture" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="dumpstate_test_fixture" />
+    </test>
+</configuration>
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index 0343277..f0b6203 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -18,6 +18,8 @@
 
 #include "DumpstateInternal.h"
 
+#include <grp.h>
+#include <pwd.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -25,14 +27,14 @@
 #include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <cstdint>
 #include <string>
 #include <vector>
 
 #include <android-base/file.h>
-#include <cutils/log.h>
-#include <private/android_filesystem_config.h>
+#include <log/log.h>
 
 uint64_t Nanotime() {
     timespec ts;
@@ -42,7 +44,17 @@
 
 // Switches to non-root user and group.
 bool DropRootUser() {
-    if (getgid() == AID_SHELL && getuid() == AID_SHELL) {
+    struct group* grp = getgrnam("shell");
+    gid_t shell_gid = grp != nullptr ? grp->gr_gid : 0;
+    struct passwd* pwd = getpwnam("shell");
+    uid_t shell_uid = pwd != nullptr ? pwd->pw_uid : 0;
+
+    if (!shell_gid || !shell_uid) {
+        MYLOGE("Unable to get AID_SHELL: %s\n", strerror(errno));
+        return false;
+    }
+
+    if (getgid() == shell_gid && getuid() == shell_uid) {
         MYLOGD("drop_root_user(): already running as Shell\n");
         return true;
     }
@@ -52,17 +64,28 @@
         return false;
     }
 
-    gid_t groups[] = {AID_LOG,  AID_SDCARD_R,     AID_SDCARD_RW, AID_MOUNT,
-                      AID_INET, AID_NET_BW_STATS, AID_READPROC,  AID_BLUETOOTH};
-    if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) {
+    static const std::vector<std::string> group_names{
+        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats", "readproc", "bluetooth"};
+    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());
+        groups[i] = grp != nullptr ? grp->gr_gid : 0;
+        if (groups[i] == 0) {
+            MYLOGE("Unable to get required gid '%s': %s\n", group_names[i].c_str(),
+                   strerror(errno));
+            return false;
+        }
+    }
+
+    if (setgroups(groups.size(), groups.data()) != 0) {
         MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
         return false;
     }
-    if (setgid(AID_SHELL) != 0) {
+    if (setgid(shell_gid) != 0) {
         MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
         return false;
     }
-    if (setuid(AID_SHELL) != 0) {
+    if (setuid(shell_uid) != 0) {
         MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
         return false;
     }
diff --git a/cmds/dumpstate/DumpstateInternal.h b/cmds/dumpstate/DumpstateInternal.h
index 2f7704d..10db5d6 100644
--- a/cmds/dumpstate/DumpstateInternal.h
+++ b/cmds/dumpstate/DumpstateInternal.h
@@ -32,6 +32,12 @@
     ALOGI(__VA_ARGS__);
 #endif
 
+#ifndef MYLOGW
+#define MYLOGW(...)               \
+    fprintf(stderr, __VA_ARGS__); \
+    ALOGW(__VA_ARGS__);
+#endif
+
 #ifndef MYLOGE
 #define MYLOGE(...)               \
     fprintf(stderr, __VA_ARGS__); \
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 26702c4..e866b8b 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -30,7 +30,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/log.h>
+#include <log/log.h>
 
 #include "DumpstateInternal.h"
 
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f84d86d..5f93e99 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -21,13 +21,9 @@
 #include <fcntl.h>
 #include <libgen.h>
 #include <limits.h>
-#include <memory>
-#include <regex>
-#include <set>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string>
 #include <string.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
@@ -35,6 +31,11 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <memory>
+#include <regex>
+#include <set>
+#include <string>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
@@ -71,6 +72,7 @@
 
 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
+#define BLK_DEV_SYS_DIR "/sys/block"
 
 #define RAFT_DIR "/data/misc/raft"
 #define RECOVERY_DIR "/cache/recovery"
@@ -78,19 +80,29 @@
 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
-#define TOMBSTONE_DIR "/data/tombstones"
-#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
-/* Can accomodate a tombstone number up to 9999. */
-#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
-#define NUM_TOMBSTONES  10
 #define WLUTIL "/vendor/xbin/wlutil"
 
-typedef struct {
-  char name[TOMBSTONE_MAX_LEN];
-  int fd;
-} tombstone_data_t;
+// TODO(narayan): Since this information has to be kept in sync
+// with tombstoned, we should just put it in a common header.
+//
+// File: system/core/debuggerd/tombstoned/tombstoned.cpp
+static const std::string TOMBSTONE_DIR = "/data/tombstones/";
+static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
+static const std::string ANR_DIR = "/data/anr/";
+static const std::string ANR_FILE_PREFIX = "anr_";
 
-static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
+struct DumpData {
+    std::string name;
+    int fd;
+    time_t mtime;
+};
+
+static bool operator<(const DumpData& d1, const DumpData& d2) {
+    return d1.mtime > d2.mtime;
+}
+
+static std::unique_ptr<std::vector<DumpData>> tombstone_data;
+static std::unique_ptr<std::vector<DumpData>> anr_data;
 
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
@@ -111,7 +123,13 @@
 static const std::string ZIP_ROOT_DIR = "FS";
 
 // Must be hardcoded because dumpstate HAL implementation need SELinux access to it
-static const std::string kDumpstateBoardPath = "/bugreports/dumpstate_board.txt";
+static const std::string kDumpstateBoardPath = "/bugreports/";
+static const std::string kDumpstateBoardFiles[] = {
+    "dumpstate_board.txt",
+    "dumpstate_board.bin"
+};
+static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
+
 static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
 
 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
@@ -122,23 +140,85 @@
 
 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
 
-/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
- * otherwise, gets just those modified in the last half an hour. */
-static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
-    time_t thirty_minutes_ago = ds.now_ - 60 * 30;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
-        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
-                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-        struct stat st;
-        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
-            (ds.IsZipping() || st.st_mtime >= thirty_minutes_ago)) {
-            data[i].fd = fd;
-        } else {
-            close(fd);
-            data[i].fd = -1;
+/*
+ * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
+ * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
+ * is set, the vector only contains files that were written in the last 30 minutes.
+ * If |limit_by_count| is set, the vector only contains the ten latest files.
+ */
+static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
+                                         const std::string& file_prefix,
+                                         bool limit_by_mtime,
+                                         bool limit_by_count = true) {
+    const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
+
+    std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
+    std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
+
+    struct dirent* entry = nullptr;
+    while ((entry = readdir(dump_dir.get()))) {
+        if (entry->d_type != DT_REG) {
+            continue;
         }
+
+        const std::string base_name(entry->d_name);
+        if (base_name.find(file_prefix) != 0) {
+            continue;
+        }
+
+        const std::string abs_path = dir_path + base_name;
+        android::base::unique_fd fd(
+            TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
+        if (fd == -1) {
+            MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+            break;
+        }
+
+        struct stat st = {};
+        if (fstat(fd, &st) == -1) {
+            MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+            continue;
+        }
+
+        if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
+            MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
+            continue;
+        }
+
+        DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
+
+        dump_data->push_back(data);
     }
+
+    std::sort(dump_data->begin(), dump_data->end());
+
+    if (limit_by_count && dump_data->size() > 10) {
+        dump_data->erase(dump_data->begin() + 10, dump_data->end());
+    }
+
+    return dump_data.release();
+}
+
+static bool AddDumps(const std::vector<DumpData>::const_iterator start,
+                     const std::vector<DumpData>::const_iterator end,
+                     const char* type_name, const bool add_to_zip) {
+    bool dumped = false;
+    for (auto it = start; it != end; ++it) {
+        const std::string& name = it->name;
+        const int fd = it->fd;
+        dumped = true;
+        if (ds.IsZipping() && add_to_zip) {
+            if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
+                MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
+            }
+        } else {
+            dump_file_from_fd(type_name, name.c_str(), fd);
+        }
+
+        close(fd);
+    }
+
+    return dumped;
 }
 
 // for_each_pid() callback to get mount info about a process.
@@ -377,88 +457,6 @@
     }
 }
 
-/**
- * Finds the last modified file in the directory dir whose name starts with file_prefix.
- *
- * Function returns empty string when it does not find a file
- */
-static std::string GetLastModifiedFileWithPrefix(const std::string& dir,
-                                                 const std::string& file_prefix) {
-    std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir);
-    if (d == nullptr) {
-        MYLOGD("Error %d opening %s\n", errno, dir.c_str());
-        return "";
-    }
-
-    // Find the newest file matching the file_prefix in dir
-    struct dirent *de;
-    time_t last_modified_time = 0;
-    std::string last_modified_file = "";
-    struct stat s;
-
-    while ((de = readdir(d.get()))) {
-        std::string file = std::string(de->d_name);
-        if (!file_prefix.empty()) {
-            if (!android::base::StartsWith(file, file_prefix.c_str())) continue;
-        }
-        file = dir + "/" + file;
-        int ret = stat(file.c_str(), &s);
-
-        if ((ret == 0) && (s.st_mtime > last_modified_time)) {
-            last_modified_file = file;
-            last_modified_time = s.st_mtime;
-        }
-    }
-
-    return last_modified_file;
-}
-
-static void DumpModemLogs() {
-    DurationReporter durationReporter("DUMP MODEM LOGS");
-    if (PropertiesHelper::IsUserBuild()) {
-        return;
-    }
-
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n");
-        return;
-    }
-
-    std::string file_prefix = android::base::GetProperty("ro.radio.log_prefix", "");
-
-    if(file_prefix.empty()) {
-        MYLOGD("No modem log : file_prefix is empty\n");
-        return;
-    }
-
-    // TODO: b/33820081 we need to provide a right way to dump modem logs.
-    std::string radio_bugreport_dir = android::base::GetProperty("ro.radio.log_loc", "");
-    if (radio_bugreport_dir.empty()) {
-        radio_bugreport_dir = dirname(ds.GetPath("").c_str());
-    }
-
-    MYLOGD("DumpModemLogs: directory is %s and file_prefix is %s\n",
-           radio_bugreport_dir.c_str(), file_prefix.c_str());
-
-    std::string modem_log_file = GetLastModifiedFileWithPrefix(radio_bugreport_dir, file_prefix);
-
-    struct stat s;
-    if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) {
-        MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str());
-        return;
-    }
-
-    std::string filename = basename(modem_log_file.c_str());
-    if (!ds.AddZipEntry(filename, modem_log_file)) {
-        MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str());
-    } else {
-        MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str());
-        if (remove(modem_log_file.c_str())) {
-            MYLOGE("Error removing modem log %s\n", modem_log_file.c_str());
-        }
-    }
-}
-
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -472,7 +470,6 @@
     return false;
 }
 
-static const char mmcblk0[] = "/sys/block/mmcblk0/";
 unsigned long worst_write_perf = 20000; /* in KB/s */
 
 //
@@ -586,11 +583,13 @@
         return 0;
     }
 
-    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
-        path += sizeof(mmcblk0) - 1;
+    if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
+        path += sizeof(BLK_DEV_SYS_DIR) - 1;
     }
 
-    printf("%s: %s\n", path, buffer);
+    printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
+           "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
+           "W-wait", "in-fli", "activ", "T-wait", path, buffer);
     free(buffer);
 
     if (fields[__STAT_IO_TICKS]) {
@@ -627,9 +626,9 @@
                                  / fields[__STAT_IO_TICKS];
 
         if (!write_perf && !write_ios) {
-            printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
+            printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
         } else {
-            printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
+            printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
                    read_ios, write_perf, write_ios, queue);
         }
 
@@ -849,7 +848,7 @@
                         "-d", "*:v"});
 }
 
-static void DumpIpTables() {
+static void DumpIpTablesAsRoot() {
     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
     RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
@@ -860,11 +859,10 @@
     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
 }
 
-static void AddAnrTraceFiles() {
-    bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
+                                  const std::string& anr_traces_dir) {
     std::string dump_traces_dir;
 
-    /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != nullptr) {
         if (add_to_zip) {
             dump_traces_dir = dirname(dump_traces_path);
@@ -877,8 +875,6 @@
         }
     }
 
-    std::string anr_traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
-    std::string anr_traces_dir = dirname(anr_traces_path.c_str());
 
     // Make sure directory is not added twice.
     // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
@@ -888,65 +884,166 @@
     // be revisited.
     bool already_dumped = anr_traces_dir == dump_traces_dir;
 
-    MYLOGD("AddAnrTraceFiles(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
+    MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
            dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
 
-    if (anr_traces_path.empty()) {
-        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
+    int fd = TEMP_FAILURE_RETRY(
+        open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+    if (fd < 0) {
+        printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
     } else {
-        int fd = TEMP_FAILURE_RETRY(
-            open(anr_traces_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-        if (fd < 0) {
-            printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path.c_str(),
-                   strerror(errno));
-        } else {
-            if (add_to_zip) {
-                if (!already_dumped) {
-                    MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
-                           anr_traces_dir.c_str());
-                    ds.AddDir(anr_traces_dir, true);
-                    already_dumped = true;
-                }
-            } else {
-                MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
-                       anr_traces_path.c_str());
-                dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path.c_str(), fd);
+        if (add_to_zip) {
+            if (!already_dumped) {
+                MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
+                       anr_traces_dir.c_str());
+                ds.AddDir(anr_traces_dir, true);
             }
+        } else {
+            MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
+                   anr_traces_file.c_str());
+            dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
+        }
+    }
+}
+
+static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
+    MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
+           anr_traces_dir.c_str());
+
+    // If we're here, dump_traces_path will always be a temporary file
+    // (created with mkostemp or similar) that contains dumps taken earlier
+    // on in the process.
+    if (dump_traces_path != nullptr) {
+        if (add_to_zip) {
+            ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
+        } else {
+            MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
+                   dump_traces_path);
+            ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
+        }
+
+        const int ret = unlink(dump_traces_path);
+        if (ret == -1) {
+            MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
+                   strerror(errno));
         }
     }
 
-    if (add_to_zip && already_dumped) {
-        MYLOGD("Already dumped directory %s to the zip file\n", anr_traces_dir.c_str());
+    // Add a specific message for the first ANR Dump.
+    if (anr_data->size() > 0) {
+        AddDumps(anr_data->begin(), anr_data->begin() + 1,
+                 "VM TRACES AT LAST ANR", add_to_zip);
+
+        if (anr_data->size() > 1) {
+            // NOTE: Historical ANRs are always added as separate entries in the
+            // bugreport zip file.
+            AddDumps(anr_data->begin() + 1, anr_data->end(),
+                     "HISTORICAL ANR", true /* add_to_zip */);
+        }
+    } else {
+        printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
+    }
+}
+
+static void AddAnrTraceFiles() {
+    const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+
+    std::string anr_traces_file;
+    std::string anr_traces_dir;
+    bool is_global_trace_file = true;
+
+    // First check whether the stack-trace-dir property is set. When it's set,
+    // each ANR trace will be written to a separate file and not to a global
+    // stack trace file.
+    anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+    if (anr_traces_dir.empty()) {
+        anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+        if (!anr_traces_file.empty()) {
+            anr_traces_dir = dirname(anr_traces_file.c_str());
+        }
+    } else {
+        is_global_trace_file = false;
+    }
+
+    // We have neither configured a global trace file nor a trace directory,
+    // there will be nothing to dump.
+    if (anr_traces_file.empty() && anr_traces_dir.empty()) {
+        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
         return;
     }
 
+    if (is_global_trace_file) {
+        AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
+    } else {
+        AddAnrTraceDir(add_to_zip, anr_traces_dir);
+    }
+
     /* slow traces for slow operations */
     struct stat st;
-    if (!anr_traces_path.empty()) {
-        int tail = anr_traces_path.size() - 1;
-        while (tail > 0 && anr_traces_path.at(tail) != '/') {
-            tail--;
-        }
+    if (!anr_traces_dir.empty()) {
         int i = 0;
-        while (1) {
-            anr_traces_path = anr_traces_path.substr(0, tail + 1) +
-                              android::base::StringPrintf("slow%02d.txt", i);
-            if (stat(anr_traces_path.c_str(), &st)) {
+        while (true) {
+            const std::string slow_trace_path =
+                anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
+            if (stat(slow_trace_path.c_str(), &st)) {
                 // No traces file at this index, done with the files.
                 break;
             }
-            ds.DumpFile("VM TRACES WHEN SLOW", anr_traces_path.c_str());
+            ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
             i++;
         }
     }
 }
 
+static void DumpBlockStatFiles() {
+    DurationReporter duration_reporter("DUMP BLOCK STAT");
+
+    std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
+
+    if (dirptr == nullptr) {
+        MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
+        return;
+    }
+
+    printf("------ DUMP BLOCK STAT ------\n\n");
+    while (struct dirent *d = readdir(dirptr.get())) {
+        if ((d->d_name[0] == '.')
+         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+          || (d->d_name[1] == '\0'))) {
+            continue;
+        }
+        const std::string new_path =
+            android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
+        printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
+        dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
+        printf("\n");
+    }
+     return;
+}
+
+static void DumpPacketStats() {
+    DumpFile("NETWORK DEV INFO", "/proc/net/dev");
+    DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
+    DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
+    DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
+    DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
+}
+
+static void DumpIpAddrAndRules() {
+    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
+    RunCommand("NETWORK INTERFACES", {"ip", "link"});
+    RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
+    RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
+    RunCommand("IP RULES", {"ip", "rule", "show"});
+    RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
+}
+
 static void dumpstate() {
     DurationReporter duration_reporter("DUMPSTATE");
 
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     RunCommand("UPTIME", {"uptime"});
-    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
+    DumpBlockStatFiles();
     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
     DumpFile("MEMORY INFO", "/proc/meminfo");
     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
@@ -1010,52 +1107,25 @@
 
     AddAnrTraceFiles();
 
-    int dumped = 0;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        if (tombstone_data[i].fd != -1) {
-            const char *name = tombstone_data[i].name;
-            int fd = tombstone_data[i].fd;
-            dumped = 1;
-            if (ds.IsZipping()) {
-                if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
-                    MYLOGE("Unable to add tombstone %s to zip file\n", name);
-                }
-            } else {
-                dump_file_from_fd("TOMBSTONE", name, fd);
-            }
-            close(fd);
-            tombstone_data[i].fd = -1;
-        }
-    }
-    if (!dumped) {
-        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
+    // NOTE: tombstones are always added as separate entries in the zip archive
+    // and are not interspersed with the main report.
+    const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
+                                            "TOMBSTONE", true /* add_to_zip */);
+    if (!tombstones_dumped) {
+        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
     }
 
-    DumpFile("NETWORK DEV INFO", "/proc/net/dev");
-    DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
-    DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
-    DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
-    DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
+    DumpPacketStats();
 
     DoKmsg();
 
-    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
-
-    RunCommand("NETWORK INTERFACES", {"ip", "link"});
-
-    RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
-    RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
-
-    RunCommand("IP RULES", {"ip", "rule", "show"});
-    RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
+    DumpIpAddrAndRules();
 
     dump_route_tables();
 
     RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
-    RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
-               CommandOptions::WithTimeout(20).Build());
 
     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
                CommandOptions::WithTimeout(10).Build());
@@ -1150,11 +1220,6 @@
     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
 
-    // DumpModemLogs adds the modem logs if available to the bugreport.
-    // Do this at the end to allow for sufficient time for the modem logs to be
-    // collected.
-    DumpModemLogs();
-
     printf("========================================================\n");
     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
@@ -1163,6 +1228,46 @@
     printf("========================================================\n");
 }
 
+// This method collects dumpsys for telephony debugging only
+static void DumpstateTelephonyOnly() {
+    DurationReporter duration_reporter("DUMPSTATE");
+
+    DumpIpTablesAsRoot();
+
+    if (!DropRootUser()) {
+        return;
+    }
+
+    do_dmesg();
+    DoLogcat();
+    DumpPacketStats();
+    DoKmsg();
+    DumpIpAddrAndRules();
+    dump_route_tables();
+
+    RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
+               CommandOptions::WithTimeout(10).Build());
+
+    RunCommand("SYSTEM PROPERTIES", {"getprop"});
+
+    printf("========================================================\n");
+    printf("== Android Framework Services\n");
+    printf("========================================================\n");
+
+    RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
+    RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
+
+    printf("========================================================\n");
+    printf("== Running Application Services\n");
+    printf("========================================================\n");
+
+    RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
+
+    printf("========================================================\n");
+    printf("== dumpstate: done (id %d)\n", ds.id_);
+    printf("========================================================\n");
+}
+
 void Dumpstate::DumpstateBoard() {
     DurationReporter duration_reporter("dumpstate_board()");
     printf("========================================================\n");
@@ -1180,23 +1285,35 @@
         return;
     }
 
-    std::string path = kDumpstateBoardPath;
-    MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path.c_str());
+    std::string path[NUM_OF_DUMPS];
+    android::base::unique_fd fd[NUM_OF_DUMPS];
+    int numFds = 0;
 
-    int fd =
-        TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
-                                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
-    if (fd < 0) {
-        MYLOGE("Could not open file %s: %s\n", path.c_str(), strerror(errno));
-        return;
+    for (int i = 0; i < NUM_OF_DUMPS; i++) {
+        path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
+        MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
+
+        fd[i] = android::base::unique_fd(
+            TEMP_FAILURE_RETRY(open(path[i].c_str(),
+            O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+            S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
+        if (fd[i] < 0) {
+            MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
+            return;
+        } else {
+            numFds++;
+        }
     }
 
-    native_handle_t* handle = native_handle_create(1, 0);
+    native_handle_t *handle = native_handle_create(numFds, 0);
     if (handle == nullptr) {
         MYLOGE("Could not create native_handle\n");
         return;
     }
-    handle->data[0] = fd;
+
+    for (int i = 0; i < numFds; i++) {
+        handle->data[i] = fd[i].release();
+    }
 
     // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
     android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
@@ -1207,14 +1324,26 @@
         return;
     }
 
-    AddZipEntry("dumpstate-board.txt", path);
+    for (int i = 0; i < numFds; i++) {
+        struct stat s;
+        if (fstat(handle->data[i], &s) == -1) {
+            MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
+        } else if (s.st_size > 0) {
+            AddZipEntry(kDumpstateBoardFiles[i], path[i]);
+        } else {
+            MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
+        }
+    }
+
     printf("*** See dumpstate-board.txt entry ***\n");
 
     native_handle_close(handle);
     native_handle_delete(handle);
 
-    if (remove(path.c_str()) != 0) {
-        MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
+    for (int i = 0; i < numFds; i++) {
+        if (remove(path[i].c_str()) != 0) {
+            MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
+        }
     }
 }
 
@@ -1676,15 +1805,8 @@
     ds.PrintHeader();
 
     if (telephony_only) {
-        DumpIpTables();
-        if (!DropRootUser()) {
-            return -1;
-        }
-        do_dmesg();
-        DoLogcat();
-        DoKmsg();
+        DumpstateTelephonyOnly();
         ds.DumpstateBoard();
-        DumpModemLogs();
     } else {
         // Dumps systrace right away, otherwise it will be filled with unnecessary events.
         // First try to dump anrd trace if the daemon is running. Otherwise, dump
@@ -1707,7 +1829,9 @@
         dump_traces_path = dump_traces();
 
         /* Run some operations that require root. */
-        get_tombstone_fds(tombstone_data);
+        tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
+        anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
+
         ds.AddDir(RECOVERY_DIR, true);
         ds.AddDir(RECOVERY_DATA_DIR, true);
         ds.AddDir(LOGPERSIST_DATA_DIR, false);
@@ -1716,7 +1840,7 @@
             ds.AddDir(PROFILE_DATA_DIR_REF, true);
         }
         add_mountinfo();
-        DumpIpTables();
+        DumpIpTablesAsRoot();
 
         // Capture any IPSec policies in play.  No keys are exposed here.
         RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index f02303b..7757c1e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -26,10 +26,11 @@
 #include <vector>
 
 #include <android-base/macros.h>
+#include <android/os/IDumpstateListener.h>
+#include <utils/StrongPointer.h>
 #include <ziparchive/zip_writer.h>
 
 #include "DumpstateUtil.h"
-#include "android/os/BnDumpstate.h"
 
 // Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
 // std::vector<std::string>
@@ -49,6 +50,8 @@
 }  // namespace os
 }  // namespace android
 
+class ZipWriter;
+
 // TODO: remove once moved to HAL
 #ifdef __cplusplus
 extern "C" {
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 1c19268..a94cf99 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -94,7 +94,7 @@
   protected:
     const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
     const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
-    const std::string kTestDataPath = kFixturesPath + "/testdata/";
+    const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
     const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
     const std::string kEchoCommand = "/system/bin/echo";
 
diff --git a/cmds/dumpstate/testdata/empty-file.txt b/cmds/dumpstate/tests/testdata/empty-file.txt
similarity index 100%
rename from cmds/dumpstate/testdata/empty-file.txt
rename to cmds/dumpstate/tests/testdata/empty-file.txt
diff --git a/cmds/dumpstate/testdata/multiple-lines-with-newline.txt b/cmds/dumpstate/tests/testdata/multiple-lines-with-newline.txt
similarity index 100%
rename from cmds/dumpstate/testdata/multiple-lines-with-newline.txt
rename to cmds/dumpstate/tests/testdata/multiple-lines-with-newline.txt
diff --git a/cmds/dumpstate/testdata/multiple-lines.txt b/cmds/dumpstate/tests/testdata/multiple-lines.txt
similarity index 100%
rename from cmds/dumpstate/testdata/multiple-lines.txt
rename to cmds/dumpstate/tests/testdata/multiple-lines.txt
diff --git a/cmds/dumpstate/testdata/single-line-with-newline.txt b/cmds/dumpstate/tests/testdata/single-line-with-newline.txt
similarity index 100%
rename from cmds/dumpstate/testdata/single-line-with-newline.txt
rename to cmds/dumpstate/tests/testdata/single-line-with-newline.txt
diff --git a/cmds/dumpstate/testdata/single-line.txt b/cmds/dumpstate/tests/testdata/single-line.txt
similarity index 100%
rename from cmds/dumpstate/testdata/single-line.txt
rename to cmds/dumpstate/tests/testdata/single-line.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-1st-NAN.txt b/cmds/dumpstate/tests/testdata/stats-invalid-1st-NAN.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-1st-NAN.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-1st-NAN.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-1st-negative.txt b/cmds/dumpstate/tests/testdata/stats-invalid-1st-negative.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-1st-negative.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-1st-negative.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-1st-too-big.txt b/cmds/dumpstate/tests/testdata/stats-invalid-1st-too-big.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-1st-too-big.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-1st-too-big.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-2nd-NAN.txt b/cmds/dumpstate/tests/testdata/stats-invalid-2nd-NAN.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-2nd-NAN.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-2nd-NAN.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-2nd-negative.txt b/cmds/dumpstate/tests/testdata/stats-invalid-2nd-negative.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-2nd-negative.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-2nd-negative.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-2nd-too-big.txt b/cmds/dumpstate/tests/testdata/stats-invalid-2nd-too-big.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-2nd-too-big.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-2nd-too-big.txt
diff --git a/cmds/dumpstate/testdata/stats-invalid-both-NAN.txt b/cmds/dumpstate/tests/testdata/stats-invalid-both-NAN.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-invalid-both-NAN.txt
rename to cmds/dumpstate/tests/testdata/stats-invalid-both-NAN.txt
diff --git a/cmds/dumpstate/testdata/stats-one-run-no-newline.txt b/cmds/dumpstate/tests/testdata/stats-one-run-no-newline.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-one-run-no-newline.txt
rename to cmds/dumpstate/tests/testdata/stats-one-run-no-newline.txt
diff --git a/cmds/dumpstate/testdata/stats-two-runs.txt b/cmds/dumpstate/tests/testdata/stats-two-runs.txt
similarity index 100%
rename from cmds/dumpstate/testdata/stats-two-runs.txt
rename to cmds/dumpstate/tests/testdata/stats-two-runs.txt
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index eefdcbd..93f4c22 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -38,6 +38,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -46,6 +47,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android-base/unique_fd.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
@@ -96,8 +98,9 @@
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
         "android.hardware.graphics.composer@2.1::IComposer",
-        "android.hardware.vr@1.0::IVr",
         "android.hardware.media.omx@1.0::IOmx",
+        "android.hardware.sensors@1.0::ISensors",
+        "android.hardware.vr@1.0::IVr",
         NULL,
 };
 
@@ -853,15 +856,143 @@
     return pids; // whether it was okay or not
 }
 
+const char* DumpTraces(const std::string& traces_path);
+const char* DumpTracesTombstoned(const std::string& traces_dir);
+
 /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
 const char *dump_traces() {
     DurationReporter duration_reporter("DUMP TRACES");
 
-    const char* result = nullptr;
+    const std::string traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+    if (!traces_dir.empty()) {
+        return DumpTracesTombstoned(traces_dir);
+    }
 
-    std::string traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
-    if (traces_path.empty()) return nullptr;
+    const std::string traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+    if (!traces_file.empty()) {
+        return DumpTraces(traces_file);
+    }
 
+    return nullptr;
+}
+
+static 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);
+}
+
+const char* DumpTracesTombstoned(const std::string& traces_dir) {
+    const std::string temp_file_pattern = traces_dir + "/dumptrace_XXXXXX";
+
+    const size_t buf_size = temp_file_pattern.length() + 1;
+    std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
+    memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
+
+    // Create a new, empty file to receive all trace dumps.
+    //
+    // TODO: This can be simplified once we remove support for the old style
+    // dumps. We can have a file descriptor passed in to dump_traces instead
+    // of creating a file, closing it and then reopening it again.
+    android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
+    if (fd < 0) {
+        MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    // Nobody should have access to this temporary file except dumpstate, but we
+    // temporarily grant 'read' to 'others' here because this file is created
+    // when tombstoned is still running as root, but dumped after dropping. This
+    // can go away once support for old style dumping has.
+    const int chmod_ret = fchmod(fd, 0666);
+    if (chmod_ret < 0) {
+        MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+    if (proc.get() == nullptr) {
+        MYLOGE("opendir /proc failed: %s\n", strerror(errno));
+        return nullptr;
+    }
+
+    // Number of times process dumping has timed out. If we encounter too many
+    // failures, we'll give up.
+    int timeout_failures = 0;
+    bool dalvik_found = false;
+
+    const std::set<int> hal_pids = get_interesting_hal_pids();
+
+    struct dirent* d;
+    while ((d = readdir(proc.get()))) {
+        int pid = atoi(d->d_name);
+        if (pid <= 0) {
+            continue;
+        }
+
+        const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+        std::string exe;
+        if (!android::base::Readlink(link_name, &exe)) {
+            continue;
+        }
+
+        bool is_java_process;
+        if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+            // Don't bother dumping backtraces for the zygote.
+            if (IsZygote(pid)) {
+                continue;
+            }
+
+            dalvik_found = true;
+            is_java_process = true;
+        } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
+            is_java_process = false;
+        } else {
+            // Probably a native process we don't care about, continue.
+            continue;
+        }
+
+        // If 3 backtrace dumps fail in a row, consider debuggerd dead.
+        if (timeout_failures == 3) {
+            dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
+            break;
+        }
+
+        const uint64_t start = Nanotime();
+        const int ret = dump_backtrace_to_file_timeout(
+            pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+            is_java_process ? 5 : 20, fd);
+
+        if (ret == -1) {
+            dprintf(fd, "dumping failed, likely due to a timeout\n");
+            timeout_failures++;
+            continue;
+        }
+
+        // We've successfully dumped stack traces, reset the failure count
+        // and write a summary of the elapsed time to the file and continue with the
+        // next process.
+        timeout_failures = 0;
+
+        dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
+                pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
+    }
+
+    if (!dalvik_found) {
+        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+    }
+
+    return file_name_buf.release();
+}
+
+const char* DumpTraces(const std::string& traces_path) {
+    const char* result = NULL;
     /* move the old traces.txt (if any) out of the way temporarily */
     std::string anrtraces_path = traces_path + ".anr";
     if (rename(traces_path.c_str(), anrtraces_path.c_str()) && errno != ENOENT) {
@@ -974,7 +1105,8 @@
                 /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
                 if (timeout_failures == 3) {
                     dprintf(fd, "too many stack dump failures, skipping...\n");
-                } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
+                } else if (dump_backtrace_to_file_timeout(
+                        pid, kDebuggerdNativeBacktrace, 20, fd) == -1) {
                     dprintf(fd, "dumping failed, likely due to a timeout\n");
                     timeout_failures++;
                 } else {
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index f0e7200..fa6f6df 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -16,6 +16,7 @@
 
 #include <algorithm>
 #include <chrono>
+#include <iomanip>
 #include <thread>
 
 #include <android-base/file.h>
@@ -282,7 +283,14 @@
               std::chrono::duration<double> elapsed_seconds =
                   std::chrono::steady_clock::now() - start;
               aout << StringPrintf("--------- %.3fs ", elapsed_seconds.count()).c_str()
-                   << "was the duration of dumpsys " << service_name << endl;
+                   << "was the duration of dumpsys " << service_name;
+
+              using std::chrono::system_clock;
+              const auto finish = system_clock::to_time_t(system_clock::now());
+              std::tm finish_tm;
+              localtime_r(&finish, &finish_tm);
+              aout << ", ending at: " << std::put_time(&finish_tm, "%Y-%m-%d %H:%M:%S")
+                   << endl;
             }
         } else {
             aerr << "Can't find service: " << service_name << endl;
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index 7698ed5..127e0f3 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -1,6 +1,7 @@
 // Build the unit tests for dumpsys
 cc_test {
     name: "dumpsys_test",
+    test_suites: ["device-tests"],
 
     srcs: ["dumpsys_test.cpp"],
 
diff --git a/cmds/dumpsys/tests/AndroidTest.xml b/cmds/dumpsys/tests/AndroidTest.xml
new file mode 100644
index 0000000..1a8c67f
--- /dev/null
+++ b/cmds/dumpsys/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for dumpsys_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="dumpsys_test->/data/local/tmp/dumpsys_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="dumpsys_test" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 66beb6d..cfd53e5 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -35,6 +35,7 @@
 using ::testing::Eq;
 using ::testing::HasSubstr;
 using ::testing::MakeAction;
+using ::testing::Mock;
 using ::testing::Not;
 using ::testing::Return;
 using ::testing::StrEq;
@@ -155,10 +156,11 @@
             .WillRepeatedly(DoAll(WithArg<0>(WriteOnFd(output)), Return(0)));
     }
 
-    void ExpectDumpAndHang(const char* name, int timeout_s, const std::string& output) {
+    sp<BinderMock> ExpectDumpAndHang(const char* name, int timeout_s, const std::string& output) {
         sp<BinderMock> binder_mock = ExpectCheckService(name);
         EXPECT_CALL(*binder_mock, dump(_, _))
             .WillRepeatedly(DoAll(Sleep(timeout_s), WithArg<0>(WriteOnFd(output)), Return(0)));
+        return binder_mock;
     }
 
     void CallMain(const std::vector<std::string>& args) {
@@ -245,15 +247,15 @@
 
 // Tests 'dumpsys -t 1 service_name' on a service that times out after 2s
 TEST_F(DumpsysTest, DumpRunningServiceTimeout) {
-    ExpectDumpAndHang("Valet", 2, "Here's your car");
+    sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car");
 
     CallMain({"-t", "1", "Valet"});
 
     AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1s) EXPIRED");
     AssertNotDumped("Here's your car");
 
-    // Must wait so binder mock is deleted, otherwise test will fail with a leaked object
-    sleep(1);
+    // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp
+    Mock::AllowLeak(binder_mock.get());
 }
 
 // Tests 'dumpsys service_name Y U NO HAVE ARGS' on a service that is running
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index e293948..3eb39b9 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -148,6 +148,7 @@
         }
 
         // Bubble up modified time to parent
+        CHECK(p != nullptr);
         switch (p->fts_info) {
         case FTS_DP:
         case FTS_DEFAULT:
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 60c89a9..8a79ee1 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -311,6 +311,7 @@
         return -1;
     }
 
+#if APPLY_HARD_QUOTAS
     if ((dq.dqb_bhardlimit == 0) || (dq.dqb_ihardlimit == 0)) {
         auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
         struct statvfs stat;
@@ -320,7 +321,8 @@
         }
 
         dq.dqb_valid = QIF_LIMITS;
-        dq.dqb_bhardlimit = (((stat.f_blocks * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
+        dq.dqb_bhardlimit =
+            (((static_cast<uint64_t>(stat.f_blocks) * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
         dq.dqb_ihardlimit = (stat.f_files / 2);
         if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), device.c_str(), uid,
                 reinterpret_cast<char*>(&dq)) != 0) {
@@ -334,6 +336,10 @@
         // Hard quota already set; assume it's reasonable
         return 0;
     }
+#else
+    // Hard quotas disabled
+    return 0;
+#endif
 }
 
 binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
@@ -1641,6 +1647,7 @@
     int64_t videoSize = 0;
     int64_t imageSize = 0;
     int64_t appSize = 0;
+    int64_t obbSize = 0;
 
     auto device = findQuotaDeviceForUuid(uuid);
     if (device.empty()) {
@@ -1688,6 +1695,13 @@
 #endif
             imageSize = dq.dqb_curspace;
         }
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), AID_MEDIA_OBB,
+                reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+            LOG(DEBUG) << "quotactl() for GID " << AID_MEDIA_OBB << " " << dq.dqb_curspace;
+#endif
+            obbSize = dq.dqb_curspace;
+        }
         ATRACE_END();
 
         ATRACE_BEGIN("apps");
@@ -1744,6 +1758,11 @@
         }
         fts_close(fts);
         ATRACE_END();
+
+        ATRACE_BEGIN("obb");
+        auto obbPath = create_data_media_obb_path(uuid_, "");
+        calculate_tree_size(obbPath, &obbSize);
+        ATRACE_END();
     }
 
     std::vector<int64_t> ret;
@@ -1752,6 +1771,7 @@
     ret.push_back(videoSize);
     ret.push_back(imageSize);
     ret.push_back(appSize);
+    ret.push_back(obbSize);
 #if MEASURE_DEBUG
     LOG(DEBUG) << "Final result " << toString(ret);
 #endif
@@ -1786,6 +1806,16 @@
     return ok();
 }
 
+// Copy the contents of a system profile over the data profile.
+binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
+        int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+    std::lock_guard<std::recursive_mutex> lock(mLock);
+    *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName);
+    return ok();
+}
+
 // TODO: Consider returning error codes.
 binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
         bool* _aidl_return) {
@@ -1801,8 +1831,8 @@
         const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
         int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
         const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
-        const std::unique_ptr<std::string>& sharedLibraries,
-        const std::unique_ptr<std::string>& seInfo) {
+        const std::unique_ptr<std::string>& classLoaderContext,
+        const std::unique_ptr<std::string>& seInfo, bool downgrade) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     if (packageName && *packageName != "*") {
@@ -1816,10 +1846,11 @@
     const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
     const char* compiler_filter = compilerFilter.c_str();
     const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
-    const char* shared_libraries = sharedLibraries ? sharedLibraries->c_str() : nullptr;
+    const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr;
     const char* se_info = seInfo ? seInfo->c_str() : nullptr;
     int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
-            oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries, se_info);
+            oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
+            downgrade);
     return res ? error(res, "Failed to dexopt") : ok();
 }
 
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 4011315..c8db3df 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -83,14 +83,16 @@
             const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
             int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
             const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
-            const std::unique_ptr<std::string>& sharedLibraries,
-            const std::unique_ptr<std::string>& seInfo);
+            const std::unique_ptr<std::string>& classLoaderContext,
+            const std::unique_ptr<std::string>& seInfo, bool downgrade);
 
     binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
 
     binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
     binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
             const std::string& codePaths, bool* _aidl_return);
+    binder::Status copySystemProfile(const std::string& systemProfile,
+            int32_t uid, const std::string& packageName, bool* _aidl_return);
     binder::Status clearAppProfiles(const std::string& packageName);
     binder::Status destroyAppProfiles(const std::string& packageName);
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index f09a397..452a2b1 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -51,12 +51,14 @@
             @nullable @utf8InCpp String outputPath, int dexFlags,
             @utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
             @nullable @utf8InCpp String sharedLibraries,
-            @nullable @utf8InCpp String seInfo);
+            @nullable @utf8InCpp String seInfo, boolean downgrade);
 
     void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
 
     boolean mergeProfiles(int uid, @utf8InCpp String packageName);
     boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
+    boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
+            @utf8InCpp String packageName);
     void clearAppProfiles(@utf8InCpp String packageName);
     void destroyAppProfiles(@utf8InCpp String packageName);
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 70cf35c..f29da17 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -191,7 +191,7 @@
 static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
         const char* input_file_name, const char* output_file_name, int swap_fd,
         const char* instruction_set, const char* compiler_filter,
-        bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
+        bool debuggable, bool post_bootcomplete, int profile_fd, const char* class_loader_context) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -291,6 +291,12 @@
     char dex2oat_swap_fd[arraysize("--swap-fd=") + MAX_INT_LEN];
     bool have_dex2oat_image_fd = false;
     char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
+    size_t class_loader_context_size = arraysize("--class-loader-context=") + PKG_PATH_MAX;
+    char class_loader_context_arg[class_loader_context_size];
+    if (class_loader_context != nullptr) {
+        snprintf(class_loader_context_arg, class_loader_context_size, "--class-loader-context=%s",
+            class_loader_context);
+    }
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
@@ -387,7 +393,7 @@
                      + (have_app_image_format ? 1 : 0)
                      + dex2oat_flags_count
                      + (profile_fd == -1 ? 0 : 1)
-                     + (shared_libraries != nullptr ? 4 : 0)
+                     + (class_loader_context != nullptr ? 1 : 0)
                      + (has_base_dir ? 1 : 0)
                      + (have_dex2oat_large_app_threshold ? 1 : 0)];
     int i = 0;
@@ -447,15 +453,13 @@
     if (profile_fd != -1) {
         argv[i++] = profile_arg;
     }
-    if (shared_libraries != nullptr) {
-        argv[i++] = RUNTIME_ARG;
-        argv[i++] = "-classpath";
-        argv[i++] = RUNTIME_ARG;
-        argv[i++] = shared_libraries;
-    }
     if (has_base_dir) {
         argv[i++] = base_dir;
     }
+    if (class_loader_context != nullptr) {
+        argv[i++] = class_loader_context_arg;
+    }
+
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -847,6 +851,70 @@
     return true;
 }
 
+bool copy_system_profile(const std::string& system_profile,
+        uid_t packageUid, const std::string& data_profile_location) {
+    unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
+    unique_fd out_fd(open_reference_profile(packageUid,
+                     data_profile_location,
+                     /*read_write*/ true,
+                     /*secondary*/ false));
+    if (in_fd.get() < 0) {
+        PLOG(WARNING) << "Could not open profile " << system_profile;
+        return false;
+    }
+    if (out_fd.get() < 0) {
+        PLOG(WARNING) << "Could not open profile " << data_profile_location;
+        return false;
+    }
+
+    // As a security measure we want to write the profile information with the reduced capabilities
+    // of the package user id. So we fork and drop capabilities in the child.
+    pid_t pid = fork();
+    if (pid == 0) {
+        /* child -- drop privileges before continuing */
+        drop_capabilities(packageUid);
+
+        if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
+            if (errno != EWOULDBLOCK) {
+                PLOG(WARNING) << "Error locking profile " << data_profile_location;
+            }
+            // This implies that the app owning this profile is running
+            // (and has acquired the lock).
+            //
+            // The app never acquires the lock for the reference profiles of primary apks.
+            // Only dex2oat from installd will do that. Since installd is single threaded
+            // we should not see this case. Nevertheless be prepared for it.
+            PLOG(WARNING) << "Failed to flock " << data_profile_location;
+            return false;
+        }
+
+        bool truncated = ftruncate(out_fd.get(), 0) == 0;
+        if (!truncated) {
+            PLOG(WARNING) << "Could not truncate " << data_profile_location;
+        }
+
+        // Copy over data.
+        static constexpr size_t kBufferSize = 4 * 1024;
+        char buffer[kBufferSize];
+        while (true) {
+            ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
+            if (bytes == 0) {
+                break;
+            }
+            write(out_fd.get(), buffer, bytes);
+        }
+        if (flock(out_fd.get(), LOCK_UN) != 0) {
+            PLOG(WARNING) << "Error unlocking profile " << data_profile_location;
+        }
+        // Use _exit since we don't want to run the global destructors in the child.
+        // b/62597429
+        _exit(0);
+    }
+    /* parent */
+    int return_code = wait_child(pid);
+    return return_code == 0;
+}
+
 static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
   // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
   if (EndsWith(oat_path, ".dex")) {
@@ -926,14 +994,22 @@
   return oat_dir == nullptr || oat_dir[0] == '!';
 }
 
+// Best-effort check whether we can fit the the path into our buffers.
+// Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
+// without a swap file, if necessary. Reference profiles file also add an extra ".prof"
+// extension to the cache path (5 bytes).
+// TODO(calin): move away from char* buffers and PKG_PATH_MAX.
+static bool validate_dex_path_size(const std::string& dex_path) {
+    if (dex_path.size() >= (PKG_PATH_MAX - 8)) {
+        LOG(ERROR) << "dex_path too long: " << dex_path;
+        return false;
+    }
+    return true;
+}
+
 static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
             const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
-    // Early best-effort check whether we can fit the the path into our buffers.
-    // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
-    // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
-    // extension to the cache path (5 bytes).
-    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
-        ALOGE("apk_path too long '%s'\n", apk_path);
+    if (!validate_dex_path_size(apk_path)) {
         return false;
     }
 
@@ -1061,10 +1137,9 @@
 // (re)Creates the app image if needed.
 Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
         bool is_public, int uid, bool is_secondary_dex) {
-    // Use app images only if it is enabled (by a set image format) and we are compiling
-    // profile-guided (so the app image doesn't conservatively contain all classes).
-    // Note that we don't create an image for secondary dex files.
-    if (is_secondary_dex || !profile_guided) {
+
+    // We don't create an image for secondary dex files.
+    if (is_secondary_dex) {
         return Dex2oatFileWrapper();
     }
 
@@ -1073,6 +1148,14 @@
         // Happens when the out_oat_path has an unknown extension.
         return Dex2oatFileWrapper();
     }
+
+    // Use app images only if it is enabled (by a set image format) and we are compiling
+    // profile-guided (so the app image doesn't conservatively contain all classes).
+    if (!profile_guided) {
+        // In case there is a stale image, remove it now. Ignore any error.
+        unlink(image_path.c_str());
+        return Dex2oatFileWrapper();
+    }
     char app_image_format[kPropertyValueMax];
     bool have_app_image_format =
             get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
@@ -1286,36 +1369,39 @@
 // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
 // If this is for a profile guided compilation, profile_was_updated will tell whether or not
 // the profile has changed.
-static void exec_dexoptanalyzer(const std::string& dex_file, const char* instruction_set,
-        const char* compiler_filter, bool profile_was_updated) {
+static void exec_dexoptanalyzer(const std::string& dex_file, const std::string& instruction_set,
+        const std::string& compiler_filter, bool profile_was_updated, bool downgrade) {
     static const char* DEXOPTANALYZER_BIN = "/system/bin/dexoptanalyzer";
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
-    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
-        ALOGE("Instruction set %s longer than max length of %d",
-              instruction_set, MAX_INSTRUCTION_SET_LEN);
+    if (instruction_set.size() >= MAX_INSTRUCTION_SET_LEN) {
+        LOG(ERROR) << "Instruction set " << instruction_set
+                << " longer than max length of " << MAX_INSTRUCTION_SET_LEN;
         return;
     }
 
-    char dex_file_arg[strlen("--dex-file=") + PKG_PATH_MAX];
-    char isa_arg[strlen("--isa=") + MAX_INSTRUCTION_SET_LEN];
-    char compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
+    std::string dex_file_arg = "--dex-file=" + dex_file;
+    std::string isa_arg = "--isa=" + instruction_set;
+    std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
     const char* assume_profile_changed = "--assume-profile-changed";
-
-    sprintf(dex_file_arg, "--dex-file=%s", dex_file.c_str());
-    sprintf(isa_arg, "--isa=%s", instruction_set);
-    sprintf(compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
+    const char* downgrade_flag = "--downgrade";
 
     // program name, dex file, isa, filter, the final NULL
-    const char* argv[5 + (profile_was_updated ? 1 : 0)];
+    const int argc = 5 +
+        (profile_was_updated ? 1 : 0) +
+        (downgrade ? 1 : 0);
+    const char* argv[argc];
     int i = 0;
     argv[i++] = DEXOPTANALYZER_BIN;
-    argv[i++] = dex_file_arg;
-    argv[i++] = isa_arg;
-    argv[i++] = compiler_filter_arg;
+    argv[i++] = dex_file_arg.c_str();
+    argv[i++] = isa_arg.c_str();
+    argv[i++] = compiler_filter_arg.c_str();
     if (profile_was_updated) {
         argv[i++] = assume_profile_changed;
     }
+    if (downgrade) {
+        argv[i++] = downgrade_flag;
+    }
     argv[i] = NULL;
 
     execv(DEXOPTANALYZER_BIN, (char * const *)argv);
@@ -1396,7 +1482,7 @@
 static bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
         int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
         const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
-        std::string* oat_dir_out, std::string* dex_path_out) {
+        std::string* oat_dir_out, std::string* dex_path_out, bool downgrade) {
     int storage_flag;
 
     if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
@@ -1426,6 +1512,9 @@
         }
     }
     const std::string& dex_path = *dex_path_out;
+    if (!validate_dex_path_size(dex_path)) {
+        return false;
+    }
     if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
         LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
         return false;
@@ -1462,7 +1551,8 @@
         // child -- drop privileges before continuing.
         drop_capabilities(uid);
         // Run dexoptanalyzer to get dexopt_needed code.
-        exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter, profile_was_updated);
+        exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter, profile_was_updated,
+                            downgrade);
         exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
     }
 
@@ -1489,13 +1579,23 @@
 
 int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-        const char* volume_uuid, const char* shared_libraries, const char* se_info) {
+        const char* volume_uuid, const char* class_loader_context, const char* se_info,
+        bool downgrade) {
     CHECK(pkgname != nullptr);
     CHECK(pkgname[0] != 0);
     if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
         LOG_FATAL("dexopt flags contains unknown fields\n");
     }
 
+    if (!validate_dex_path_size(dex_path)) {
+        return -1;
+    }
+
+    if (class_loader_context != nullptr && strlen(class_loader_context) > PKG_PATH_MAX) {
+        LOG(ERROR) << "Class loader context exceeds the allowed size: " << class_loader_context;
+        return -1;
+    }
+
     bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
@@ -1508,7 +1608,8 @@
     if (is_secondary_dex) {
         if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
                 instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
-                &dex_real_path)) {
+                &dex_real_path,
+                downgrade)) {
             oat_dir = oat_dir_str.c_str();
             dex_path = dex_real_path.c_str();
             if (dexopt_needed == NO_DEXOPT_NEEDED) {
@@ -1597,7 +1698,7 @@
                     debuggable,
                     boot_complete,
                     reference_profile_fd.get(),
-                    shared_libraries);
+                    class_loader_context);
         _exit(68);   /* only get here on exec failure */
     } else {
         int res = wait_child(pid);
@@ -1685,14 +1786,24 @@
         /*out*/bool* out_secondary_dex_exists) {
     // Set out to false to start with, just in case we have validation errors.
     *out_secondary_dex_exists = false;
+    if (!validate_dex_path_size(dex_path)) {
+        return false;
+    }
+
     if (isas.size() == 0) {
         LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
         return false;
     }
 
     const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+
+    // Note that we cannot validate the package path here because the file might not exist
+    // and we cannot call realpath to resolve system symlinks. Since /data/user/0 symlinks to
+    // /data/data/ a lot of validations will fail if we attempt to check the package path.
+    // It is still ok to be more relaxed because any file removal is done after forking and
+    // dropping capabilities.
     if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
-            uid, storage_flag)) {
+            uid, storage_flag, /*validate_package_path*/ false)) {
         LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
         return false;
     }
@@ -1706,37 +1817,56 @@
         return false;
     }
 
-    // The secondary dex does not exist anymore. Clear any generated files.
-    char oat_path[PKG_PATH_MAX];
-    char oat_dir[PKG_PATH_MAX];
-    char oat_isa_dir[PKG_PATH_MAX];
-    bool result = true;
-    for (size_t i = 0; i < isas.size(); i++) {
-        if (!create_secondary_dex_oat_layout(dex_path, isas[i], oat_dir, oat_isa_dir, oat_path)) {
-            LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
-            result = false;
-            continue;
-        }
+    // As a security measure we want to unlink art artifacts with the reduced capabilities
+    // of the package user id. So we fork and drop capabilities in the child.
+    pid_t pid = fork();
+    if (pid == 0) {
+        // The secondary dex does not exist anymore. Clear any generated files.
+        char oat_path[PKG_PATH_MAX];
+        char oat_dir[PKG_PATH_MAX];
+        char oat_isa_dir[PKG_PATH_MAX];
+        bool result = true;
+        /* child -- drop privileges before continuing */
+        drop_capabilities(uid);
+        for (size_t i = 0; i < isas.size(); i++) {
+            if (!create_secondary_dex_oat_layout(dex_path,
+                                                 isas[i],
+                                                 oat_dir,
+                                                 oat_isa_dir,
+                                                 oat_path)) {
+                LOG(ERROR) << "Could not create secondary odex layout: "
+                           << dex_path;
+                result = false;
+                continue;
+            }
 
-        // Delete oat/vdex/art files.
-        result = unlink_if_exists(oat_path) && result;
-        result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
-        result = unlink_if_exists(create_image_filename(oat_path)) && result;
+            // Delete oat/vdex/art files.
+            result = unlink_if_exists(oat_path) && result;
+            result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
+            result = unlink_if_exists(create_image_filename(oat_path)) && result;
 
-        // Delete profiles.
-        std::string current_profile = create_current_profile_path(
+            // Delete profiles.
+            std::string current_profile = create_current_profile_path(
                 multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
-        std::string reference_profile = create_reference_profile_path(
+            std::string reference_profile = create_reference_profile_path(
                 dex_path, /*is_secondary*/true);
-        result = unlink_if_exists(current_profile) && result;
-        result = unlink_if_exists(reference_profile) && result;
+            result = unlink_if_exists(current_profile) && result;
+            result = unlink_if_exists(reference_profile) && result;
 
-        // Try removing the directories as well, they might be empty.
-        result = rmdir_if_empty(oat_isa_dir) && result;
-        result = rmdir_if_empty(oat_dir) && result;
+            // We upgraded once the location of current profile for secondary dex files.
+            // Check for any previous left-overs and remove them as well.
+            std::string old_current_profile = dex_path + ".prof";
+            result = unlink_if_exists(old_current_profile);
+
+            // Try removing the directories as well, they might be empty.
+            result = rmdir_if_empty(oat_isa_dir) && result;
+            result = rmdir_if_empty(oat_dir) && result;
+        }
+        result ? _exit(0) : _exit(1);
     }
 
-    return result;
+    int return_code = wait_child(pid);
+    return return_code == 0;
 }
 
 // Helper for move_ab, so that we can have common failure-case cleanup.
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 355adb1..23446da 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -30,7 +30,6 @@
 static constexpr int DEX2OAT_FOR_BOOT_IMAGE      = 2;
 static constexpr int DEX2OAT_FOR_FILTER          = 3;
 static constexpr int DEX2OAT_FOR_RELOCATION      = 4;
-static constexpr int PATCHOAT_FOR_RELOCATION     = 5;
 
 // Clear the reference profile for the primary apk of the given package.
 bool clear_primary_reference_profile(const std::string& pkgname);
@@ -51,6 +50,10 @@
 
 bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
 
+bool copy_system_profile(const std::string& system_profile,
+                         uid_t packageUid,
+                         const std::string& data_profile_location);
+
 bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
 
 bool reconcile_secondary_dex_file(const std::string& dex_path,
@@ -60,7 +63,8 @@
 
 int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
-        const char* volume_uuid, const char* shared_libraries, const char* se_info);
+        const char* volume_uuid, const char* class_loader_context, const char* se_info,
+        bool downgrade);
 
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index 6a81cfc..2597c79 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -31,7 +31,7 @@
 constexpr const char* DALVIK_CACHE_POSTFIX = "@classes.dex";
 
 constexpr size_t PKG_NAME_MAX = 128u;   /* largest allowed package name */
-constexpr size_t PKG_PATH_MAX = 256u;   /* max size of any path we use */
+constexpr size_t PKG_PATH_MAX = 1024u;  /* max size of any path we use */
 
 /****************************************************************************
  * IMPORTANT: These values are passed from Java code. Keep them in sync with
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 68cb0d7..09e1a00 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -178,6 +178,7 @@
         const char* volume_uuid;
         const char* shared_libraries;
         const char* se_info;
+        bool downgrade;
     };
 
     bool ReadSystemProperties() {
@@ -281,6 +282,13 @@
         return true;
     }
 
+    bool ParseBool(const char* in) {
+        if (strcmp(in, "true") == 0) {
+            return true;
+        }
+        return false;
+    }
+
     bool ParseUInt(const char* in, uint32_t* out) {
         char* end;
         long long int result = strtoll(in, &end, 0);
@@ -349,6 +357,8 @@
         switch (version) {
             case 2:
                 return ReadArgumentsV2(argc, argv, true);
+            case 3:
+                return ReadArgumentsV3(argc, argv);
 
             default:
                 LOG(ERROR) << "Unsupported version " << version;
@@ -427,6 +437,10 @@
             }
         }
 
+        // Set downgrade to false. It is only relevant when downgrading compiler
+        // filter, which is not the case during ota.
+        package_parameters_.downgrade = false;
+
         if (param_index != 11) {
             LOG(ERROR) << "Not enough parameters";
             return false;
@@ -435,6 +449,89 @@
         return true;
     }
 
+    bool ReadArgumentsV3(int argc ATTRIBUTE_UNUSED, char** argv) {
+        size_t dexopt_index = 3;
+
+        // Check for "dexopt".
+        if (argv[dexopt_index] == nullptr) {
+            LOG(ERROR) << "Missing parameters";
+            return false;
+        }
+        if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
+            LOG(ERROR) << "Expected \"dexopt\"";
+            return false;
+        }
+
+        size_t param_index = 0;
+        for (;; ++param_index) {
+            const char* param = argv[dexopt_index + 1 + param_index];
+            if (param == nullptr) {
+                break;
+            }
+
+            switch (param_index) {
+                case 0:
+                    package_parameters_.apk_path = param;
+                    break;
+
+                case 1:
+                    package_parameters_.uid = atoi(param);
+                    break;
+
+                case 2:
+                    package_parameters_.pkgName = param;
+                    break;
+
+                case 3:
+                    package_parameters_.instruction_set = param;
+                    break;
+
+                case 4:
+                    package_parameters_.dexopt_needed = atoi(param);
+                    break;
+
+                case 5:
+                    package_parameters_.oat_dir = param;
+                    break;
+
+                case 6:
+                    package_parameters_.dexopt_flags = atoi(param);
+                    break;
+
+                case 7:
+                    package_parameters_.compiler_filter = param;
+                    break;
+
+                case 8:
+                    package_parameters_.volume_uuid = ParseNull(param);
+                    break;
+
+                case 9:
+                    package_parameters_.shared_libraries = ParseNull(param);
+                    break;
+
+                case 10:
+                    package_parameters_.se_info = ParseNull(param);
+                    break;
+
+                case 11:
+                    package_parameters_.downgrade = ParseBool(param);
+                    break;
+
+                default:
+                    LOG(ERROR) << "Too many arguments, got " << param;
+                    return false;
+            }
+        }
+
+        if (param_index != 12) {
+            LOG(ERROR) << "Not enough parameters";
+            return false;
+        }
+
+        return true;
+    }
+
     static int ReplaceMask(int input, int old_mask, int new_mask) {
         return (input & old_mask) != 0 ? new_mask : 0;
     }
@@ -534,6 +631,10 @@
         // receive from a v1 A side.
         package_parameters_.se_info = nullptr;
 
+        // Set downgrade to false. It is only relevant when downgrading compiler
+        // filter, which is not the case during ota.
+        package_parameters_.downgrade = false;
+
         return true;
     }
 
@@ -753,10 +854,6 @@
     }
 
     static const char* ParseNull(const char* arg) {
-        // b/38186355. Revert soon.
-        if (strcmp(arg, "!null") == 0) {
-            return nullptr;
-        }
         return (strcmp(arg, "!") == 0) ? nullptr : arg;
     }
 
@@ -823,7 +920,8 @@
                       package_parameters_.compiler_filter,
                       package_parameters_.volume_uuid,
                       package_parameters_.shared_libraries,
-                      package_parameters_.se_info);
+                      package_parameters_.se_info,
+                      package_parameters_.downgrade);
     }
 
     int RunPreopt() {
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index aed068c..2d58515 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -99,7 +99,7 @@
 static int64_t free() {
     struct statvfs buf;
     if (!statvfs("/data/local/tmp", &buf)) {
-        return buf.f_bavail * buf.f_frsize;
+        return static_cast<int64_t>(buf.f_bavail) * buf.f_frsize;
     } else {
         PLOG(ERROR) << "Failed to statvfs";
         return -1;
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index dab3236..46ed85f 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -38,16 +38,6 @@
 
 #define TEST_PROFILE_DIR "/data/misc/profiles"
 
-#define REALLY_LONG_APP_NAME "com.example." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-
-#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
-
 namespace android {
 namespace installd {
 
@@ -88,6 +78,14 @@
     virtual void TearDown() {
         free(android_system_dirs.dirs);
     }
+
+    std::string create_too_long_path(const std::string& seed) {
+        std::string result = seed;
+        for (size_t i = seed.size(); i < PKG_PATH_MAX; i++) {
+            result += "a";
+        }
+        return result;
+    }
 };
 
 TEST_F(UtilsTest, IsValidApkPath_BadPrefix) {
@@ -388,17 +386,18 @@
             << "Primary user package directory should be created correctly";
 }
 
+
 TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
     char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
+    std::string really_long_app_name = create_too_long_path("com.example");
+    EXPECT_EQ(-1, create_move_path(path, really_long_app_name.c_str(), "shared_prefs", 0))
             << "Should fail to create move path for primary user";
 }
 
 TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
     char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
+    std::string really_long_leaf_name = create_too_long_path("leaf_");
+    EXPECT_EQ(-1, create_move_path(path, "com.android.test", really_long_leaf_name.c_str(), 0))
             << "Should fail to create move path for primary user";
 }
 
@@ -560,7 +559,7 @@
 }
 
 TEST_F(UtilsTest, CreateSecondaryCurrentProfile) {
-    EXPECT_EQ("/data/user/0/com.example/secondary.dex.prof",
+    EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.cur.prof",
             create_current_profile_path(/*user*/0,
                     "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
 }
@@ -571,5 +570,88 @@
                     "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
 }
 
+static void pass_secondary_dex_validation(const std::string& package_name,
+        const std::string& dex_path, int uid, int storage_flag) {
+    EXPECT_TRUE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+            storage_flag))
+            << dex_path << " should be allowed as a valid secondary dex path";
+}
+
+static void fail_secondary_dex_validation(const std::string& package_name,
+        const std::string& dex_path, int uid, int storage_flag) {
+    EXPECT_FALSE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+            storage_flag))
+            << dex_path << " should not be allowed as a valid secondary dex path";
+}
+
+TEST_F(UtilsTest, ValidateSecondaryDexFilesPath) {
+    std::string package_name = "com.test.app";
+    std::string app_dir_ce_user_0 = "/data/data/" + package_name;
+    std::string app_dir_ce_user_10 = "/data/user/10/" + package_name;
+
+    std::string app_dir_de_user_0 = "/data/user_de/0/" + package_name;
+    std::string app_dir_de_user_10 = "/data/user_de/10/" + package_name;
+
+    EXPECT_EQ(app_dir_ce_user_0,
+            create_data_user_ce_package_path(nullptr, 0, package_name.c_str()));
+    EXPECT_EQ(app_dir_ce_user_10,
+            create_data_user_ce_package_path(nullptr, 10, package_name.c_str()));
+
+    EXPECT_EQ(app_dir_de_user_0,
+            create_data_user_de_package_path(nullptr, 0, package_name.c_str()));
+    EXPECT_EQ(app_dir_de_user_10,
+            create_data_user_de_package_path(nullptr, 10, package_name.c_str()));
+
+    uid_t app_uid_for_user_0 = multiuser_get_uid(/*user_id*/0, /*app_id*/ 1234);
+    uid_t app_uid_for_user_10 = multiuser_get_uid(/*user_id*/10, /*app_id*/ 1234);
+
+    // Standard path for user 0 on CE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/ce0.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+    // Standard path for user 10 on CE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_ce_user_10 + "/ce10.dex", app_uid_for_user_10, FLAG_STORAGE_CE);
+
+    // Standard path for user 0 on DE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_de_user_0 + "/de0.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+    // Standard path for user 10 on DE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_de_user_10 + "/de0.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+    // Dex path for user 0 accessed from user 10.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/path0_from10.dex",
+        app_uid_for_user_10, FLAG_STORAGE_CE);
+
+    // Dex path for CE storage accessed with DE.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/ce_from_de.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+
+    // Dex path for DE storage accessed with CE.
+    fail_secondary_dex_validation(
+        package_name, app_dir_de_user_0 + "/de_from_ce.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+    // Location which does not start with '/'.
+    fail_secondary_dex_validation(
+        package_name, "without_slash.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+    // The dex file is not in the specified package directory.
+    fail_secondary_dex_validation(
+        "another.package", app_dir_ce_user_0 + "/for_another_package.dex",
+        app_uid_for_user_0, FLAG_STORAGE_DE);
+
+    // The dex path contains indirect directories.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/1/../foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/1/./foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+    // Super long path.
+    std::string too_long = create_too_long_path("too_long_");
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_10 + "/" + too_long, app_uid_for_user_10, FLAG_STORAGE_CE);
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index c792082..dd32ac6 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -168,18 +168,19 @@
 
 /**
  * Create the path name for user data for a certain userid.
+ * Keep same implementation as vold to minimize path walking overhead
  */
 std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
     std::string data(create_data_path(volume_uuid));
-    if (volume_uuid == nullptr) {
-        if (userid == 0) {
-            return StringPrintf("%s/data", data.c_str());
-        } else {
-            return StringPrintf("%s/user/%u", data.c_str(), userid);
+    if (volume_uuid == nullptr && userid == 0) {
+        std::string legacy = StringPrintf("%s/data", data.c_str());
+        struct stat sb;
+        if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
+            /* /data/data is dir, return /data/data for legacy system */
+            return legacy;
         }
-    } else {
-        return StringPrintf("%s/user/%u", data.c_str(), userid);
     }
+    return StringPrintf("%s/user/%u", data.c_str(), userid);
 }
 
 /**
@@ -237,13 +238,38 @@
 
 // Keep profile paths in sync with ActivityThread and LoadedApk.
 const std::string PROFILE_EXT = ".prof";
+const std::string CURRENT_PROFILE_EXT = ".cur";
 const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
 
+// Gets the parent directory and the file name for the given secondary dex path.
+// Returns true on success, false on failure (if the dex_path does not have the expected
+// structure).
+static bool get_secondary_dex_location(const std::string& dex_path,
+        std::string* out_dir_name, std::string* out_file_name) {
+   size_t dirIndex = dex_path.rfind('/');
+   if (dirIndex == std::string::npos) {
+        return false;
+   }
+   if (dirIndex == dex_path.size() - 1) {
+        return false;
+   }
+   *out_dir_name = dex_path.substr(0, dirIndex);
+   *out_file_name = dex_path.substr(dirIndex + 1);
+
+   return true;
+}
+
 std::string create_current_profile_path(userid_t user, const std::string& location,
         bool is_secondary_dex) {
     if (is_secondary_dex) {
-        // Secondary dex profiles are stored next to the dex files using .prof extension.
-        return StringPrintf("%s%s", location.c_str(), PROFILE_EXT.c_str());
+        // Secondary dex current profiles are stored next to the dex files under the oat folder.
+        std::string dex_dir;
+        std::string dex_name;
+        CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
+                << "Unexpected dir structure for secondary dex " << location;
+        return StringPrintf("%s/oat/%s%s%s",
+                dex_dir.c_str(), dex_name.c_str(), CURRENT_PROFILE_EXT.c_str(),
+                PROFILE_EXT.c_str());
     } else {
         // Profiles for primary apks are under /data/misc/profiles/cur.
         std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
@@ -254,12 +280,10 @@
 std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
     if (is_secondary_dex) {
         // Secondary dex reference profiles are stored next to the dex files under the oat folder.
-        size_t dirIndex = location.rfind('/');
-        CHECK(dirIndex != std::string::npos)
+        std::string dex_dir;
+        std::string dex_name;
+        CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
                 << "Unexpected dir structure for secondary dex " << location;
-
-        std::string dex_dir = location.substr(0, dirIndex);
-        std::string dex_name = location.substr(dirIndex +1);
         return StringPrintf("%s/oat/%s%s",
                 dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
     } else {
@@ -632,7 +656,7 @@
 int64_t data_disk_free(const std::string& data_path) {
     struct statvfs sfs;
     if (statvfs(data_path.c_str(), &sfs) == 0) {
-        return sfs.f_bavail * sfs.f_frsize;
+        return static_cast<int64_t>(sfs.f_bavail) * sfs.f_frsize;
     } else {
         PLOG(ERROR) << "Couldn't statvfs " << data_path;
         return -1;
@@ -777,24 +801,36 @@
 }
 
 bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
-        const char* volume_uuid, int uid, int storage_flag) {
+        const char* volume_uuid, int uid, int storage_flag, bool validate_package_path) {
     CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
 
-    std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
-        ? create_data_user_ce_package_path(
-                volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
-        : create_data_user_de_package_path(
-                volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
-    dir_rec_t dir;
-    if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) {
-        LOG(WARNING) << "Could not get dir rec for " << app_private_dir;
-        return false;
+    // Empty paths are not allowed.
+    if (dex_path.empty()) { return false; }
+    // First character should always be '/'. No relative paths.
+    if (dex_path[0] != '/') { return false; }
+    // The last character should not be '/'.
+    if (dex_path[dex_path.size() - 1] == '/') { return false; }
+    // There should be no '.' after the directory marker.
+    if (dex_path.find("/.") != std::string::npos) { return false; }
+    // The path should be at most PKG_PATH_MAX long.
+    if (dex_path.size() > PKG_PATH_MAX) { return false; }
+
+    if (validate_package_path) {
+        // If we are asked to validate the package path check that
+        // the dex_path is under the app data directory.
+        std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
+            ? create_data_user_ce_package_path(
+                    volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
+            : create_data_user_de_package_path(
+                    volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
+
+        if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
+            return false;
+        }
     }
-    // Usually secondary dex files have a nested directory structure.
-    // Pick at most 10 subdirectories when validating (arbitrary value).
-    // If the secondary dex file is >10 directory nested then validation will
-    // fail and the file will not be compiled.
-    return validate_path(&dir, dex_path.c_str(), /*max_subdirs*/ 10) == 0;
+
+    // If we got here we have a valid path.
+    return true;
 }
 
 /**
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 070da84..e938042 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -36,6 +36,8 @@
 #define BYPASS_QUOTA 0
 #define BYPASS_SDCARDFS 0
 
+#define APPLY_HARD_QUOTAS 1
+
 namespace android {
 namespace installd {
 
@@ -123,7 +125,7 @@
 
 int validate_system_app_path(const char* path);
 bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
-        const char* volume_uuid, int uid, int storage_flag);
+        const char* volume_uuid, int uid, int storage_flag, bool validate_package_path = true);
 
 int get_path_from_env(dir_rec_t* rec, const char* var);
 
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 38647eb..67b5b46 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -22,7 +22,6 @@
         "libhidltransport",
         "libhidl-gen-utils",
         "libvintf",
-        "android.hidl.manager@1.0",
     ],
     srcs: [
         "DebugCommand.cpp",
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 710b6e4..7c6cfd9 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -73,46 +73,92 @@
     }), pids->end());
 }
 
-bool ListCommand::getReferencedPids(
-        pid_t serverPid, std::map<uint64_t, Pids> *objects) const {
-
-    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
+bool scanBinderContext(pid_t pid,
+        const std::string &contextName,
+        std::function<void(const std::string&)> eachLine) {
+    std::ifstream ifs("/d/binder/proc/" + std::to_string(pid));
     if (!ifs.is_open()) {
         return false;
     }
 
-    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
+    static const std::regex kContextLine("^context (\\w+)$");
 
+    bool isDesiredContext = false;
     std::string line;
     std::smatch match;
     while(getline(ifs, line)) {
-        if (!std::regex_search(line, match, prefix)) {
-            // the line doesn't start with the correct prefix
+        if (std::regex_search(line, match, kContextLine)) {
+            isDesiredContext = match.str(1) == contextName;
             continue;
         }
-        std::string ptrString = "0x" + match.str(2); // use number after c
-        uint64_t ptr;
-        if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
-            // Should not reach here, but just be tolerant.
-            mErr << "Could not parse number " << ptrString << std::endl;
+
+        if (!isDesiredContext) {
             continue;
         }
-        const std::string proc = " proc ";
-        auto pos = line.rfind(proc);
-        if (pos != std::string::npos) {
-            for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
-                int32_t pid;
-                if (!::android::base::ParseInt(pidStr, &pid)) {
-                    mErr << "Could not parse number " << pidStr << std::endl;
-                    continue;
-                }
-                (*objects)[ptr].push_back(pid);
-            }
-        }
+
+        eachLine(line);
     }
     return true;
 }
 
+bool ListCommand::getPidInfo(
+        pid_t serverPid, PidInfo *pidInfo) const {
+    static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
+    static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)");
+
+    std::smatch match;
+    return scanBinderContext(serverPid, "hwbinder", [&](const std::string& line) {
+        if (std::regex_search(line, match, kReferencePrefix)) {
+            const std::string &ptrString = "0x" + match.str(2); // use number after c
+            uint64_t ptr;
+            if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+                // Should not reach here, but just be tolerant.
+                mErr << "Could not parse number " << ptrString << std::endl;
+                return;
+            }
+            const std::string proc = " proc ";
+            auto pos = line.rfind(proc);
+            if (pos != std::string::npos) {
+                for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
+                    int32_t pid;
+                    if (!::android::base::ParseInt(pidStr, &pid)) {
+                        mErr << "Could not parse number " << pidStr << std::endl;
+                        return;
+                    }
+                    pidInfo->refPids[ptr].push_back(pid);
+                }
+            }
+
+            return;
+        }
+
+        if (std::regex_search(line, match, kThreadPrefix)) {
+            // "1" is waiting in binder driver
+            // "2" is poll. It's impossible to tell if these are in use.
+            //     and HIDL default code doesn't use it.
+            bool isInUse = match.str(1) != "1";
+            // "0" is a thread that has called into binder
+            // "1" is looper thread
+            // "2" is main looper thread
+            bool isHwbinderThread = match.str(2) != "0";
+
+            if (!isHwbinderThread) {
+                return;
+            }
+
+            if (isInUse) {
+                pidInfo->threadUsage++;
+            }
+
+            pidInfo->threadCount++;
+            return;
+        }
+
+        // not reference or thread line
+        return;
+    });
+}
+
 // Must process hwbinder services first, then passthrough services.
 void ListCommand::forEachTable(const std::function<void(Table &)> &f) {
     f(mServicesTable);
@@ -164,9 +210,11 @@
         const std::string &interfaceName,
         const std::string &transport,
         const std::string &arch,
+        const std::string &threadUsage,
         const std::string &server,
         const std::string &serverCmdline,
-        const std::string &address, const std::string &clients,
+        const std::string &address,
+        const std::string &clients,
         const std::string &clientCmdlines) const {
     if (mSelectedColumns & ENABLE_INTERFACE_NAME)
         mOut << std::setw(80) << interfaceName << "\t";
@@ -174,6 +222,9 @@
         mOut << std::setw(10) << transport << "\t";
     if (mSelectedColumns & ENABLE_ARCH)
         mOut << std::setw(5) << arch << "\t";
+    if (mSelectedColumns & ENABLE_THREADS) {
+        mOut << std::setw(8) << threadUsage << "\t";
+    }
     if (mSelectedColumns & ENABLE_SERVER_PID) {
         if (mEnableCmdlines) {
             mOut << std::setw(15) << serverCmdline << "\t";
@@ -193,7 +244,18 @@
     mOut << std::endl;
 }
 
+static inline bool findAndBumpVersion(vintf::ManifestHal* hal, const vintf::Version& version) {
+    for (vintf::Version& v : hal->versions) {
+        if (v.majorVer == version.majorVer) {
+            v.minorVer = std::max(v.minorVer, version.minorVer);
+            return true;
+        }
+    }
+    return false;
+}
+
 void ListCommand::dumpVintf() const {
+    using vintf::operator|=;
     mOut << "<!-- " << std::endl
          << "    This is a skeleton device manifest. Notes: " << std::endl
          << "    1. android.hidl.*, android.frameworks.*, android.system.* are not included." << std::endl
@@ -201,7 +263,9 @@
          << "       only hwbinder is shown." << std::endl
          << "    3. It is likely that HALs in passthrough transport does not have" << std::endl
          << "       <interface> declared; users will have to write them by hand." << std::endl
-         << "    4. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
+         << "    4. A HAL with lower minor version can be overridden by a HAL with" << std::endl
+         << "       higher minor version if they have the same name and major version." << std::endl
+         << "    5. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
          << "       is removed from the manifest file and written by assemble_vintf" << std::endl
          << "       at build time." << std::endl
          << "-->" << std::endl;
@@ -265,17 +329,19 @@
             for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
                 if (hal->transport() != transport) {
                     if (transport != vintf::Transport::PASSTHROUGH) {
-                        mErr << "Fatal: should not reach here. Generated result may be wrong."
+                        mErr << "Fatal: should not reach here. Generated result may be wrong for '"
+                             << hal->name << "'."
                              << std::endl;
                     }
                     done = true;
                     break;
                 }
-                if (hal->hasVersion(version)) {
+                if (findAndBumpVersion(hal, version)) {
                     if (&table != &mImplementationsTable) {
                         hal->interfaces[interfaceName].name = interfaceName;
                         hal->interfaces[interfaceName].instances.insert(instanceName);
                     }
+                    hal->transportArch.arch |= arch;
                     done = true;
                     break;
                 }
@@ -344,15 +410,20 @@
     mImplementationsTable.description =
             "All available passthrough implementations (all -impl.so files)";
     forEachTable([this] (const Table &table) {
-        mOut << table.description << std::endl;
+        if (!mNeat) {
+            mOut << table.description << std::endl;
+        }
         mOut << std::left;
-        printLine("Interface", "Transport", "Arch", "Server", "Server CMD",
-                  "PTR", "Clients", "Clients CMD");
+        if (!mNeat) {
+            printLine("Interface", "Transport", "Arch", "Thread Use", "Server",
+                      "Server CMD", "PTR", "Clients", "Clients CMD");
+        }
 
         for (const auto &entry : table) {
             printLine(entry.interfaceName,
                     entry.transport,
                     getArchString(entry.arch),
+                    entry.getThreadUsage(),
                     entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid),
                     entry.serverCmdline,
                     entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress),
@@ -369,7 +440,9 @@
                         NullableOStream<std::ostream>(nullptr));
             }
         }
-        mOut << std::endl;
+        if (!mNeat) {
+            mOut << std::endl;
+        }
     });
 
 }
@@ -409,7 +482,8 @@
     using namespace ::android::hardware;
     using namespace ::android::hidl::manager::V1_0;
     using namespace ::android::hidl::base::V1_0;
-    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+    using std::literals::chrono_literals::operator""s;
+    auto ret = timeoutIPC(2s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
         std::map<std::string, TableEntry> entries;
         for (const auto &info : infos) {
             std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
@@ -419,7 +493,7 @@
                 .transport = "passthrough",
                 .serverPid = NO_PID,
                 .serverObjectAddress = NO_PTR,
-                .clientPids = {},
+                .clientPids = info.clientPids,
                 .arch = ARCH_UNKNOWN
             }).first->second.arch |= fromBaseArchitecture(info.arch);
         }
@@ -486,7 +560,7 @@
     Status status = OK;
     // server pid, .ptr value of binder object, child pids
     std::map<std::string, DebugInfo> allDebugInfos;
-    std::map<pid_t, std::map<uint64_t, Pids>> allPids;
+    std::map<pid_t, PidInfo> allPids;
     for (const auto &fqInstanceName : fqInstanceNames) {
         const auto pair = splitFirst(fqInstanceName, '/');
         const auto &serviceName = pair.first;
@@ -510,7 +584,7 @@
         auto debugRet = timeoutIPC(service, &IBase::getDebugInfo, [&] (const auto &debugInfo) {
             allDebugInfos[fqInstanceName] = debugInfo;
             if (debugInfo.pid >= 0) {
-                allPids[static_cast<pid_t>(debugInfo.pid)].clear();
+                allPids[static_cast<pid_t>(debugInfo.pid)] = PidInfo();
             }
         });
         if (!debugRet.isOk()) {
@@ -520,9 +594,10 @@
             status |= DUMP_BINDERIZED_ERROR;
         }
     }
+
     for (auto &pair : allPids) {
         pid_t serverPid = pair.first;
-        if (!getReferencedPids(serverPid, &allPids[serverPid])) {
+        if (!getPidInfo(serverPid, &allPids[serverPid])) {
             mErr << "Warning: no information for PID " << serverPid
                       << ", are you root?" << std::endl;
             status |= DUMP_BINDERIZED_ERROR;
@@ -537,18 +612,23 @@
                 .serverPid = NO_PID,
                 .serverObjectAddress = NO_PTR,
                 .clientPids = {},
+                .threadUsage = 0,
+                .threadCount = 0,
                 .arch = ARCH_UNKNOWN
             });
             continue;
         }
         const DebugInfo &info = it->second;
+        bool writePidInfo = info.pid != NO_PID && info.ptr != NO_PTR;
+
         putEntry(HWSERVICEMANAGER_LIST, {
             .interfaceName = fqInstanceName,
             .transport = mode,
             .serverPid = info.pid,
             .serverObjectAddress = info.ptr,
-            .clientPids = info.pid == NO_PID || info.ptr == NO_PTR
-                    ? Pids{} : allPids[info.pid][info.ptr],
+            .clientPids = writePidInfo ? allPids[info.pid].refPids[info.ptr] : Pids{},
+            .threadUsage = writePidInfo ? allPids[info.pid].threadUsage : 0,
+            .threadCount = writePidInfo ? allPids[info.pid].threadCount : 0,
             .arch = fromBaseArchitecture(info.arch),
         });
     }
@@ -587,12 +667,14 @@
         {"pid",       no_argument,       0, 'p' },
         {"address",   no_argument,       0, 'a' },
         {"clients",   no_argument,       0, 'c' },
+        {"threads",   no_argument,       0, 'e' },
         {"cmdline",   no_argument,       0, 'm' },
         {"debug",     optional_argument, 0, 'd' },
 
         // long options without short alternatives
         {"sort",      required_argument, 0, 's' },
         {"init-vintf",optional_argument, 0, 'v' },
+        {"neat",      no_argument,       0, 'n' },
         { 0,          0,                 0,  0  }
     };
 
@@ -602,7 +684,7 @@
     for (;;) {
         // using getopt_long in case we want to add other options in the future
         c = getopt_long(arg.argc, arg.argv,
-                "hitrpacmd", longOptions, &optionIndex);
+                "hitrpacmde", longOptions, &optionIndex);
         if (c == -1) {
             break;
         }
@@ -654,6 +736,10 @@
             mSelectedColumns |= ENABLE_CLIENT_PIDS;
             break;
         }
+        case 'e': {
+            mSelectedColumns |= ENABLE_THREADS;
+            break;
+        }
         case 'm': {
             mEnableCmdlines = true;
             break;
@@ -672,6 +758,10 @@
             }
             break;
         }
+        case 'n': {
+            mNeat = true;
+            break;
+        }
         case 'h': // falls through
         default: // see unrecognized options
             mLshal.usage(command);
@@ -684,7 +774,7 @@
     }
 
     if (mSelectedColumns == 0) {
-        mSelectedColumns = ENABLE_INTERFACE_NAME | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS;
+        mSelectedColumns = ENABLE_INTERFACE_NAME | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS | ENABLE_THREADS;
     }
     return OK;
 }
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 42c965f..a75db04 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -48,18 +48,26 @@
     Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
     Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
     Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
-    bool getReferencedPids(
-        pid_t serverPid, std::map<uint64_t, Pids> *objects) const;
+
+    struct PidInfo {
+        std::map<uint64_t, Pids> refPids; // pids that are referenced
+        uint32_t threadUsage; // number of threads in use
+        uint32_t threadCount; // number of threads total
+    };
+    bool getPidInfo(pid_t serverPid, PidInfo *info) const;
+
     void dumpTable();
     void dumpVintf() const;
     void printLine(
             const std::string &interfaceName,
             const std::string &transport,
             const std::string &arch,
+            const std::string &threadUsage,
             const std::string &server,
             const std::string &serverCmdline,
-            const std::string &address, const std::string &clients,
-            const std::string &clientCmdlines) const ;
+            const std::string &address,
+            const std::string &clients,
+            const std::string &clientCmdlines) const;
     // Return /proc/{pid}/cmdline if it exists, else empty string.
     const std::string &getCmdline(pid_t pid);
     // Call getCmdline on all pid in pids. If it returns empty string, the process might
@@ -85,7 +93,12 @@
     // If true, calls IBase::debug(...) on each service.
     bool mEmitDebugInfo = false;
 
+    // If true, output in VINTF format.
     bool mVintf = false;
+
+    // If true, explanatory text are not emitted.
+    bool mNeat = false;
+
     // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
     // If an entry exist but is an empty string, process might have died.
     // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 9db42f1..e2d5f6d 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -66,7 +66,7 @@
             "        List all hals with default ordering and columns (`lshal list -ipc`)\n"
             "    lshal list [-h|--help]\n"
             "        -h, --help: Print help message for list (`lshal help list`)\n"
-            "    lshal [list] [--interface|-i] [--transport|-t] [-r|--arch]\n"
+            "    lshal [list] [--interface|-i] [--transport|-t] [-r|--arch] [-e|--threads]\n"
             "            [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]\n"
             "            [--sort={interface|i|pid|p}] [--init-vintf[=<output file>]]\n"
             "            [--debug|-d[=<output file>]]\n"
@@ -74,6 +74,8 @@
             "        -n, --instance: print the instance name column\n"
             "        -t, --transport: print the transport mode column\n"
             "        -r, --arch: print if the HAL is in 64-bit or 32-bit\n"
+            "        -e, --threads: print currently used/available threads\n"
+            "                       (note, available threads created lazily)\n"
             "        -p, --pid: print the server PID, or server cmdline if -m is set\n"
             "        -a, --address: print the server object address column\n"
             "        -c, --clients: print the client PIDs, or client cmdlines if -m is set\n"
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 9ae8f78..e04c3ca 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -47,6 +47,8 @@
     std::string interfaceName;
     std::string transport;
     int32_t serverPid;
+    uint32_t threadUsage;
+    uint32_t threadCount;
     std::string serverCmdline;
     uint64_t serverObjectAddress;
     Pids clientPids;
@@ -59,6 +61,14 @@
     static bool sortByServerPid(const TableEntry &a, const TableEntry &b) {
         return a.serverPid < b.serverPid;
     };
+
+    std::string getThreadUsage() const {
+        if (threadCount == 0) {
+            return "N/A";
+        }
+
+        return std::to_string(threadUsage) + "/" + std::to_string(threadCount);
+    }
 };
 
 struct Table {
@@ -80,7 +90,8 @@
     ENABLE_SERVER_PID     = 1 << 2,
     ENABLE_SERVER_ADDR    = 1 << 3,
     ENABLE_CLIENT_PIDS    = 1 << 4,
-    ENABLE_ARCH           = 1 << 5
+    ENABLE_ARCH           = 1 << 5,
+    ENABLE_THREADS        = 1 << 6,
 };
 
 using TableEntrySelect = unsigned int;
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index ca477bf..c940404 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -77,14 +77,15 @@
     return success;
 }
 
-template<class Function, class I, class... Args>
+template<class R, class P, class Function, class I, class... Args>
 typename std::result_of<Function(I *, Args...)>::type
-timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+timeoutIPC(std::chrono::duration<R, P> wait, const sp<I> &interfaceObject, Function &&func,
+           Args &&... args) {
     using ::android::hardware::Status;
     typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
     auto boundFunc = std::bind(std::forward<Function>(func),
             interfaceObject.get(), std::forward<Args>(args)...);
-    bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] {
+    bool success = timeout(wait, [&ret, &boundFunc] {
         ret = std::move(boundFunc());
     });
     if (!success) {
@@ -93,5 +94,12 @@
     return ret;
 }
 
+template<class Function, class I, class... Args>
+typename std::result_of<Function(I *, Args...)>::type
+timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+    return timeoutIPC(IPC_CALL_WAIT, interfaceObject, func, args...);
+}
+
+
 }  // namespace lshal
 }  // namespace android
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 39d92a7..d3d396f 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -46,7 +46,6 @@
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils"],
-    static_libs: ["libselinux"],
+    shared_libs: ["libcutils", "libselinux_vendor"],
     init_rc: ["vndservicemanager.rc"],
 }
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 45bb1d0..31cd0cb 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -8,10 +8,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <cutils/android_filesystem_config.h>
 #include <cutils/multiuser.h>
 
-#include <private/android_filesystem_config.h>
-
 #include <selinux/android.h>
 #include <selinux/avc.h>
 
@@ -287,7 +286,11 @@
     }
 
     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;
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index aec211a..d336a43 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -12,3 +12,4 @@
     onrestart restart drm
     onrestart restart cameraserver
     writepid /dev/cpuset/system-background/tasks
+    shutdown critical
diff --git a/cmds/servicemanager/vndservicemanager.rc b/cmds/servicemanager/vndservicemanager.rc
index d5ddaaf..3fa4d7d 100644
--- a/cmds/servicemanager/vndservicemanager.rc
+++ b/cmds/servicemanager/vndservicemanager.rc
@@ -3,4 +3,4 @@
     user system
     group system readproc
     writepid /dev/cpuset/system-background/tasks
-
+    shutdown critical
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
new file mode 100644
index 0000000..d4c037a
--- /dev/null
+++ b/cmds/surfacereplayer/Android.bp
@@ -0,0 +1,4 @@
+subdirs = [
+    "proto",
+    "replayer",
+]
\ No newline at end of file
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
new file mode 100644
index 0000000..dda80bb
--- /dev/null
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -0,0 +1,10 @@
+cc_library_static {
+    name: "libtrace_proto",
+    srcs: [
+        "src/trace.proto",
+    ],
+    proto: {
+        type: "lite",
+        export_proto_headers: true,
+    },
+}
diff --git a/cmds/surfacereplayer/proto/Android.mk b/cmds/surfacereplayer/proto/Android.mk
deleted file mode 100644
index 3cf1148..0000000
--- a/cmds/surfacereplayer/proto/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-proto-files-under, src)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_MODULE := libtrace_proto
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
new file mode 100644
index 0000000..5caceec
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -0,0 +1,66 @@
+cc_library_shared {
+    name: "libsurfacereplayer",
+    clang: true,
+    srcs: [
+        "BufferQueueScheduler.cpp",
+        "Event.cpp",
+        "Replayer.cpp",
+    ],
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-format",
+	"-Wno-c++98-compat-pedantic",
+	"-Wno-float-conversion",
+	"-Wno-disabled-macro-expansion",
+	"-Wno-float-equal",
+	"-Wno-sign-conversion",
+	"-Wno-padded",
+	"-std=c++14",
+    ],
+    static_libs: [
+        "libtrace_proto",
+    ],
+    shared_libs: [
+        "libEGL",
+        "libGLESv2",
+        "libbinder",
+        "liblog",
+        "libcutils",
+        "libgui",
+        "libui",
+        "libutils",
+        "libprotobuf-cpp-lite",
+        "libbase",
+        "libnativewindow",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+}
+
+cc_binary {
+    name: "surfacereplayer",
+    clang: true,
+    srcs: [
+        "Main.cpp",
+    ],
+    shared_libs: [
+        "libprotobuf-cpp-lite",
+        "libsurfacereplayer",
+        "libutils",
+        "libgui",
+    ],
+    static_libs: [
+        "libtrace_proto",
+    ],
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+	"-Wno-c++98-compat-pedantic",
+	"-Wno-float-conversion",
+	"-Wno-disabled-macro-expansion",
+	"-Wno-float-equal",
+	"-std=c++14",
+    ],
+}
diff --git a/cmds/surfacereplayer/replayer/Android.mk b/cmds/surfacereplayer/replayer/Android.mk
deleted file mode 100644
index 1dd926c..0000000
--- a/cmds/surfacereplayer/replayer/Android.mk
+++ /dev/null
@@ -1,75 +0,0 @@
-# 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.
-
-LOCAL_TARGET_DIR := $(TARGET_OUT_DATA)/local/tmp
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(call first-makefiles-under, /frameworks/native/cmds/surfacereplayer/proto)
-
-include $(CLEAR_VARS)
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-LOCAL_CPPFLAGS := -Wno-format
-
-LOCAL_MODULE := libsurfacereplayer
-
-LOCAL_SRC_FILES := \
-    BufferQueueScheduler.cpp \
-    Event.cpp \
-    Replayer.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    libEGL \
-    libGLESv2 \
-    libbinder \
-    liblog \
-    libcutils \
-    libgui \
-    libui \
-    libutils \
-    libprotobuf-cpp-lite \
-    libbase \
-    libnativewindow \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtrace_proto \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/..
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := surfacereplayer
-
-LOCAL_SRC_FILES := \
-    Main.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    libprotobuf-cpp-lite \
-    libsurfacereplayer \
-    libutils \
-    libgui \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtrace_proto \
-
-LOCAL_CPPFLAGS := -Weverything -Werror
-LOCAL_CPPFLAGS := -Wno-unused-parameter
-
-LOCAL_MODULE_PATH := $(LOCAL_TARGET_DIR)
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index dd1dd7d..7090bdb 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -24,7 +24,7 @@
  * 5. Exit successfully or print error statement
  */
 
-#include <replayer/Replayer.h>
+#include <Replayer.h>
 
 #include <csignal>
 #include <iostream>
diff --git a/data/etc/android.hardware.broadcastradio.xml b/data/etc/android.hardware.broadcastradio.xml
new file mode 100644
index 0000000..c669518
--- /dev/null
+++ b/data/etc/android.hardware.broadcastradio.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard set of features for a broadcast radio. -->
+<permissions>
+    <feature name="android.hardware.broadcastradio" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.euicc.xml b/data/etc/android.hardware.telephony.euicc.xml
new file mode 100644
index 0000000..167ed6a
--- /dev/null
+++ b/data/etc/android.hardware.telephony.euicc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices with an eUICC. -->
+<permissions>
+    <feature name="android.hardware.telephony.euicc" />
+</permissions>
diff --git a/data/etc/android.hardware.wifi.passpoint.xml b/data/etc/android.hardware.wifi.passpoint.xml
new file mode 100644
index 0000000..4698bb3
--- /dev/null
+++ b/data/etc/android.hardware.wifi.passpoint.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device includes WiFi Passpoint. -->
+<permissions>
+    <feature name="android.hardware.wifi.passpoint" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index 835504f..561f5ba 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -41,7 +41,6 @@
     <feature name="android.software.voice_recognizers" notLowRam="true" />
     <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
-    <feature name="android.software.input_methods" />
     <feature name="android.software.print" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 0d5d206..ec7be53 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -45,7 +45,7 @@
     <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
-    <feature name="android.software.picture_in_picture" />
+    <feature name="android.software.picture_in_picture" notLowRam="true" />
     <feature name="android.software.activities_on_secondary_displays" />
     <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
diff --git a/headers/Android.bp b/headers/Android.bp
new file mode 100644
index 0000000..82bc8a1
--- /dev/null
+++ b/headers/Android.bp
@@ -0,0 +1,20 @@
+cc_library_headers {
+    name: "media_plugin_headers",
+    vendor_available: true,
+    export_include_dirs: [
+        "media_plugin",
+        "media_plugin/media/openmax",
+    ],
+    header_libs: [
+        "libstagefright_headers",
+        "libcutils_headers",
+        "libutils_headers",
+        "libstagefright_foundation_headers",
+    ],
+    export_header_lib_headers: [
+        "libstagefright_headers",
+        "libcutils_headers",
+        "libutils_headers",
+        "libstagefright_foundation_headers",
+    ],
+}
diff --git a/include/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
similarity index 100%
rename from include/media/cas/CasAPI.h
rename to headers/media_plugin/media/cas/CasAPI.h
diff --git a/include/media/cas/DescramblerAPI.h b/headers/media_plugin/media/cas/DescramblerAPI.h
similarity index 100%
rename from include/media/cas/DescramblerAPI.h
rename to headers/media_plugin/media/cas/DescramblerAPI.h
diff --git a/include/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
similarity index 100%
rename from include/media/drm/DrmAPI.h
rename to headers/media_plugin/media/drm/DrmAPI.h
diff --git a/include/media/editor/II420ColorConverter.h b/headers/media_plugin/media/editor/II420ColorConverter.h
similarity index 100%
rename from include/media/editor/II420ColorConverter.h
rename to headers/media_plugin/media/editor/II420ColorConverter.h
diff --git a/include/media/hardware/CryptoAPI.h b/headers/media_plugin/media/hardware/CryptoAPI.h
similarity index 100%
rename from include/media/hardware/CryptoAPI.h
rename to headers/media_plugin/media/hardware/CryptoAPI.h
diff --git a/include/media/hardware/HDCPAPI.h b/headers/media_plugin/media/hardware/HDCPAPI.h
similarity index 99%
rename from include/media/hardware/HDCPAPI.h
rename to headers/media_plugin/media/hardware/HDCPAPI.h
index 30cd5fd..7797bb2 100644
--- a/include/media/hardware/HDCPAPI.h
+++ b/headers/media_plugin/media/hardware/HDCPAPI.h
@@ -15,11 +15,10 @@
  */
 
 #ifndef HDCP_API_H_
-
 #define HDCP_API_H_
 
 #include <utils/Errors.h>
-#include <system/window.h>
+#include <cutils/native_handle.h>
 
 namespace android {
 
diff --git a/include/media/hardware/HardwareAPI.h b/headers/media_plugin/media/hardware/HardwareAPI.h
similarity index 99%
rename from include/media/hardware/HardwareAPI.h
rename to headers/media_plugin/media/hardware/HardwareAPI.h
index cecf715..6c1ba3d 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/headers/media_plugin/media/hardware/HardwareAPI.h
@@ -20,13 +20,15 @@
 
 #include <media/hardware/OMXPluginBase.h>
 #include <media/hardware/MetadataBufferType.h>
-#include <system/window.h>
+#include <cutils/native_handle.h>
 #include <utils/RefBase.h>
 
 #include "VideoAPI.h"
 
 #include <OMX_Component.h>
 
+struct ANativeWindowBuffer;
+
 namespace android {
 
 // This structure is used to enable Android native buffer use for either
diff --git a/include/media/hardware/MetadataBufferType.h b/headers/media_plugin/media/hardware/MetadataBufferType.h
similarity index 100%
rename from include/media/hardware/MetadataBufferType.h
rename to headers/media_plugin/media/hardware/MetadataBufferType.h
diff --git a/include/media/hardware/OMXPluginBase.h b/headers/media_plugin/media/hardware/OMXPluginBase.h
similarity index 100%
rename from include/media/hardware/OMXPluginBase.h
rename to headers/media_plugin/media/hardware/OMXPluginBase.h
diff --git a/include/media/hardware/VideoAPI.h b/headers/media_plugin/media/hardware/VideoAPI.h
similarity index 100%
rename from include/media/hardware/VideoAPI.h
rename to headers/media_plugin/media/hardware/VideoAPI.h
diff --git a/include/media/openmax/OMX_AsString.h b/headers/media_plugin/media/openmax/OMX_AsString.h
similarity index 98%
rename from include/media/openmax/OMX_AsString.h
rename to headers/media_plugin/media/openmax/OMX_AsString.h
index 56d7cc8..dc25ded 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/headers/media_plugin/media/openmax/OMX_AsString.h
@@ -930,6 +930,14 @@
 #ifndef AS_STRING_FOR_OMX_VIDEOEXT_H
 #define AS_STRING_FOR_OMX_VIDEOEXT_H
 
+inline static const char *asString(OMX_VIDEO_AVCPROFILEEXTTYPE i, const char *def = "??") {
+    switch (i) {
+        case OMX_VIDEO_AVCProfileConstrainedBaseline:   return "ConstrainedBaseline";
+        case OMX_VIDEO_AVCProfileConstrainedHigh:       return "ConstrainedHigh";
+        default:                                return asString((OMX_VIDEO_AVCPROFILETYPE)i, def);
+    }
+}
+
 inline static const char *asString(OMX_VIDEO_VP8PROFILETYPE i, const char *def = "??") {
     switch (i) {
         case OMX_VIDEO_VP8ProfileMain:    return "Main";
diff --git a/include/media/openmax/OMX_Audio.h b/headers/media_plugin/media/openmax/OMX_Audio.h
similarity index 100%
rename from include/media/openmax/OMX_Audio.h
rename to headers/media_plugin/media/openmax/OMX_Audio.h
diff --git a/include/media/openmax/OMX_AudioExt.h b/headers/media_plugin/media/openmax/OMX_AudioExt.h
similarity index 100%
rename from include/media/openmax/OMX_AudioExt.h
rename to headers/media_plugin/media/openmax/OMX_AudioExt.h
diff --git a/include/media/openmax/OMX_Component.h b/headers/media_plugin/media/openmax/OMX_Component.h
similarity index 100%
rename from include/media/openmax/OMX_Component.h
rename to headers/media_plugin/media/openmax/OMX_Component.h
diff --git a/include/media/openmax/OMX_ContentPipe.h b/headers/media_plugin/media/openmax/OMX_ContentPipe.h
similarity index 100%
rename from include/media/openmax/OMX_ContentPipe.h
rename to headers/media_plugin/media/openmax/OMX_ContentPipe.h
diff --git a/include/media/openmax/OMX_Core.h b/headers/media_plugin/media/openmax/OMX_Core.h
similarity index 100%
rename from include/media/openmax/OMX_Core.h
rename to headers/media_plugin/media/openmax/OMX_Core.h
diff --git a/include/media/openmax/OMX_IVCommon.h b/headers/media_plugin/media/openmax/OMX_IVCommon.h
similarity index 100%
rename from include/media/openmax/OMX_IVCommon.h
rename to headers/media_plugin/media/openmax/OMX_IVCommon.h
diff --git a/include/media/openmax/OMX_Image.h b/headers/media_plugin/media/openmax/OMX_Image.h
similarity index 100%
rename from include/media/openmax/OMX_Image.h
rename to headers/media_plugin/media/openmax/OMX_Image.h
diff --git a/include/media/openmax/OMX_Index.h b/headers/media_plugin/media/openmax/OMX_Index.h
similarity index 100%
rename from include/media/openmax/OMX_Index.h
rename to headers/media_plugin/media/openmax/OMX_Index.h
diff --git a/include/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h
similarity index 100%
rename from include/media/openmax/OMX_IndexExt.h
rename to headers/media_plugin/media/openmax/OMX_IndexExt.h
diff --git a/include/media/openmax/OMX_Other.h b/headers/media_plugin/media/openmax/OMX_Other.h
similarity index 100%
rename from include/media/openmax/OMX_Other.h
rename to headers/media_plugin/media/openmax/OMX_Other.h
diff --git a/include/media/openmax/OMX_Types.h b/headers/media_plugin/media/openmax/OMX_Types.h
similarity index 100%
rename from include/media/openmax/OMX_Types.h
rename to headers/media_plugin/media/openmax/OMX_Types.h
diff --git a/include/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
similarity index 100%
rename from include/media/openmax/OMX_Video.h
rename to headers/media_plugin/media/openmax/OMX_Video.h
diff --git a/include/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
similarity index 94%
rename from include/media/openmax/OMX_VideoExt.h
rename to headers/media_plugin/media/openmax/OMX_VideoExt.h
index 128dd2d..c102564 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -58,6 +58,12 @@
     OMX_NALUFORMATSTYPE eNaluFormat;
 } OMX_NALSTREAMFORMATTYPE;
 
+/** AVC additional profiles */
+typedef enum OMX_VIDEO_AVCPROFILEEXTTYPE {
+    OMX_VIDEO_AVCProfileConstrainedBaseline = 0x10000,   /**< Constrained baseline profile */
+    OMX_VIDEO_AVCProfileConstrainedHigh     = 0x80000,   /**< Constrained high profile */
+} OMX_VIDEO_AVCPROFILEEXTTYPE;
+
 /** VP8 profiles */
 typedef enum OMX_VIDEO_VP8PROFILETYPE {
     OMX_VIDEO_VP8ProfileMain = 0x01,
@@ -164,20 +170,20 @@
 
 /** VP9 levels */
 typedef enum OMX_VIDEO_VP9LEVELTYPE {
-    OMX_VIDEO_VP9Level1  = 0x0,
-    OMX_VIDEO_VP9Level11 = 0x1,
-    OMX_VIDEO_VP9Level2  = 0x2,
-    OMX_VIDEO_VP9Level21 = 0x4,
-    OMX_VIDEO_VP9Level3  = 0x8,
-    OMX_VIDEO_VP9Level31 = 0x10,
-    OMX_VIDEO_VP9Level4  = 0x20,
-    OMX_VIDEO_VP9Level41 = 0x40,
-    OMX_VIDEO_VP9Level5  = 0x80,
-    OMX_VIDEO_VP9Level51 = 0x100,
-    OMX_VIDEO_VP9Level52 = 0x200,
-    OMX_VIDEO_VP9Level6  = 0x400,
-    OMX_VIDEO_VP9Level61 = 0x800,
-    OMX_VIDEO_VP9Level62 = 0x1000,
+    OMX_VIDEO_VP9Level1  = 0x1,
+    OMX_VIDEO_VP9Level11 = 0x2,
+    OMX_VIDEO_VP9Level2  = 0x4,
+    OMX_VIDEO_VP9Level21 = 0x8,
+    OMX_VIDEO_VP9Level3  = 0x10,
+    OMX_VIDEO_VP9Level31 = 0x20,
+    OMX_VIDEO_VP9Level4  = 0x40,
+    OMX_VIDEO_VP9Level41 = 0x80,
+    OMX_VIDEO_VP9Level5  = 0x100,
+    OMX_VIDEO_VP9Level51 = 0x200,
+    OMX_VIDEO_VP9Level52 = 0x400,
+    OMX_VIDEO_VP9Level6  = 0x800,
+    OMX_VIDEO_VP9Level61 = 0x1000,
+    OMX_VIDEO_VP9Level62 = 0x2000,
     OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF,
     OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF
 } OMX_VIDEO_VP9LEVELTYPE;
@@ -290,6 +296,8 @@
     OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
     OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
     OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+    OMX_VIDEO_DolbyVisionProfileDvheSt  = 0x100,
+    OMX_VIDEO_DolbyVisionProfileDvavSe  = 0x200,
     OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
 } OMX_VIDEO_DOLBYVISIONPROFILETYPE;
 
diff --git a/include/android/asset_manager.h b/include/android/asset_manager.h
index 7ef3ecb..2ac7d4d 100644
--- a/include/android/asset_manager.h
+++ b/include/android/asset_manager.h
@@ -33,6 +33,10 @@
 extern "C" {
 #endif
 
+#if !defined(__ANDROID__) && !defined(__RENAME_IF_FILE_OFFSET64)
+#define __RENAME_IF_FILE_OFFSET64(x)
+#endif
+
 struct AAssetManager;
 /**
  * {@link AAssetManager} provides access to an application's raw assets by
@@ -132,9 +136,9 @@
  *
  * Returns the new position on success, or (off_t) -1 on error.
  */
-off_t AAsset_seek(AAsset* asset, off_t offset, int whence);
+off_t AAsset_seek(AAsset* asset, off_t offset, int whence)
+    __RENAME_IF_FILE_OFFSET64(AAsset_seek64);
 
-#if __ANDROID_API__ >= 13
 /**
  * Seek to the specified offset within the asset data.  'whence' uses the
  * same constants as lseek()/fseek().
@@ -145,7 +149,6 @@
  * Returns the new position on success, or (off64_t) -1 on error.
  */
 off64_t AAsset_seek64(AAsset* asset, off64_t offset, int whence);
-#endif
 
 /**
  * Close the asset, freeing all associated resources.
@@ -162,29 +165,27 @@
 /**
  * Report the total size of the asset data.
  */
-off_t AAsset_getLength(AAsset* asset);
+off_t AAsset_getLength(AAsset* asset)
+    __RENAME_IF_FILE_OFFSET64(AAsset_getLength64);
 
-#if __ANDROID_API__ >= 13
 /**
  * Report the total size of the asset data. Reports the size using a 64-bit
  * number insted of 32-bit as AAsset_getLength.
  */
 off64_t AAsset_getLength64(AAsset* asset);
-#endif
 
 /**
  * Report the total amount of asset data that can be read from the current position.
  */
-off_t AAsset_getRemainingLength(AAsset* asset);
+off_t AAsset_getRemainingLength(AAsset* asset)
+    __RENAME_IF_FILE_OFFSET64(AAsset_getRemainingLength64);
 
-#if __ANDROID_API__ >= 13
 /**
  * Report the total amount of asset data that can be read from the current position.
  *
  * Uses a 64-bit number instead of a 32-bit number as AAsset_getRemainingLength does.
  */
 off64_t AAsset_getRemainingLength64(AAsset* asset);
-#endif
 
 /**
  * Open a new file descriptor that can be used to read the asset data. If the
@@ -194,9 +195,9 @@
  * Returns < 0 if direct fd access is not possible (for example, if the asset is
  * compressed).
  */
-int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength);
+int AAsset_openFileDescriptor(AAsset* asset, off_t* outStart, off_t* outLength)
+    __RENAME_IF_FILE_OFFSET64(AAsset_openFileDescriptor64);
 
-#if __ANDROID_API__ >= 13
 /**
  * Open a new file descriptor that can be used to read the asset data.
  *
@@ -207,7 +208,6 @@
  * compressed).
  */
 int AAsset_openFileDescriptor64(AAsset* asset, off64_t* outStart, off64_t* outLength);
-#endif
 
 /**
  * Returns whether this asset's internal buffer is allocated in ordinary RAM (i.e. not
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index e202060..2164d61 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -765,7 +765,9 @@
     /** fingerprint navigation key, left. */
     AKEYCODE_SYSTEM_NAVIGATION_LEFT = 282,
     /** fingerprint navigation key, right. */
-    AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283
+    AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283,
+    /** all apps */
+    AKEYCODE_ALL_APPS = 284
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/android/sensor.h b/include/android/sensor.h
index cdb3fff..7f46087 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -50,6 +50,7 @@
 
 #include <android/looper.h>
 
+#include <stdbool.h>
 #include <sys/types.h>
 #include <math.h>
 #include <stdint.h>
@@ -380,8 +381,13 @@
  *     ASensorManager* sensorManager = ASensorManager_getInstance();
  *
  */
+#if __ANDROID_API__ >= __ANDROID_API_O__
 __attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
+#else
+ASensorManager* ASensorManager_getInstance();
+#endif
 
+#if __ANDROID_API__ >= __ANDROID_API_O__
 /*
  * Get a reference to the sensor manager. ASensorManager is a singleton
  * per package as different packages may have access to different sensors.
@@ -392,6 +398,7 @@
  *
  */
 ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
+#endif
 
 /**
  * Returns the list of available sensors.
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
new file mode 100644
index 0000000..85ac78f
--- /dev/null
+++ b/include/android/sharedmem_jni.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup Memory
+ * @{
+ */
+
+/**
+ * @file sharedmem_jni.h
+ */
+
+#ifndef ANDROID_SHARED_MEMORY_JNI_H
+#define ANDROID_SHARED_MEMORY_JNI_H
+
+#include <jni.h>
+#include <android/sharedmem.h>
+#include <stddef.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
+ */
+
+/**
+ * Structures and functions for a shared memory buffer that can be shared across process.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __ANDROID_API__ >= __ANDROID_API_O_MR1__
+
+/**
+ * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
+ * descriptor has all the same properties & capabilities as the FD returned from
+ * ASharedMemory_create(), however the protection flags will be the same as those of the
+ * android.os.SharedMemory object.
+ *
+ * Use close() to release the shared memory region.
+ *
+ * \param env The JNIEnv* pointer
+ * \param sharedMemory The Java android.os.SharedMemory object
+ * \return file descriptor that denotes the shared memory; -1 if the shared memory object is
+ *      already closed, if the JNIEnv or jobject is NULL, or if there are too many open file
+ *      descriptors (errno=EMFILE)
+ */
+int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory);
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_SHARED_MEMORY_JNI_H
+
+/** @} */
diff --git a/include/batteryservice b/include/batteryservice
new file mode 120000
index 0000000..2178c32
--- /dev/null
+++ b/include/batteryservice
@@ -0,0 +1 @@
+../services/batteryservice/include/batteryservice/
\ No newline at end of file
diff --git a/include/gui b/include/gui
new file mode 120000
index 0000000..3b796f3
--- /dev/null
+++ b/include/gui
@@ -0,0 +1 @@
+../libs/gui/include/gui
\ No newline at end of file
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index 20154eb..c282cf0 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -323,6 +323,7 @@
     DEFINE_KEYCODE(SYSTEM_NAVIGATION_DOWN),
     DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT),
     DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT),
+    DEFINE_KEYCODE(ALL_APPS),
 
     { NULL, 0 }
 };
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index f31bcea..9449474 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -65,6 +65,7 @@
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
+            int32_t displayId;
             int32_t action;
             int32_t flags;
             int32_t keyCode;
@@ -83,6 +84,7 @@
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
+            int32_t displayId;
             int32_t action;
             int32_t actionButton;
             int32_t flags;
@@ -232,6 +234,7 @@
             uint32_t seq,
             int32_t deviceId,
             int32_t source,
+            int32_t displayId,
             int32_t action,
             int32_t actionButton,
             int32_t flags,
@@ -303,7 +306,7 @@
      * Other errors probably indicate that the channel is broken.
      */
     status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
-            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
 
     /* Sends a finished signal to the publisher to inform it that the message
      * with the specified sequence number has finished being process and whether
@@ -367,20 +370,24 @@
         int32_t idToIndex[MAX_POINTER_ID + 1];
         PointerCoords pointers[MAX_POINTERS];
 
-        void initializeFrom(const InputMessage* msg) {
-            eventTime = msg->body.motion.eventTime;
+        void initializeFrom(const InputMessage& msg) {
+            eventTime = msg.body.motion.eventTime;
             idBits.clear();
-            for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
-                uint32_t id = msg->body.motion.pointers[i].properties.id;
+            for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+                uint32_t id = msg.body.motion.pointers[i].properties.id;
                 idBits.markBit(id);
                 idToIndex[id] = i;
-                pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
+                pointers[i].copyFrom(msg.body.motion.pointers[i].coords);
             }
         }
 
         const PointerCoords& getPointerById(uint32_t id) const {
             return pointers[idToIndex[id]];
         }
+
+        bool hasPointerId(uint32_t id) const {
+            return idBits.hasBit(id);
+        }
     };
     struct TouchState {
         int32_t deviceId;
@@ -399,7 +406,7 @@
             lastResample.idBits.clear();
         }
 
-        void addHistory(const InputMessage* msg) {
+        void addHistory(const InputMessage& msg) {
             historyCurrent ^= 1;
             if (historySize < 2) {
                 historySize += 1;
@@ -410,6 +417,24 @@
         const History* getHistory(size_t index) const {
             return &history[(historyCurrent + index) & 1];
         }
+
+        bool recentCoordinatesAreIdentical(uint32_t id) const {
+            // Return true if the two most recently received "raw" coordinates are identical
+            if (historySize < 2) {
+                return false;
+            }
+            if (!getHistory(0)->hasPointerId(id) || !getHistory(1)->hasPointerId(id)) {
+                return false;
+            }
+            float currentX = getHistory(0)->getPointerById(id).getX();
+            float currentY = getHistory(0)->getPointerById(id).getY();
+            float previousX = getHistory(1)->getPointerById(id).getX();
+            float previousY = getHistory(1)->getPointerById(id).getY();
+            if (currentX == previousX && currentY == previousY) {
+                return true;
+            }
+            return false;
+        }
     };
     Vector<TouchState> mTouchStates;
 
@@ -424,12 +449,13 @@
     Vector<SeqChain> mSeqChains;
 
     status_t consumeBatch(InputEventFactoryInterface* factory,
-            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
     status_t consumeSamples(InputEventFactoryInterface* factory,
-            Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
+            Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
+            int32_t* displayId);
 
-    void updateTouchState(InputMessage* msg);
-    void rewriteMessage(const TouchState& state, InputMessage* msg);
+    void updateTouchState(InputMessage& msg);
+    bool rewriteMessage(const TouchState& state, InputMessage& msg);
     void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
             const InputMessage *next);
 
diff --git a/include/media b/include/media
new file mode 120000
index 0000000..3e7da1c
--- /dev/null
+++ b/include/media
@@ -0,0 +1 @@
+../headers/media_plugin/media
\ No newline at end of file
diff --git a/include/private/gui b/include/private/gui
new file mode 120000
index 0000000..99de2dc
--- /dev/null
+++ b/include/private/gui
@@ -0,0 +1 @@
+../../libs/gui/include/private/gui
\ No newline at end of file
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index a86c586..380e745 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -21,6 +21,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <limits>
+
 namespace android {
 // ----------------------------------------------------------------------------
 
diff --git a/include/ui b/include/ui
new file mode 120000
index 0000000..2fb3147
--- /dev/null
+++ b/include/ui
@@ -0,0 +1 @@
+../libs/ui/include/ui
\ No newline at end of file
diff --git a/include_sensor/android/looper.h b/include_sensor/android/looper.h
new file mode 120000
index 0000000..0cf51b8
--- /dev/null
+++ b/include_sensor/android/looper.h
@@ -0,0 +1 @@
+../../include/android/looper.h
\ No newline at end of file
diff --git a/include_sensor/android/sensor.h b/include_sensor/android/sensor.h
new file mode 120000
index 0000000..0626f4f
--- /dev/null
+++ b/include_sensor/android/sensor.h
@@ -0,0 +1 @@
+../../include/android/sensor.h
\ No newline at end of file
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 0d25176..a20154f 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -23,5 +23,6 @@
 cc_library_static {
     name: "libarect",
     host_supported: true,
+    vendor_available: true,
     export_include_dirs: ["include"],
 }
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 204fdb5..83b8021 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -15,6 +15,17 @@
 cc_library_headers {
     name: "libbinder_headers",
     export_include_dirs: ["include"],
+    vendor_available: true,
+    header_libs: [
+        "libbase_headers",
+        "libcutils_headers",
+        "libutils_headers",
+    ],
+    export_header_lib_headers: [
+        "libbase_headers",
+        "libcutils_headers",
+        "libutils_headers",
+    ],
 }
 
 cc_library {
@@ -22,6 +33,9 @@
 
     // for vndbinder
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "AppOpsManager.cpp",
@@ -55,8 +69,13 @@
         "TextOutput.cpp",
         "IpPrefix.cpp",
         "Value.cpp",
+        "aidl/android/content/pm/IPackageManagerNative.aidl",
     ],
 
+    aidl: {
+        export_aidl_headers: true,
+    },
+
     cflags: [
         "-Wall",
         "-Wextra",
@@ -74,13 +93,13 @@
         "libcutils",
         "libutils",
     ],
-    export_shared_lib_headers: [
-        "libbase",
-        "libutils",
+
+    header_libs: [
+        "libbinder_headers",
     ],
 
-    export_include_dirs: [
-        "include",
+    export_header_lib_headers: [
+        "libbinder_headers",
     ],
 
     clang: true,
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index a8f2da5..4ac61a3 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <binder/Debug.h>
+#include <binder/ProcessState.h>
 
 #include <utils/misc.h>
 
@@ -294,5 +295,14 @@
     }
 }
 
+ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
+    sp<ProcessState> proc = ProcessState::selfOrNull();
+    if (proc.get() == NULL) {
+        return 0;
+    }
+
+    return proc->getKernelReferences(count, buf);
+}
+
 }; // namespace android
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index aec8f10..e22179b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1851,7 +1851,7 @@
 
 status_t Parcel::readBool(bool *pArg) const
 {
-    int32_t tmp;
+    int32_t tmp = 0;
     status_t ret = readInt32(&tmp);
     *pArg = (tmp != 0);
     return ret;
@@ -1864,7 +1864,7 @@
 
 status_t Parcel::readChar(char16_t *pArg) const
 {
-    int32_t tmp;
+    int32_t tmp = 0;
     status_t ret = readInt32(&tmp);
     *pArg = char16_t(tmp);
     return ret;
@@ -1877,7 +1877,7 @@
 
 status_t Parcel::readByte(int8_t *pArg) const
 {
-    int32_t tmp;
+    int32_t tmp = 0;
     status_t ret = readInt32(&tmp);
     *pArg = int8_t(tmp);
     return ret;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index add5e74..11dd525 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -90,6 +90,12 @@
     return gProcess;
 }
 
+sp<ProcessState> ProcessState::selfOrNull()
+{
+    Mutex::Autolock _l(gProcessMutex);
+    return gProcess;
+}
+
 void ProcessState::setContextObject(const sp<IBinder>& object)
 {
     setContextObject(object, String16("default"));
@@ -176,6 +182,46 @@
     return mManagesContexts;
 }
 
+// Get references to userspace objects held by the kernel binder driver
+// Writes up to count elements into buf, and returns the total number
+// of references the kernel has, which may be larger than count.
+// buf may be NULL if count is 0.  The pointers returned by this method
+// should only be used for debugging and not dereferenced, they may
+// 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 : NULL;
+    size_t count = 0;
+
+    do {
+        status_t result = ioctl(mDriverFD, BINDER_GET_NODE_DEBUG_INFO, &info);
+        if (result < 0) {
+            return -1;
+        }
+        if (info.ptr != 0) {
+            if (buf && buf < end)
+                *buf++ = info.ptr;
+            count++;
+            if (buf && buf < end)
+                *buf++ = info.cookie;
+            count++;
+        }
+    } while (info.ptr != 0);
+
+    return count;
+}
+
 ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
 {
     const size_t N=mHandleToObject.size();
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
new file mode 100644
index 0000000..3264666
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -0,0 +1,57 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+/**
+ * Parallel implementation of certain {@link PackageManager} APIs that need to
+ * be exposed to native code.
+ * <p>These APIs are a parallel definition to the APIs in PackageManager, so,
+ * they can technically diverge. However, it's good practice to keep these
+ * APIs in sync with each other.
+ * <p>Because these APIs are exposed to native code, it's possible they will
+ * be exposed to privileged components [such as UID 0]. Care should be taken
+ * to avoid exposing potential security holes for methods where permission
+ * checks are bypassed based upon UID alone.
+ *
+ * @hide
+ */
+interface IPackageManagerNative {
+    /**
+     * Returns a set of names for the given UIDs.
+     * IMPORTANT: Unlike the Java version of this API, unknown UIDs are
+     * not represented by 'null's. Instead, they are represented by empty
+     * strings.
+     */
+    @utf8InCpp String[] getNamesForUids(in int[] uids);
+
+    /**
+     * Returns the name of the installer (a package) which installed the named
+     * package. Preloaded packages return the string "preload". Sideloaded packages
+     * return an empty string. Unknown or unknowable are returned as empty strings.
+     */
+
+    @utf8InCpp String getInstallerForPackage(in String packageName);
+
+    /**
+     * Returns the version code of the named package.
+     * Unknown or unknowable versions are returned as 0.
+     */
+
+    int getVersionCodeForPackage(in String packageName);
+
+}
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
index f6a3355..be0266c 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/include/binder/Debug.h
@@ -18,14 +18,13 @@
 #define ANDROID_BINDER_DEBUG_H
 
 #include <stdint.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 const char* stringForIndent(int32_t indentLevel);
 
@@ -39,9 +38,10 @@
     size_t alignment=0, bool cArrayStyle=false,
     debugPrintFunc func = 0, void* cookie = 0);
 
-#ifdef __cplusplus
-}
-#endif
+
+ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
+
+__END_DECLS
 
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/binder/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
index d5b57ac..a9166e2 100644
--- a/libs/binder/include/binder/Parcelable.h
+++ b/libs/binder/include/binder/Parcelable.h
@@ -36,6 +36,9 @@
 public:
     virtual ~Parcelable() = default;
 
+    Parcelable() = default;
+    Parcelable(const Parcelable&) = default;
+
     // Write |this| parcelable to the given |parcel|.  Keep in mind that
     // implementations of writeToParcel must be manually kept in sync
     // with readFromParcel and the Java equivalent versions of these methods.
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 1ef045d..f85c261 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -35,6 +35,7 @@
 {
 public:
     static  sp<ProcessState>    self();
+    static  sp<ProcessState>    selfOrNull();
     /* initWithDriver() can be used to configure libbinder to use
      * a different binder driver dev node. It must be called *before*
      * any call to ProcessState::self(). /dev/binder remains the default.
@@ -71,6 +72,8 @@
 
             String8             getDriverName();
 
+            ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
+
 private:
     friend class IPCThreadState;
     
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index bef9505..3071408 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -42,6 +42,23 @@
 }
 
 cc_test {
+    name: "binderLibTest_IPC_32",
+    srcs: ["binderLibTest.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+    compile_multilib: "32",
+    cflags: ["-DBINDER_IPC_32BIT=1"],
+}
+
+cc_test {
+    product_variables: {
+        binder32bit: {
+            cflags: ["-DBINDER_IPC_32BIT=1"],
+        },
+    },
+
     name: "binderLibTest",
     srcs: ["binderLibTest.cpp"],
     shared_libs: [
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index 6e8f7df..455f2c4 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -101,18 +101,21 @@
 };
 
 static const uint32_t num_buckets = 128;
-static const uint64_t max_time_bucket = 50ull * 1000000;
-static const uint64_t time_per_bucket = max_time_bucket / num_buckets;
-static constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6;
+static uint64_t max_time_bucket = 50ull * 1000000;
+static uint64_t time_per_bucket = max_time_bucket / num_buckets;
 
 struct ProcResults {
-    uint64_t m_best = max_time_bucket;
     uint64_t m_worst = 0;
     uint32_t m_buckets[num_buckets] = {0};
     uint64_t m_transactions = 0;
+    uint64_t m_long_transactions = 0;
     uint64_t m_total_time = 0;
+    uint64_t m_best = max_time_bucket;
 
     void add_time(uint64_t time) {
+        if (time > max_time_bucket) {
+            m_long_transactions++;
+        }
         m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1;
         m_best = min(time, m_best);
         m_worst = max(time, m_worst);
@@ -127,16 +130,24 @@
         ret.m_worst = max(a.m_worst, b.m_worst);
         ret.m_best = min(a.m_best, b.m_best);
         ret.m_transactions = a.m_transactions + b.m_transactions;
+        ret.m_long_transactions = a.m_long_transactions + b.m_long_transactions;
         ret.m_total_time = a.m_total_time + b.m_total_time;
         return ret;
     }
     void dump() {
+        if (m_long_transactions > 0) {
+            cout << (double)m_long_transactions / m_transactions << "% of transactions took longer "
+                "than estimated max latency. Consider setting -m to be higher than "
+                 << m_worst / 1000 << " microseconds" << endl;
+        }
+
         double best = (double)m_best / 1.0E6;
         double worst = (double)m_worst / 1.0E6;
         double average = (double)m_total_time / m_transactions / 1.0E6;
         cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl;
 
         uint64_t cur_total = 0;
+        float time_per_bucket_ms = time_per_bucket / 1.0E6;
         for (int i = 0; i < num_buckets; i++) {
             float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms;
             if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) {
@@ -154,7 +165,6 @@
             cur_total += m_buckets[i];
         }
         cout << endl;
-
     }
 };
 
@@ -166,13 +176,12 @@
     return serviceName;
 }
 
-void worker_fx(
-    int num,
-    int worker_count,
-    int iterations,
-    int payload_size,
-    bool cs_pair,
-    Pipe p)
+void worker_fx(int num,
+               int worker_count,
+               int iterations,
+               int payload_size,
+               bool cs_pair,
+               Pipe p)
 {
     // Create BinderWorkerService and for go.
     ProcessState::self()->startThreadPool();
@@ -204,12 +213,12 @@
     for (int i = 0; (!cs_pair || num >= server_count) && i < iterations; i++) {
         Parcel data, reply;
         int target = cs_pair ? num % server_count : rand() % workers.size();
-	int sz = payload_size;
+        int sz = payload_size;
 
-	while (sz > sizeof(uint32_t)) {
-		data.writeInt32(0);
-		sz -= sizeof(uint32_t);
-	}
+        while (sz > sizeof(uint32_t)) {
+            data.writeInt32(0);
+            sz -= sizeof(uint32_t);
+        }
         start = chrono::high_resolution_clock::now();
         status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
         end = chrono::high_resolution_clock::now();
@@ -264,47 +273,19 @@
     }
 }
 
-int main(int argc, char *argv[])
+void run_main(int iterations,
+              int workers,
+              int payload_size,
+              int cs_pair,
+              bool training_round=false)
 {
-    int workers = 2;
-    int iterations = 10000;
-    int payload_size = 0;
-    bool cs_pair = false;
-    (void)argc;
-    (void)argv;
     vector<Pipe> pipes;
-
-    // Parse arguments.
-    for (int i = 1; i < argc; i++) {
-        if (string(argv[i]) == "-w") {
-            workers = atoi(argv[i+1]);
-            i++;
-            continue;
-        }
-        if (string(argv[i]) == "-i") {
-            iterations = atoi(argv[i+1]);
-            i++;
-            continue;
-        }
-        if (string(argv[i]) == "-s") {
-            payload_size = atoi(argv[i+1]);
-	    i++;
-	}
-        if (string(argv[i]) == "-p") {
-		// client/server pairs instead of spreading
-		// requests to all workers. If true, half
-		// the workers become clients and half servers
-		cs_pair = true;
-	}
-    }
-
     // Create all the workers and wait for them to spawn.
     for (int i = 0; i < workers; i++) {
         pipes.push_back(make_worker(i, iterations, workers, payload_size, cs_pair));
     }
     wait_all(pipes);
 
-
     // Run the workers and wait for completion.
     chrono::time_point<chrono::high_resolution_clock> start, end;
     cout << "waiting for workers to complete" << endl;
@@ -326,7 +307,6 @@
         pipes[i].recv(tmp_results);
         tot_results = ProcResults::combine(tot_results, tmp_results);
     }
-    tot_results.dump();
 
     // Kill all the workers.
     cout << "killing workers" << endl;
@@ -338,5 +318,83 @@
             cout << "nonzero child status" << status << endl;
         }
     }
+    if (training_round) {
+        // sets max_time_bucket to 2 * m_worst from the training round.
+        // Also needs to adjust time_per_bucket accordingly.
+        max_time_bucket = 2 * tot_results.m_worst;
+        time_per_bucket = max_time_bucket / num_buckets;
+        cout << "Max latency during training: " << tot_results.m_worst / 1.0E6 << "ms" << endl;
+    } else {
+            tot_results.dump();
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int workers = 2;
+    int iterations = 10000;
+    int payload_size = 0;
+    bool cs_pair = false;
+    bool training_round = false;
+    (void)argc;
+    (void)argv;
+
+    // Parse arguments.
+    for (int i = 1; i < argc; i++) {
+        if (string(argv[i]) == "--help") {
+            cout << "Usage: binderThroughputTest [OPTIONS]" << endl;
+            cout << "\t-i N    : Specify number of iterations." << endl;
+            cout << "\t-m N    : Specify expected max latency in microseconds." << endl;
+            cout << "\t-p      : Split workers into client/server pairs." << endl;
+            cout << "\t-s N    : Specify payload size." << endl;
+            cout << "\t-t N    : Run training round." << endl;
+            cout << "\t-w N    : Specify total number of workers." << endl;
+            return 0;
+        }
+        if (string(argv[i]) == "-w") {
+            workers = atoi(argv[i+1]);
+            i++;
+            continue;
+        }
+        if (string(argv[i]) == "-i") {
+            iterations = atoi(argv[i+1]);
+            i++;
+            continue;
+        }
+        if (string(argv[i]) == "-s") {
+            payload_size = atoi(argv[i+1]);
+            i++;
+        }
+        if (string(argv[i]) == "-p") {
+            // client/server pairs instead of spreading
+            // requests to all workers. If true, half
+            // the workers become clients and half servers
+            cs_pair = true;
+        }
+        if (string(argv[i]) == "-t") {
+            // Run one training round before actually collecting data
+            // to get an approximation of max latency.
+            training_round = true;
+        }
+        if (string(argv[i]) == "-m") {
+            // Caller specified the max latency in microseconds.
+            // No need to run training round in this case.
+            if (atoi(argv[i+1]) > 0) {
+                max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
+                i++;
+            } else {
+                cout << "Max latency -m must be positive." << endl;
+                exit(EXIT_FAILURE);
+            }
+        }
+    }
+
+    if (training_round) {
+        cout << "Start training round" << endl;
+        run_main(iterations, workers, payload_size, cs_pair, training_round=true);
+        cout << "Completed training round" << endl << endl;
+    }
+
+    run_main(iterations, workers, payload_size, cs_pair);
     return 0;
 }
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
new file mode 100644
index 0000000..f2686d5
--- /dev/null
+++ b/libs/graphicsenv/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libgraphicsenv",
+
+    srcs: [
+        "GraphicsEnv.cpp",
+    ],
+
+    shared_libs: [
+        "libnativeloader",
+        "liblog",
+    ],
+
+    export_include_dirs: ["include"],
+}
diff --git a/libs/ui/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
similarity index 98%
rename from libs/ui/GraphicsEnv.cpp
rename to libs/graphicsenv/GraphicsEnv.cpp
index 8182c07..39b5829 100644
--- a/libs/ui/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -16,7 +16,7 @@
 
 //#define LOG_NDEBUG 1
 #define LOG_TAG "GraphicsEnv"
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
 
 #include <mutex>
 
diff --git a/include/ui/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
similarity index 100%
rename from include/ui/GraphicsEnv.h
rename to libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index a07726a..3996305 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -11,9 +11,18 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+cc_library_headers {
+    name: "libgui_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+}
 
 cc_library_shared {
     name: "libgui",
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     clang: true,
     cppflags: [
@@ -111,20 +120,30 @@
         "liblog",
         "libhidlbase",
         "libhidltransport",
-        "android.hidl.base@1.0",
         "android.hidl.token@1.0-utils",
         "android.hardware.graphics.bufferqueue@1.0",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
     ],
 
+    header_libs: [
+        "libnativebase_headers",
+        "libgui_headers",
+    ],
+
     export_shared_lib_headers: [
         "libbinder",
+        "libEGL",
+        "libnativewindow",
         "libui",
         "android.hidl.token@1.0-utils",
         "android.hardware.graphics.bufferqueue@1.0",
     ],
 
+    export_header_lib_headers: [
+        "libgui_headers",
+    ],
+
     export_include_dirs: [
         "include",
     ],
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index d9d50db..da42956 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -19,6 +19,8 @@
 //#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #include <utils/Log.h>
 
+#include <inttypes.h>
+
 #include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 
@@ -31,13 +33,13 @@
 namespace android {
 
 BufferItemConsumer::BufferItemConsumer(
-        const sp<IGraphicBufferConsumer>& consumer, uint32_t consumerUsage,
+        const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
         int bufferCount, bool controlledByApp) :
     ConsumerBase(consumer, controlledByApp)
 {
     status_t err = mConsumer->setConsumerUsageBits(consumerUsage);
     LOG_ALWAYS_FATAL_IF(err != OK,
-            "Failed to set consumer usage bits to %#x", consumerUsage);
+            "Failed to set consumer usage bits to %#" PRIx64, consumerUsage);
     if (bufferCount != DEFAULT_MAX_BUFFERS) {
         err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
         LOG_ALWAYS_FATAL_IF(err != OK,
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 5e5de44..17cf677 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -15,6 +15,8 @@
  */
 
 #include <inttypes.h>
+#include <pwd.h>
+#include <sys/types.h>
 
 #define LOG_TAG "BufferQueueConsumer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -34,7 +36,8 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/PermissionCache.h>
-#include <private/android_filesystem_config.h>
+
+#include <system/window.h>
 
 namespace android {
 
@@ -701,9 +704,9 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
+status_t BufferQueueConsumer::setConsumerUsageBits(uint64_t usage) {
     ATRACE_CALL();
-    BQ_LOGV("setConsumerUsageBits: %#x", usage);
+    BQ_LOGV("setConsumerUsageBits: %#" PRIx64, usage);
     Mutex::Autolock lock(mCore->mMutex);
     mCore->mConsumerUsageBits = usage;
     return NO_ERROR;
@@ -745,12 +748,19 @@
 }
 
 status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
+    struct passwd* pwd = getpwnam("shell");
+    uid_t shellUid = pwd ? pwd->pw_uid : 0;
+    if (!shellUid) {
+        int savedErrno = errno;
+        BQ_LOGE("Cannot get AID_SHELL");
+        return savedErrno ? -savedErrno : UNKNOWN_ERROR;
+    }
+
     const IPCThreadState* ipc = IPCThreadState::self();
     const pid_t pid = ipc->getCallingPid();
     const uid_t uid = ipc->getCallingUid();
-    if ((uid != AID_SHELL)
-            && !PermissionCache::checkPermission(String16(
-            "android.permission.DUMP"), pid, uid)) {
+    if ((uid != shellUid) &&
+        !PermissionCache::checkPermission(String16("android.permission.DUMP"), pid, uid)) {
         outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
         android_errorWriteWithInfoLog(0x534e4554, "27046057",
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index cfb25e0..bb703da 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -38,6 +38,8 @@
 #include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 
+#include <system/window.h>
+
 namespace android {
 
 static String8 getUniqueName() {
@@ -110,54 +112,60 @@
 void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
     Mutex::Autolock lock(mMutex);
 
-    String8 fifo;
+    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  default-size=[%dx%d] default-format=%d ", prefix.string(),
+                            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
+    outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
+                            mFrameCounter);
+
+    outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
     Fifo::const_iterator current(mQueue.begin());
     while (current != mQueue.end()) {
-        fifo.appendFormat("%02d:%p crop=[%d,%d,%d,%d], "
-                "xform=0x%02x, time=%#" PRIx64 ", scale=%s\n",
-                current->mSlot, current->mGraphicBuffer.get(),
-                current->mCrop.left, current->mCrop.top, current->mCrop.right,
-                current->mCrop.bottom, current->mTransform, current->mTimestamp,
-                BufferItem::scalingModeName(current->mScalingMode));
+        double timestamp = current->mTimestamp / 1e9;
+        outResult->appendFormat("%s  %02d:%p ", prefix.string(), current->mSlot,
+                                current->mGraphicBuffer.get());
+        outResult->appendFormat("crop=[%d,%d,%d,%d] ", current->mCrop.left, current->mCrop.top,
+                                current->mCrop.right, current->mCrop.bottom);
+        outResult->appendFormat("xform=0x%02x time=%.4f scale=%s\n", current->mTransform, timestamp,
+                                BufferItem::scalingModeName(current->mScalingMode));
         ++current;
     }
 
-    outResult->appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
-            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
-            "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
-            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix.string(),
-            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
-            mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
-            mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
-            fifo.string());
-
+    outResult->appendFormat("%sSlots:\n", prefix.string());
     for (int s : mActiveBuffers) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
         // A dequeued buffer might be null if it's still being allocated
         if (buffer.get()) {
-            outResult->appendFormat("%s%s[%02d:%p] state=%-8s, %p "
-                    "[%4ux%4u:%4u,%3X]\n", prefix.string(),
-                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
-                    buffer.get(), mSlots[s].mBufferState.string(),
-                    buffer->handle, buffer->width, buffer->height,
-                    buffer->stride, buffer->format);
+            outResult->appendFormat("%s %s[%02d:%p] ", prefix.string(),
+                                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
+                                    buffer.get());
+            outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+                                    buffer->handle, mSlots[s].mFrameNumber);
+            outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+                                    buffer->stride, buffer->format);
         } else {
-            outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
-                    buffer.get(), mSlots[s].mBufferState.string());
+            outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
+            outResult->appendFormat("state=%-8s frame=%" PRIu64 "\n",
+                                    mSlots[s].mBufferState.string(), mSlots[s].mFrameNumber);
         }
     }
     for (int s : mFreeBuffers) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        outResult->appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
-                prefix.string(), s, buffer.get(), mSlots[s].mBufferState.string(),
-                buffer->handle, buffer->width, buffer->height, buffer->stride,
-                buffer->format);
+        outResult->appendFormat("%s  [%02d:%p] ", prefix.string(), s, buffer.get());
+        outResult->appendFormat("state=%-8s %p frame=%" PRIu64, mSlots[s].mBufferState.string(),
+                                buffer->handle, mSlots[s].mFrameNumber);
+        outResult->appendFormat(" [%4ux%4u:%4u,%3X]\n", buffer->width, buffer->height,
+                                buffer->stride, buffer->format);
     }
 
     for (int s : mFreeSlots) {
         const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
-        outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
-                buffer.get(), mSlots[s].mBufferState.string());
+        outResult->appendFormat("%s  [%02d:%p] state=%-8s\n", prefix.string(), s, buffer.get(),
+                                mSlots[s].mBufferState.string());
     }
 }
 
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 8385864..625dc5b 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -39,6 +39,8 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include <system/window.h>
+
 namespace android {
 
 static constexpr uint32_t BQ_LAYER_COUNT = 1;
@@ -345,10 +347,10 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
-        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
+status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
+                                            uint32_t width, uint32_t height, PixelFormat format,
+                                            uint64_t usage, uint64_t* outBufferAge,
+                                            FrameEventHistoryDelta* outTimestamps) {
     ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
@@ -365,8 +367,7 @@
         }
     } // Autolock scope
 
-    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
-            format, usage);
+    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#" PRIx64, width, height, format, usage);
 
     if ((width && !height) || (!width && height)) {
         BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
@@ -416,11 +417,9 @@
             // buffer. If this buffer would require reallocation to meet the
             // requested attributes, we free it and attempt to get another one.
             if (!mCore->mAllowAllocation) {
-                if (buffer->needsReallocation(width, height, format,
-                        BQ_LAYER_COUNT, usage)) {
+                if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
                     if (mCore->mSharedBufferSlot == found) {
-                        BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
-                                "buffer");
+                        BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
                         return BAD_VALUE;
                     }
                     mCore->mFreeSlots.insert(found);
@@ -433,8 +432,7 @@
 
         const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
         if (mCore->mSharedBufferSlot == found &&
-                buffer->needsReallocation(width, height, format,
-                        BQ_LAYER_COUNT, usage)) {
+                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
             BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                     "buffer");
 
@@ -468,8 +466,7 @@
         } else {
             // We add 1 because that will be the frame number when this buffer
             // is queued
-            mCore->mBufferAge =
-                    mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
+            mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
         }
 
         BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
@@ -561,6 +558,9 @@
             mSlots[*outSlot].mFrameNumber,
             mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
 
+    if (outBufferAge) {
+        *outBufferAge = mCore->mBufferAge;
+    }
     addAndGetFrameTimestamps(nullptr, outTimestamps);
 
     return returnFlags;
@@ -1102,6 +1102,7 @@
             value = (mCore->mQueue.size() > 1);
             break;
         case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
+            // deprecated; higher 32 bits are truncated
             value = static_cast<int32_t>(mCore->mConsumerUsageBits);
             break;
         case NATIVE_WINDOW_DEFAULT_DATASPACE:
@@ -1319,14 +1320,14 @@
 }
 
 void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage) {
+        PixelFormat format, uint64_t usage) {
     ATRACE_CALL();
     while (true) {
         size_t newBufferCount = 0;
         uint32_t allocWidth = 0;
         uint32_t allocHeight = 0;
         PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
-        uint32_t allocUsage = 0;
+        uint64_t allocUsage = 0;
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
             mCore->waitWhileAllocatingLocked();
@@ -1360,7 +1361,7 @@
 
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
-                        " %u, usage %u)", width, height, format, usage);
+                        " %u, usage %#" PRIx64 ")", width, height, format, usage);
                 Mutex::Autolock lock(mCore->mMutex);
                 mCore->mIsAllocating = false;
                 mCore->mIsAllocatingCondition.broadcast();
@@ -1375,7 +1376,7 @@
             uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
             PixelFormat checkFormat = format != 0 ?
                     format : mCore->mDefaultBufferFormat;
-            uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
+            uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
             if (checkWidth != allocWidth || checkHeight != allocHeight ||
                 checkFormat != allocFormat || checkUsage != allocUsage) {
                 // Something changed while we released the lock. Retry.
@@ -1547,4 +1548,12 @@
     return NO_ERROR;
 }
 
+status_t BufferQueueProducer::getConsumerUsage(uint64_t* outUsage) const {
+    BQ_LOGV("getConsumerUsage");
+
+    Mutex::Autolock lock(mCore->mMutex);
+    *outUsage = mCore->mConsumerUsageBits;
+    return NO_ERROR;
+}
+
 } // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index c2b10a9..7aa7872 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -106,7 +106,7 @@
 
     sp<FrameAvailableListener> listener;
     { // scope for the lock
-        Mutex::Autolock lock(mMutex);
+        Mutex::Autolock lock(mFrameAvailableMutex);
         listener = mFrameAvailableListener.promote();
     }
 
@@ -121,7 +121,7 @@
 
     sp<FrameAvailableListener> listener;
     {
-        Mutex::Autolock lock(mMutex);
+        Mutex::Autolock lock(mFrameAvailableMutex);
         listener = mFrameAvailableListener.promote();
     }
 
@@ -185,7 +185,7 @@
 void ConsumerBase::setFrameAvailableListener(
         const wp<FrameAvailableListener>& listener) {
     CB_LOGV("setFrameAvailableListener");
-    Mutex::Autolock lock(mMutex);
+    Mutex::Autolock lock(mFrameAvailableMutex);
     mFrameAvailableListener = listener;
 }
 
@@ -335,16 +335,25 @@
         return OK;
     }
 
-    auto status = mSlots[slot].mFence->getStatus();
-
-    if (status == Fence::Status::Invalid) {
-        CB_LOGE("fence has invalid state");
+    // Check status of fences first because merging is expensive.
+    // Merging an invalid fence with any other fence results in an
+    // invalid fence.
+    auto currentStatus = mSlots[slot].mFence->getStatus();
+    if (currentStatus == Fence::Status::Invalid) {
+        CB_LOGE("Existing fence has invalid state");
         return BAD_VALUE;
     }
 
-    if (status == Fence::Status::Signaled) {
+    auto incomingStatus = fence->getStatus();
+    if (incomingStatus == Fence::Status::Invalid) {
+        CB_LOGE("New fence has invalid state");
         mSlots[slot].mFence = fence;
-    } else {  // status == Fence::Status::Unsignaled
+        return BAD_VALUE;
+    }
+
+    // If both fences are signaled or both are unsignaled, we need to merge
+    // them to get an accurate timestamp.
+    if (currentStatus == incomingStatus) {
         char fenceName[32] = {};
         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
         sp<Fence> mergedFence = Fence::merge(
@@ -357,7 +366,17 @@
             return BAD_VALUE;
         }
         mSlots[slot].mFence = mergedFence;
+    } else if (incomingStatus == Fence::Status::Unsignaled) {
+        // If one fence has signaled and the other hasn't, the unsignaled
+        // fence will approximately correspond with the correct timestamp.
+        // There's a small race if both fences signal at about the same time
+        // and their statuses are retrieved with unfortunate timing. However,
+        // by this point, they will have both signaled and only the timestamp
+        // will be slightly off; any dependencies after this point will
+        // already have been met.
+        mSlots[slot].mFence = fence;
     }
+    // else if (currentStatus == Fence::Status::Unsignaled) is a no-op.
 
     return OK;
 }
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index c654f08..14d9937 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -21,6 +21,8 @@
 #define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
 
+#include <inttypes.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
@@ -41,7 +43,7 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
@@ -1113,7 +1115,7 @@
     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
 }
 
-status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
+status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
     Mutex::Autolock lock(mMutex);
     if (mAbandoned) {
         GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
@@ -1219,7 +1221,7 @@
         mEglDisplay = EGL_NO_DISPLAY;
         mCropRect.makeInvalid();
         const sp<GraphicBuffer>& buffer = mGraphicBuffer;
-        ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
+        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 UNKNOWN_ERROR;
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index a573bee..c705d39 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -132,7 +132,7 @@
         return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
     }
 
-    status_t setConsumerUsageBits(uint32_t usage) override {
+    status_t setConsumerUsageBits(uint64_t usage) override {
         using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
         return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
     }
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index bca645f..71e22ce 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -62,7 +62,8 @@
     SET_DEQUEUE_TIMEOUT,
     GET_LAST_QUEUED_BUFFER,
     GET_FRAME_TIMESTAMPS,
-    GET_UNIQUE_ID
+    GET_UNIQUE_ID,
+    GET_CONSUMER_USAGE,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -73,7 +74,7 @@
     {
     }
 
-    virtual ~BpGraphicBufferProducer();
+    ~BpGraphicBufferProducer() override;
 
     virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
         Parcel data, reply;
@@ -124,9 +125,9 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta* outTimestamps) {
+    virtual status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) {
         Parcel data, reply;
         bool getFrameTimestamps = (outTimestamps != nullptr);
 
@@ -134,7 +135,7 @@
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(usage);
+        data.writeUint64(usage);
         data.writeBool(getFrameTimestamps);
 
         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
@@ -149,6 +150,17 @@
             fence->clear();
             return result;
         }
+        if (outBufferAge) {
+            result = reply.readUint64(outBufferAge);
+        } else {
+            // Read the value even if outBufferAge is nullptr:
+            uint64_t bufferAge;
+            result = reply.readUint64(&bufferAge);
+        }
+        if (result != NO_ERROR) {
+            ALOGE("IGBP::dequeueBuffer failed to read buffer age: %d", result);
+            return result;
+        }
         if (getFrameTimestamps) {
             result = reply.read(*outTimestamps);
             if (result != NO_ERROR) {
@@ -333,13 +345,13 @@
     }
 
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) {
+            PixelFormat format, uint64_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(usage);
+        data.writeUint64(usage);
         status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
         if (result != NO_ERROR) {
             ALOGE("allocateBuffers failed to transact: %d", result);
@@ -493,6 +505,25 @@
         }
         return actualResult;
     }
+
+    virtual status_t getConsumerUsage(uint64_t* outUsage) const {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_CONSUMER_USAGE, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getConsumerUsage failed to transact: %d", result);
+        }
+        status_t actualResult = NO_ERROR;
+        result = reply.readInt32(&actualResult);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readUint64(outUsage);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        return actualResult;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -516,11 +547,10 @@
         return mBase->setAsyncMode(async);
     }
 
-    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta* outTimestamps) override {
-        return mBase->dequeueBuffer(
-                slot, fence, w, h, format, usage, outTimestamps);
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
+                           uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        return mBase->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
     }
 
     status_t detachBuffer(int slot) override {
@@ -569,7 +599,7 @@
     }
 
     void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) override {
+            PixelFormat format, uint64_t usage) override {
         return mBase->allocateBuffers(width, height, format, usage);
     }
 
@@ -612,6 +642,10 @@
     status_t getUniqueId(uint64_t* outId) const override {
         return mBase->getUniqueId(outId);
     }
+
+    status_t getConsumerUsage(uint64_t* outUsage) const override {
+        return mBase->getConsumerUsage(outUsage);
+    }
 };
 
 IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer,
@@ -654,17 +688,19 @@
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t usage = data.readUint32();
+            uint64_t usage = data.readUint64();
+            uint64_t bufferAge = 0;
             bool getTimestamps = data.readBool();
 
             int buf = 0;
             sp<Fence> fence = Fence::NO_FENCE;
             FrameEventHistoryDelta frameTimestamps;
-            int result = dequeueBuffer(&buf, &fence, width, height, format,
-                    usage, getTimestamps ? &frameTimestamps : nullptr);
+            int result = dequeueBuffer(&buf, &fence, width, height, format, usage, &bufferAge,
+                                       getTimestamps ? &frameTimestamps : nullptr);
 
             reply->writeInt32(buf);
             reply->write(*fence);
+            reply->writeUint64(bufferAge);
             if (getTimestamps) {
                 reply->write(frameTimestamps);
             }
@@ -777,7 +813,7 @@
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t usage = data.readUint32();
+            uint64_t usage = data.readUint64();
             allocateBuffers(width, height, format, usage);
             return NO_ERROR;
         }
@@ -877,6 +913,20 @@
             }
             return NO_ERROR;
         }
+        case GET_CONSUMER_USAGE: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            uint64_t outUsage = 0;
+            status_t actualResult = getConsumerUsage(&outUsage);
+            status_t result = reply->writeInt32(actualResult);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            result = reply->writeUint64(outUsage);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index bafe947..52c9067 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -31,6 +31,8 @@
 
 #include <utils/Trace.h>
 
+#include <system/window.h>
+
 namespace android {
 
 status_t StreamSplitter::createSplitter(
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 7b2b5c3..5b1c599 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -20,6 +20,8 @@
 
 #include <gui/Surface.h>
 
+#include <inttypes.h>
+
 #include <android/native_window.h>
 
 #include <utils/Log.h>
@@ -42,21 +44,19 @@
 
 namespace android {
 
-Surface::Surface(
-        const sp<IGraphicBufferProducer>& bufferProducer,
-        bool controlledByApp)
-    : mGraphicBufferProducer(bufferProducer),
-      mCrop(Rect::EMPTY_RECT),
-      mGenerationNumber(0),
-      mSharedBufferMode(false),
-      mAutoRefresh(false),
-      mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
-      mSharedBufferHasBeenQueued(false),
-      mQueriedSupportedTimestamps(false),
-      mFrameTimestampsSupportsPresent(false),
-      mEnableFrameTimestamps(false),
-      mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
-{
+Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
+      : mGraphicBufferProducer(bufferProducer),
+        mCrop(Rect::EMPTY_RECT),
+        mBufferAge(0),
+        mGenerationNumber(0),
+        mSharedBufferMode(false),
+        mAutoRefresh(false),
+        mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
+        mSharedBufferHasBeenQueued(false),
+        mQueriedSupportedTimestamps(false),
+        mFrameTimestampsSupportsPresent(false),
+        mEnableFrameTimestamps(false),
+        mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
@@ -471,7 +471,7 @@
     uint32_t reqWidth;
     uint32_t reqHeight;
     PixelFormat reqFormat;
-    uint32_t reqUsage;
+    uint64_t reqUsage;
     bool enableFrameTimestamps;
 
     {
@@ -504,15 +504,16 @@
     nsecs_t startTime = systemTime();
 
     FrameEventHistoryDelta frameTimestamps;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
-            reqWidth, reqHeight, reqFormat, reqUsage,
-            enableFrameTimestamps ? &frameTimestamps : nullptr);
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
+                                                            reqFormat, reqUsage, &mBufferAge,
+                                                            enableFrameTimestamps ? &frameTimestamps
+                                                                                  : nullptr);
     mLastDequeueDuration = systemTime() - startTime;
 
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
-                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
-                reqUsage, result);
+                "(%d, %d, %d, %#" PRIx64 ") failed: %d",
+                reqWidth, reqHeight, reqFormat, reqUsage, result);
         return result;
     }
 
@@ -843,6 +844,14 @@
                 }
                 return err;
             }
+            case NATIVE_WINDOW_BUFFER_AGE: {
+                if (mBufferAge > INT32_MAX) {
+                    *value = 0;
+                } else {
+                    *value = static_cast<int32_t>(mBufferAge);
+                }
+                return NO_ERROR;
+            }
             case NATIVE_WINDOW_LAST_DEQUEUE_DURATION: {
                 int64_t durationUs = mLastDequeueDuration / 1000;
                 *value = durationUs > std::numeric_limits<int>::max() ?
@@ -962,6 +971,12 @@
     case NATIVE_WINDOW_GET_HDR_SUPPORT:
         res = dispatchGetHdrSupport(args);
         break;
+    case NATIVE_WINDOW_SET_USAGE64:
+        res = dispatchSetUsage64(args);
+        break;
+    case NATIVE_WINDOW_GET_CONSUMER_USAGE64:
+        res = dispatchGetConsumerUsage64(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -980,8 +995,13 @@
 }
 
 int Surface::dispatchSetUsage(va_list args) {
-    int usage = va_arg(args, int);
-    return setUsage(static_cast<uint32_t>(usage));
+    uint64_t usage = va_arg(args, uint32_t);
+    return setUsage(usage);
+}
+
+int Surface::dispatchSetUsage64(va_list args) {
+    uint64_t usage = va_arg(args, uint64_t);
+    return setUsage(usage);
 }
 
 int Surface::dispatchSetCrop(va_list args) {
@@ -1135,6 +1155,11 @@
     return getHdrSupport(outSupport);
 }
 
+int Surface::dispatchGetConsumerUsage64(va_list args) {
+    uint64_t* usage = va_arg(args, uint64_t*);
+    return getConsumerUsage(usage);
+}
+
 int Surface::connect(int api) {
     static sp<IProducerListener> listener = new DummyProducerListener();
     return connect(api, listener);
@@ -1259,8 +1284,7 @@
     uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
     graphicBuffer->mGenerationNumber = mGenerationNumber;
     int32_t attachedSlot = -1;
-    status_t result = mGraphicBufferProducer->attachBuffer(
-            &attachedSlot, graphicBuffer);
+    status_t result = mGraphicBufferProducer->attachBuffer(&attachedSlot, graphicBuffer);
     if (result != NO_ERROR) {
         ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
         graphicBuffer->mGenerationNumber = priorGeneration;
@@ -1274,7 +1298,7 @@
     return NO_ERROR;
 }
 
-int Surface::setUsage(uint32_t reqUsage)
+int Surface::setUsage(uint64_t reqUsage)
 {
     ALOGV("Surface::setUsage");
     Mutex::Autolock lock(mMutex);
@@ -1521,6 +1545,9 @@
         const Region& reg,
         int *dstFenceFd)
 {
+    if (dst->getId() == src->getId())
+        return OK;
+
     // src and dst with, height and format must be identical. no verification
     // is done here.
     status_t err;
@@ -1702,6 +1729,11 @@
     return mGraphicBufferProducer->getUniqueId(outId);
 }
 
+int Surface::getConsumerUsage(uint64_t* outUsage) const {
+    Mutex::Autolock lock(mMutex);
+    return mGraphicBufferProducer->getConsumerUsage(outUsage);
+}
+
 nsecs_t Surface::getLastDequeueStartTime() const {
     Mutex::Autolock lock(mMutex);
     return mLastDequeueStartTime;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8c83843..7ae2672 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1080,5 +1080,9 @@
     return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
 }
 
+android_dataspace ScreenshotClient::getDataSpace() const {
+    return mBuffer.dataSpace;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp
index 187b211..afa15c5 100644
--- a/libs/gui/SyncFeatures.cpp
+++ b/libs/gui/SyncFeatures.cpp
@@ -27,7 +27,7 @@
 
 #include <private/gui/SyncFeatures.h>
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 namespace android {
 
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index fda5b94..3b89291 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -21,6 +21,8 @@
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
 #include <gui/bufferqueue/1.0/B2HProducerListener.h>
 
+#include <system/window.h>
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -125,7 +127,7 @@
     t->attr.stride = l.getStride();
     t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
     t->attr.layerCount = l.getLayerCount();
-    t->attr.usage = l.getUsage();
+    t->attr.usage = uint32_t(l.getUsage());     // FIXME: need 64-bits usage version
     t->attr.id = l.getId();
     t->attr.generationNumber = l.getGenerationNumber();
     t->nativeHandle = hidl_handle(l.handle);
@@ -988,14 +990,15 @@
     return toStatusT(mBase->setAsyncMode(async));
 }
 
-status_t H2BGraphicBufferProducer::dequeueBuffer(
-        int* slot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, ::android::PixelFormat format,
-        uint32_t usage, FrameEventHistoryDelta* outTimestamps) {
+// FIXME: usage bits truncated -- needs a 64-bits usage version
+status_t H2BGraphicBufferProducer::dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+                                                 uint32_t h, ::android::PixelFormat format,
+                                                 uint64_t usage, uint64_t* outBufferAge,
+                                                 FrameEventHistoryDelta* outTimestamps) {
     *fence = new Fence();
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->dequeueBuffer(
-            w, h, static_cast<PixelFormat>(format), usage,
+            w, h, static_cast<PixelFormat>(format), uint32_t(usage),
             outTimestamps != nullptr,
             [&fnStatus, slot, fence, outTimestamps] (
                     Status status,
@@ -1015,6 +1018,10 @@
                     fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
                 }
             }));
+    if (outBufferAge) {
+        // Since the HAL version doesn't return the buffer age, set it to 0:
+        *outBufferAge = 0;
+    }
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
@@ -1144,10 +1151,11 @@
     return toStatusT(mBase->setSidebandStream(stream == nullptr ? nullptr : stream->handle()));
 }
 
+// FIXME: usage bits truncated -- needs a 64-bits usage version
 void H2BGraphicBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
-        ::android::PixelFormat format, uint32_t usage) {
+        ::android::PixelFormat format, uint64_t usage) {
     mBase->allocateBuffers(
-            width, height, static_cast<PixelFormat>(format), usage);
+            width, height, static_cast<PixelFormat>(format), uint32_t(usage));
 }
 
 status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
@@ -1226,6 +1234,18 @@
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
+status_t H2BGraphicBufferProducer::getConsumerUsage(uint64_t* outUsage) const {
+    ALOGW("getConsumerUsage is not fully supported");
+    int result;
+    status_t transStatus = toStatusT(mBase->query(
+            NATIVE_WINDOW_CONSUMER_USAGE_BITS,
+            [&result, outUsage] (int32_t tResult, int32_t tValue) {
+                result = static_cast<int>(tResult);
+                *outUsage = static_cast<uint64_t>(tValue);
+            }));
+    return transStatus == NO_ERROR ? result : static_cast<int>(transStatus);
+}
+
 }  // namespace utils
 }  // namespace V1_0
 }  // namespace bufferqueue
diff --git a/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
similarity index 100%
rename from include/gui/BufferItem.h
rename to libs/gui/include/gui/BufferItem.h
diff --git a/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
similarity index 97%
rename from include/gui/BufferItemConsumer.h
rename to libs/gui/include/gui/BufferItemConsumer.h
index db7e944..d9c5775 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/libs/gui/include/gui/BufferItemConsumer.h
@@ -52,10 +52,10 @@
     // controlledByApp tells whether this consumer is controlled by the
     // application.
     BufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer,
-            uint32_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS,
+            uint64_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS,
             bool controlledByApp = false);
 
-    virtual ~BufferItemConsumer();
+    ~BufferItemConsumer() override;
 
     // set the name of the BufferItemConsumer that will be used to identify it in
     // log messages.
diff --git a/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
similarity index 98%
rename from include/gui/BufferQueue.h
rename to libs/gui/include/gui/BufferQueue.h
index bd62d85..ba5cbf7 100644
--- a/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -57,7 +57,7 @@
     class ProxyConsumerListener : public BnConsumerListener {
     public:
         explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
-        virtual ~ProxyConsumerListener();
+        ~ProxyConsumerListener() override;
         void onDisconnect() override;
         void onFrameAvailable(const BufferItem& item) override;
         void onFrameReplaced(const BufferItem& item) override;
diff --git a/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
similarity index 97%
rename from include/gui/BufferQueueConsumer.h
rename to libs/gui/include/gui/BufferQueueConsumer.h
index b383056..d108120 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -32,7 +32,7 @@
 
 public:
     BufferQueueConsumer(const sp<BufferQueueCore>& core);
-    virtual ~BufferQueueConsumer();
+    ~BufferQueueConsumer() override;
 
     // acquireBuffer attempts to acquire ownership of the next pending buffer in
     // the BufferQueue. If no buffer is pending then it returns
@@ -121,13 +121,12 @@
     // GraphicBuffers of a defaultDataSpace if no data space is specified
     // in queueBuffer.
     // The initial default is HAL_DATASPACE_UNKNOWN
-    virtual status_t setDefaultBufferDataSpace(
-            android_dataspace defaultDataSpace);
+    virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
 
     // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
     // These are merged with the bits passed to dequeueBuffer.  The values are
     // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
-    virtual status_t setConsumerUsageBits(uint32_t usage);
+    virtual status_t setConsumerUsageBits(uint64_t usage) override;
 
     // setConsumerIsProtected will turn on an internal bit that indicates whether
     // the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
similarity index 99%
rename from include/gui/BufferQueueCore.h
rename to libs/gui/include/gui/BufferQueueCore.h
index dd8b992..537c957 100644
--- a/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -170,7 +170,7 @@
 
     // mConsumerUsageBits contains flags that the consumer wants for
     // GraphicBuffers.
-    uint32_t mConsumerUsageBits;
+    uint64_t mConsumerUsageBits;
 
     // mConsumerIsProtected indicates the consumer is ready to handle protected
     // buffer.
diff --git a/include/gui/BufferQueueDefs.h b/libs/gui/include/gui/BufferQueueDefs.h
similarity index 100%
rename from include/gui/BufferQueueDefs.h
rename to libs/gui/include/gui/BufferQueueDefs.h
diff --git a/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
similarity index 94%
rename from include/gui/BufferQueueProducer.h
rename to libs/gui/include/gui/BufferQueueProducer.h
index 5541468..5c7ffb4 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -30,7 +30,7 @@
     friend class BufferQueue; // Needed to access binderDied
 
     BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
-    virtual ~BufferQueueProducer();
+    ~BufferQueueProducer() override;
 
     // requestBuffer returns the GraphicBuffer for slot N.
     //
@@ -80,9 +80,10 @@
     //
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
-    status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
-            uint32_t width, uint32_t height, PixelFormat format,
-            uint32_t usage, FrameEventHistoryDelta* outTimestamps) override;
+    virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width,
+                                   uint32_t height, PixelFormat format, uint64_t usage,
+                                   uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) override;
 
     // See IGraphicBufferProducer::detachBuffer
     virtual status_t detachBuffer(int slot);
@@ -152,7 +153,7 @@
 
     // See IGraphicBufferProducer::allocateBuffers
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage) override;
 
     // See IGraphicBufferProducer::allowAllocation
     virtual status_t allowAllocation(bool allow);
@@ -182,6 +183,9 @@
     // See IGraphicBufferProducer::getUniqueId
     virtual status_t getUniqueId(uint64_t* outId) const override;
 
+    // See IGraphicBufferProducer::getConsumerUsage
+    virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h
similarity index 100%
rename from include/gui/BufferSlot.h
rename to libs/gui/include/gui/BufferSlot.h
diff --git a/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
similarity index 98%
rename from include/gui/ConsumerBase.h
rename to libs/gui/include/gui/ConsumerBase.h
index 7912528..e9fc8fd 100644
--- a/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -47,7 +47,7 @@
         virtual void onFrameReplaced(const BufferItem& /* item */) {}
     };
 
-    virtual ~ConsumerBase();
+    ~ConsumerBase() override;
 
     // abandon frees all the buffers and puts the ConsumerBase into the
     // 'abandoned' state.  Once put in this state the ConsumerBase can never
@@ -241,7 +241,9 @@
 
     // mFrameAvailableListener is the listener object that will be called when a
     // new frame becomes available. If it is not NULL it will be called from
-    // queueBuffer.
+    // queueBuffer. The listener object is protected by mFrameAvailableMutex
+    // (not mMutex).
+    Mutex mFrameAvailableMutex;
     wp<FrameAvailableListener> mFrameAvailableListener;
 
     // The ConsumerBase has-a BufferQueue and is responsible for creating this object
diff --git a/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h
similarity index 100%
rename from include/gui/CpuConsumer.h
rename to libs/gui/include/gui/CpuConsumer.h
diff --git a/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
similarity index 100%
rename from include/gui/DisplayEventReceiver.h
rename to libs/gui/include/gui/DisplayEventReceiver.h
diff --git a/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
similarity index 100%
rename from include/gui/FrameTimestamps.h
rename to libs/gui/include/gui/FrameTimestamps.h
diff --git a/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
similarity index 99%
rename from include/gui/GLConsumer.h
rename to libs/gui/include/gui/GLConsumer.h
index 2cf6162..75f2cca 100644
--- a/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -210,7 +210,7 @@
     // so the refactoring can proceed smoothly
     status_t setDefaultBufferFormat(PixelFormat defaultFormat);
     status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
-    status_t setConsumerUsageBits(uint32_t usage);
+    status_t setConsumerUsageBits(uint64_t usage);
     status_t setTransformHint(uint32_t hint);
     status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
 
@@ -386,7 +386,7 @@
     // BufferQueue instance; these will be OR:d with any additional flags passed
     // from the GLConsumer user. In particular, GLConsumer will always
     // consume buffers as hardware textures.
-    static const uint32_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
 
     // mCurrentTextureImage is the EglImage/buffer of the current texture. It's
     // possible that this buffer is not associated with any buffer slot, so we
diff --git a/include/gui/GuiConfig.h b/libs/gui/include/gui/GuiConfig.h
similarity index 100%
rename from include/gui/GuiConfig.h
rename to libs/gui/include/gui/GuiConfig.h
diff --git a/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
similarity index 100%
rename from include/gui/IConsumerListener.h
rename to libs/gui/include/gui/IConsumerListener.h
diff --git a/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h
similarity index 100%
rename from include/gui/IDisplayEventConnection.h
rename to libs/gui/include/gui/IDisplayEventConnection.h
diff --git a/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
similarity index 99%
rename from include/gui/IGraphicBufferConsumer.h
rename to libs/gui/include/gui/IGraphicBufferConsumer.h
index 3d069df..9fb7580 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -241,7 +241,7 @@
     // e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
-    virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
+    virtual status_t setConsumerUsageBits(uint64_t usage) = 0;
 
     // setConsumerIsProtected will turn on an internal bit that indicates whether
     // the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
similarity index 97%
rename from include/gui/IGraphicBufferProducer.h
rename to libs/gui/include/gui/IGraphicBufferProducer.h
index 9250806..039dc0d 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -194,9 +194,9 @@
     //
     // All other negative values are an unknown error returned downstream
     // from the graphics allocator (typically errno).
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta* outTimestamps) = 0;
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
     // slot from the buffer queue. If this call succeeds, the slot will be
@@ -517,7 +517,7 @@
     // dequeueBuffer. If there are already the maximum number of buffers
     // allocated, this function has no effect.
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) = 0;
+            PixelFormat format, uint64_t usage) = 0;
 
     // Sets whether dequeueBuffer is allowed to allocate new buffers.
     //
@@ -593,6 +593,12 @@
 
     // Returns a unique id for this BufferQueue
     virtual status_t getUniqueId(uint64_t* outId) const = 0;
+
+    // Returns the consumer usage flags for this BufferQueue. This returns the
+    // full 64-bit usage flags, rather than the truncated 32-bit usage flags
+    // returned by querying the now deprecated
+    // NATIVE_WINDOW_CONSUMER_USAGE_BITS attribute.
+    virtual status_t getConsumerUsage(uint64_t* outUsage) const = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
similarity index 100%
rename from include/gui/IProducerListener.h
rename to libs/gui/include/gui/IProducerListener.h
diff --git a/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
similarity index 100%
rename from include/gui/ISurfaceComposer.h
rename to libs/gui/include/gui/ISurfaceComposer.h
diff --git a/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
similarity index 100%
rename from include/gui/ISurfaceComposerClient.h
rename to libs/gui/include/gui/ISurfaceComposerClient.h
diff --git a/include/gui/OccupancyTracker.h b/libs/gui/include/gui/OccupancyTracker.h
similarity index 100%
rename from include/gui/OccupancyTracker.h
rename to libs/gui/include/gui/OccupancyTracker.h
diff --git a/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
similarity index 100%
rename from include/gui/StreamSplitter.h
rename to libs/gui/include/gui/StreamSplitter.h
diff --git a/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
similarity index 97%
rename from include/gui/Surface.h
rename to libs/gui/include/gui/Surface.h
index e8dc83e..55dd6bf 100644
--- a/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -27,7 +27,7 @@
 #include <utils/Mutex.h>
 #include <utils/RefBase.h>
 
-struct ANativeWindow_Buffer;
+#include <system/window.h>
 
 namespace android {
 
@@ -159,6 +159,7 @@
     status_t getHdrSupport(bool* supported);
 
     status_t getUniqueId(uint64_t* outId) const;
+    status_t getConsumerUsage(uint64_t* outUsage) const;
 
     // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
     nsecs_t getLastDequeueStartTime() const;
@@ -207,8 +208,8 @@
     int dispatchSetBuffersStickyTransform(va_list args);
     int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
-    int dispatchSetPostTransformCrop(va_list args);
     int dispatchSetUsage(va_list args);
+    int dispatchSetUsage64(va_list args);
     int dispatchLock(va_list args);
     int dispatchUnlockAndPost(va_list args);
     int dispatchSetSidebandStream(va_list args);
@@ -223,6 +224,7 @@
     int dispatchGetFrameTimestamps(va_list args);
     int dispatchGetWideColorSupport(va_list args);
     int dispatchGetHdrSupport(va_list args);
+    int dispatchGetConsumerUsage64(va_list args);
 
 protected:
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
@@ -242,7 +244,7 @@
     virtual int setBuffersTimestamp(int64_t timestamp);
     virtual int setBuffersDataSpace(android_dataspace dataSpace);
     virtual int setCrop(Rect const* rect);
-    virtual int setUsage(uint32_t reqUsage);
+    virtual int setUsage(uint64_t reqUsage);
     virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
 
 public:
@@ -321,7 +323,7 @@
 
     // mReqUsage is the set of buffer usage flags that will be requested
     // at the next deuque operation. It is initialized to 0.
-    uint32_t mReqUsage;
+    uint64_t mReqUsage;
 
     // mTimestamp is the timestamp that will be used for the next buffer queue
     // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
@@ -403,6 +405,10 @@
     // (the change since the previous frame) passed in by the producer.
     Region mDirtyRegion;
 
+    // mBufferAge tracks the age of the contents of the most recently dequeued
+    // buffer as the number of frames that have elapsed since it was last queued
+    uint64_t mBufferAge;
+
     // Stores the current generation number. See setGenerationNumber and
     // IGraphicBufferProducer::setGenerationNumber for more information.
     uint32_t mGenerationNumber;
diff --git a/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
similarity index 99%
rename from include/gui/SurfaceComposerClient.h
rename to libs/gui/include/gui/SurfaceComposerClient.h
index ec310cf..145c059 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -271,6 +271,7 @@
     uint32_t getStride() const;
     // size of allocated memory in bytes
     size_t getSize() const;
+    android_dataspace getDataSpace() const;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
similarity index 100%
rename from include/gui/SurfaceControl.h
rename to libs/gui/include/gui/SurfaceControl.h
diff --git a/include/gui/bufferqueue/1.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
similarity index 100%
rename from include/gui/bufferqueue/1.0/B2HProducerListener.h
rename to libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
diff --git a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
similarity index 92%
rename from include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
rename to libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 93c452a..74850b4 100644
--- a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -64,9 +64,9 @@
     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
     status_t setAsyncMode(bool async) override;
-    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, ::android::PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta* outTimestamps) override;
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                           ::android::PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override;
     status_t detachBuffer(int slot) override;
     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence)
             override;
@@ -83,7 +83,7 @@
             override;
     status_t setSidebandStream(const sp<NativeHandle>& stream) override;
     void allocateBuffers(uint32_t width, uint32_t height,
-            ::android::PixelFormat format, uint32_t usage) override;
+            ::android::PixelFormat format, uint64_t usage) override;
     status_t allowAllocation(bool allow) override;
     status_t setGenerationNumber(uint32_t generationNumber) override;
     String8 getConsumerName() const override;
@@ -94,6 +94,7 @@
           sp<Fence>* outFence, float outTransformMatrix[16]) override;
     void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;
     status_t getUniqueId(uint64_t* outId) const override;
+    status_t getConsumerUsage(uint64_t* outUsage) const override;
 };
 
 }  // namespace utils
diff --git a/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h
similarity index 100%
rename from include/gui/view/Surface.h
rename to libs/gui/include/gui/view/Surface.h
diff --git a/include/private/gui/ComposerService.h b/libs/gui/include/private/gui/ComposerService.h
similarity index 100%
rename from include/private/gui/ComposerService.h
rename to libs/gui/include/private/gui/ComposerService.h
diff --git a/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h
similarity index 100%
rename from include/private/gui/LayerState.h
rename to libs/gui/include/private/gui/LayerState.h
diff --git a/include/private/gui/SyncFeatures.h b/libs/gui/include/private/gui/SyncFeatures.h
similarity index 100%
rename from include/private/gui/SyncFeatures.h
rename to libs/gui/include/private/gui/SyncFeatures.h
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 7efdb14..fa87f29 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -4,6 +4,7 @@
 // to integrate with auto-test framework.
 cc_test {
     name: "libgui_test",
+    test_suites: ["device-tests"],
 
     clang: true,
 
diff --git a/libs/gui/tests/AndroidTest.xml b/libs/gui/tests/AndroidTest.xml
new file mode 100644
index 0000000..c02e020
--- /dev/null
+++ b/libs/gui/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for libgui_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="libgui_test->/data/local/tmp/libgui_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="libgui_test" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index d64e530..b87cbbd 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -76,8 +76,8 @@
 
         int slot;
         sp<Fence> outFence;
-        status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth,
-                                                kHeight, 0, 0, nullptr);
+        status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth, kHeight, 0, 0,
+                                                nullptr, nullptr);
         ASSERT_GE(ret, 0);
 
         ALOGV("dequeueBuffer: slot=%d", slot);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 60c1277..9a20859 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -32,6 +32,8 @@
 #include <utils/String8.h>
 #include <utils/threads.h>
 
+#include <system/window.h>
+
 #include <gtest/gtest.h>
 
 #include <thread>
@@ -142,8 +144,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -186,16 +188,16 @@
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
 
@@ -237,8 +239,8 @@
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
     for (int i = 0; i < 3; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -273,8 +275,8 @@
     BufferItem item;
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-            GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -283,8 +285,8 @@
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -333,8 +335,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -382,8 +384,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
@@ -418,8 +420,8 @@
             EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataOut;
@@ -441,8 +443,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -490,22 +492,24 @@
     sp<GraphicBuffer> buffer;
     // This should return an error since it would require an allocation
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
-            0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(WOULD_BLOCK,
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
 
     // This should succeed, now that we've lifted the prohibition
     ASSERT_EQ(OK, mProducer->allowAllocation(true));
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
 
     // Release the previous buffer back to the BufferQueue
     mProducer->cancelBuffer(slot, fence);
 
     // This should fail since we're requesting a different size
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
-            WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(WOULD_BLOCK,
+              mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
+                                       GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
 }
 
 TEST_F(BufferQueueTest, TestGenerationNumbers) {
@@ -522,7 +526,7 @@
     int slot;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
 
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -565,7 +569,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Queue the buffer
@@ -579,8 +583,7 @@
     // always the same one and because async mode gets enabled.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -617,7 +620,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Queue the buffer
@@ -644,8 +647,7 @@
     // always return the same one.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -684,7 +686,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Enable shared buffer mode
@@ -701,8 +703,7 @@
     // always the same one and because async mode gets enabled.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -737,8 +738,7 @@
     for (int i = 0; i < 5; ++i) {
         int slot = BufferQueue::INVALID_BUFFER_SLOT;
         sp<Fence> fence = Fence::NO_FENCE;
-        auto result = mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr);
+        auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
         if (i < 2) {
             ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
                     result);
@@ -765,8 +765,7 @@
     for (int i = 0; i < 2; ++i) {
         int slot = BufferQueue::INVALID_BUFFER_SLOT;
         sp<Fence> fence = Fence::NO_FENCE;
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
         IGraphicBufferProducer::QueueBufferInput input(0ull, true,
                 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
@@ -777,8 +776,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> fence = Fence::NO_FENCE;
     auto startTime = systemTime();
-    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
-            &slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_GE(systemTime() - startTime, TIMEOUT);
 
     // We're technically attaching the same buffer multiple times (since we
@@ -799,7 +797,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> sourceFence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -822,7 +820,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> firstBuffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
 
@@ -834,7 +832,7 @@
     // Dequeue a second buffer
     slot = BufferQueue::INVALID_BUFFER_SLOT;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> secondBuffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
 
@@ -885,8 +883,8 @@
     int slots[3] = {};
     mProducer->setMaxDequeuedBufferCount(3);
     for (size_t i = 0; i < 3; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -899,8 +897,7 @@
     // The first segment is a two-buffer segment, so we only put one buffer into
     // the queue at a time
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -915,17 +912,16 @@
     // two-buffer segment, but then at the end, we put two buffers in the queue
     // at the same time before draining it.
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
         std::this_thread::sleep_for(16ms);
     }
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -940,11 +936,10 @@
 
     // The third segment is a triple-buffer segment, so the queue is switching
     // between one buffer and two buffers deep.
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -1024,8 +1019,8 @@
     int slots[4] = {};
     mProducer->setMaxDequeuedBufferCount(4);
     for (size_t i = 0; i < 4; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -1036,14 +1031,14 @@
     // Get buffers in all states: dequeued, filled, acquired, free
 
     // Fill 3 buffers
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     // Dequeue 1 buffer
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
 
     // Acquire and free 1 buffer
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -1102,8 +1097,8 @@
     int slots[2] = {};
     ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
     for (size_t i = 0; i < 2; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -1113,10 +1108,10 @@
 
     // Fill 2 buffers without consumer consuming them. Verify that all
     // queued buffer returns proper bufferReplaced flag
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(false, output.bufferReplaced);
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(true, output.bufferReplaced);
 }
@@ -1138,8 +1133,7 @@
             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
 
     // Dequeue, request, and queue one buffer
-    status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0,
-            nullptr);
+    status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
@@ -1154,7 +1148,7 @@
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     // Dequeue and queue the buffer again
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     // Acquire and release the buffer again. Upon acquiring, the buffer handle
@@ -1166,7 +1160,7 @@
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     // Dequeue and queue the buffer again
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     // Disconnect the producer end. This should clear all of the slots and mark
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 5848c74..0982d7e 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -33,6 +33,7 @@
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
 
+#include <vector>
 #define CPU_CONSUMER_TEST_FORMAT_RAW 0
 #define CPU_CONSUMER_TEST_FORMAT_Y8 0
 #define CPU_CONSUMER_TEST_FORMAT_Y16 0
@@ -635,7 +636,7 @@
 
     // Consume
 
-    CpuConsumer::LockedBuffer *b = new CpuConsumer::LockedBuffer[params.maxLockedBuffers];
+    std::vector<CpuConsumer::LockedBuffer> b(params.maxLockedBuffers);
     for (int i = 0; i < params.maxLockedBuffers; i++) {
         ALOGV("Locking frame %d", i);
         err = mCC->lockNextBuffer(&b[i]);
@@ -684,9 +685,6 @@
     for (int i = 1; i < params.maxLockedBuffers; i++) {
         mCC->unlockBuffer(b[i]);
     }
-
-    delete[] b;
-
 }
 
 CpuConsumerTestParams y8TestSets[] = {
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index aa071f6..dd23bd4 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -29,6 +29,8 @@
 #include <gui/BufferQueue.h>
 #include <gui/IProducerListener.h>
 
+#include <system/window.h>
+
 #include <vector>
 
 #define ASSERT_OK(x) ASSERT_EQ(OK, (x))
@@ -192,7 +194,8 @@
     };
 
     status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
-        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage, nullptr);
+        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage,
+                                        nullptr, nullptr);
     }
 
     void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
@@ -204,9 +207,12 @@
 
         ASSERT_NO_FATAL_FAILURE(ConnectProducer());
 
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
-                DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr)));
+
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                                    DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
+                                                    nullptr, nullptr)));
 
         EXPECT_LE(0, *slot);
         EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
@@ -341,11 +347,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     EXPECT_LE(0, dequeuedSlot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -401,10 +407,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     // Slot was enqueued without requesting a buffer
     {
@@ -470,10 +477,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     // No return code, but at least test that it doesn't blow up...
     // TODO: add a return code
@@ -517,12 +525,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
     for (int i = 0; i < maxBuffers; ++i) {
-
-        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                         DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS, nullptr)))
+        EXPECT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "iteration: " << i << ", slot: " << dequeuedSlot;
     }
 
@@ -555,11 +562,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
     for (int i = 0; i < 2; i++) {
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                         DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot: " << dequeuedSlot;
     }
 
@@ -591,10 +598,11 @@
     // Should now be able to queue/dequeue as many buffers as we want without
     // blocking
     for (int i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot : " << dequeuedSlot;
         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
@@ -608,10 +616,11 @@
         int dequeuedSlot = -1;
         sp<Fence> dequeuedFence;
 
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot: " << dequeuedSlot;
     }
 
@@ -628,8 +637,9 @@
     int slot = -1;
     sp<Fence> fence;
 
-    ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
-            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr));
+    ASSERT_EQ(NO_INIT,
+              mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                       TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
 }
 
 TEST_F(IGraphicBufferProducerTest,
@@ -647,10 +657,11 @@
     int slot = -1;
     sp<Fence> fence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
-            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
-            nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                                DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
+                                                nullptr, nullptr)));
 
     EXPECT_LE(0, slot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index 7ecf08c..bb6b8a5 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -38,8 +38,10 @@
     }
     status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
-                           uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
-        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
+                           uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge,
+                                        outTimestamps);
     }
     status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
@@ -67,7 +69,7 @@
         return mProducer->setSidebandStream(stream);
     }
     void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
-                         uint32_t usage) override {
+                         uint64_t usage) override {
         mProducer->allocateBuffers(width, height, format, usage);
     }
     status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
@@ -90,6 +92,9 @@
     }
     void getFrameTimestamps(FrameEventHistoryDelta*) override {}
     status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
+    status_t getConsumerUsage(uint64_t* outUsage) const override {
+        return mProducer->getConsumerUsage(outUsage);
+    }
 
 protected:
     sp<IGraphicBufferProducer> mProducer;
@@ -105,10 +110,10 @@
 
     // Override dequeueBuffer, optionally corrupting the returned slot number
     status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
-                           PixelFormat format, uint32_t usage,
+                           PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
                            FrameEventHistoryDelta* outTimestamps) override {
         EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
-                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
+                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage, outBufferAge,
                                            outTimestamps));
         EXPECT_EQ(mExpectedSlot, *buf);
         if (mMaliciousValue != 0) {
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 80e30da..ad6e051 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -24,6 +24,8 @@
 #include <gui/StreamSplitter.h>
 #include <private/gui/ComposerService.h>
 
+#include <system/window.h>
+
 #include <gtest/gtest.h>
 
 namespace android {
@@ -80,8 +82,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -114,8 +116,8 @@
     // This should succeed even with allocation disabled since it will have
     // received the buffer back from the output BufferQueue
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
@@ -152,8 +154,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -189,8 +191,8 @@
     // This should succeed even with allocation disabled since it will have
     // received the buffer back from the output BufferQueues
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 TEST_F(StreamSplitterTest, OutputAbandonment) {
@@ -216,8 +218,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     // Abandon the output
@@ -229,8 +231,9 @@
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     // Input should be abandoned
-    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(NO_INIT,
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 } // namespace android
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index bd598e4..d5b2f00 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -28,7 +28,7 @@
 #include <utils/Log.h>
 #include <utils/Thread.h>
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
 
 namespace android {
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index 8c6ef69..77f06bb 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -426,7 +426,13 @@
 
     std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
 
-    mCallbacks[descriptor] = {callbackData, pointer};
+    if (pointer != nullptr) {
+        mCallbacks[descriptor] = {callbackData, pointer};
+    } else {
+        ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str());
+        mCallbacks.erase(descriptor);
+        return Error::None;
+    }
 
     bool hasPendingInvalidate = false;
     std::vector<hwc2_display_t> displayIds;
@@ -2005,10 +2011,21 @@
     return Error::None;
 }
 
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    return rect1.left == rect2.left &&
+            rect1.right == rect2.right &&
+            rect1.top == rect2.top &&
+            rect1.bottom == rect2.bottom;
+}
+
 Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
-    mVisibleRegion.resize(visible.numRects);
-    std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
-    mDisplay.markGeometryChanged();
+    if ((getNumVisibleRegions() != visible.numRects) ||
+        !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+                    compareRects)) {
+        mVisibleRegion.resize(visible.numRects);
+        std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+        mDisplay.markGeometryChanged();
+    }
     return Error::None;
 }
 
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 9294419..2f39976 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -34,6 +34,7 @@
     clang: true,
 
     shared_libs: [
+        "libbase",
         "liblog",
         "libcutils",
     ],
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index af1c0af..d8dc957 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -285,6 +285,7 @@
         uint32_t seq,
         int32_t deviceId,
         int32_t source,
+        int32_t displayId,
         int32_t action,
         int32_t actionButton,
         int32_t flags,
@@ -327,6 +328,7 @@
     msg.body.motion.seq = seq;
     msg.body.motion.deviceId = deviceId;
     msg.body.motion.source = source;
+    msg.body.motion.displayId = displayId;
     msg.body.motion.action = action;
     msg.body.motion.actionButton = actionButton;
     msg.body.motion.flags = flags;
@@ -396,7 +398,8 @@
 }
 
 status_t InputConsumer::consume(InputEventFactoryInterface* factory,
-        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
+        int32_t* displayId) {
 #if DEBUG_TRANSPORT_ACTIONS
     ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
             mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
@@ -404,6 +407,7 @@
 
     *outSeq = 0;
     *outEvent = NULL;
+    *displayId = -1;  // Invalid display.
 
     // Fetch the next input message.
     // Loop until an event can be returned or no additional events are received.
@@ -418,7 +422,7 @@
             if (result) {
                 // Consume the next batched event unless batches are being held for later.
                 if (consumeBatches || result != WOULD_BLOCK) {
-                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
+                    result = consumeBatch(factory, frameTime, outSeq, outEvent, displayId);
                     if (*outEvent) {
 #if DEBUG_TRANSPORT_ACTIONS
                         ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
@@ -462,7 +466,7 @@
                     // the previous batch right now and defer the new message until later.
                     mMsgDeferred = true;
                     status_t result = consumeSamples(factory,
-                            batch, batch.samples.size(), outSeq, outEvent);
+                            batch, batch.samples.size(), outSeq, outEvent, displayId);
                     mBatches.removeAt(batchIndex);
                     if (result) {
                         return result;
@@ -492,10 +496,11 @@
             MotionEvent* motionEvent = factory->createMotionEvent();
             if (! motionEvent) return NO_MEMORY;
 
-            updateTouchState(&mMsg);
+            updateTouchState(mMsg);
             initializeMotionEvent(motionEvent, &mMsg);
             *outSeq = mMsg.body.motion.seq;
             *outEvent = motionEvent;
+            *displayId = mMsg.body.motion.displayId;
 #if DEBUG_TRANSPORT_ACTIONS
             ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
                     mChannel->getName().string(), *outSeq);
@@ -513,14 +518,14 @@
 }
 
 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
-        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
     status_t result;
     for (size_t i = mBatches.size(); i > 0; ) {
         i--;
         Batch& batch = mBatches.editItemAt(i);
         if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
-                    outSeq, outEvent);
+                    outSeq, outEvent, displayId);
             mBatches.removeAt(i);
             return result;
         }
@@ -534,7 +539,7 @@
             continue;
         }
 
-        result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
+        result = consumeSamples(factory, batch, split + 1, outSeq, outEvent, displayId);
         const InputMessage* next;
         if (batch.samples.isEmpty()) {
             mBatches.removeAt(i);
@@ -552,14 +557,14 @@
 }
 
 status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
-        Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
+        Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
     MotionEvent* motionEvent = factory->createMotionEvent();
     if (! motionEvent) return NO_MEMORY;
 
     uint32_t chain = 0;
     for (size_t i = 0; i < count; i++) {
         InputMessage& msg = batch.samples.editItemAt(i);
-        updateTouchState(&msg);
+        updateTouchState(msg);
         if (i) {
             SeqChain seqChain;
             seqChain.seq = msg.body.motion.seq;
@@ -567,6 +572,7 @@
             mSeqChains.push(seqChain);
             addSample(motionEvent, &msg);
         } else {
+            *displayId = msg.body.motion.displayId;
             initializeMotionEvent(motionEvent, &msg);
         }
         chain = msg.body.motion.seq;
@@ -578,20 +584,19 @@
     return OK;
 }
 
-void InputConsumer::updateTouchState(InputMessage* msg) {
+void InputConsumer::updateTouchState(InputMessage& msg) {
     if (!mResampleTouch ||
-            !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+            !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
         return;
     }
 
-    int32_t deviceId = msg->body.motion.deviceId;
-    int32_t source = msg->body.motion.source;
-    nsecs_t eventTime = msg->body.motion.eventTime;
+    int32_t deviceId = msg.body.motion.deviceId;
+    int32_t source = msg.body.motion.source;
 
     // Update the touch state history to incorporate the new input message.
     // If the message is in the past relative to the most recently produced resampled
     // touch, then use the resampled time and coordinates instead.
-    switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
+    switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
     case AMOTION_EVENT_ACTION_DOWN: {
         ssize_t index = findTouchState(deviceId, source);
         if (index < 0) {
@@ -609,9 +614,8 @@
         if (index >= 0) {
             TouchState& touchState = mTouchStates.editItemAt(index);
             touchState.addHistory(msg);
-            if (eventTime < touchState.lastResample.eventTime) {
-                rewriteMessage(touchState, msg);
-            } else {
+            bool messageRewritten = rewriteMessage(touchState, msg);
+            if (!messageRewritten) {
                 touchState.lastResample.idBits.clear();
             }
         }
@@ -622,7 +626,7 @@
         ssize_t index = findTouchState(deviceId, source);
         if (index >= 0) {
             TouchState& touchState = mTouchStates.editItemAt(index);
-            touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+            touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
             rewriteMessage(touchState, msg);
         }
         break;
@@ -633,7 +637,7 @@
         if (index >= 0) {
             TouchState& touchState = mTouchStates.editItemAt(index);
             rewriteMessage(touchState, msg);
-            touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+            touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
         }
         break;
     }
@@ -660,23 +664,28 @@
     }
 }
 
-void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
-    for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
-        uint32_t id = msg->body.motion.pointers[i].properties.id;
+bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) {
+    bool messageRewritten = false;
+    nsecs_t eventTime = msg.body.motion.eventTime;
+    for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+        uint32_t id = msg.body.motion.pointers[i].properties.id;
         if (state.lastResample.idBits.hasBit(id)) {
-            PointerCoords& msgCoords = msg->body.motion.pointers[i].coords;
+            PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
             const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
+            if (eventTime < state.lastResample.eventTime ||
+                    state.recentCoordinatesAreIdentical(id)) {
+                msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
+                msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
 #if DEBUG_RESAMPLING
-            ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
-                    resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
-                    resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
-                    msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
-                    msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
+                ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
+                        resampleCoords.getX(), resampleCoords.getY(),
+                        msgCoords.getX(), msgCoords.getY());
 #endif
-            msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
-            msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+                messageRewritten = true;
+            }
         }
     }
+    return messageRewritten;
 }
 
 void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
@@ -704,6 +713,7 @@
     }
 
     // Ensure that the current sample has all of the pointers that need to be reported.
+    // Also ensure that the past two "real" touch events do not contain duplicate coordinates
     const History* current = touchState.getHistory(0);
     size_t pointerCount = event->getPointerCount();
     for (size_t i = 0; i < pointerCount; i++) {
@@ -714,6 +724,12 @@
 #endif
             return;
         }
+        if (touchState.recentCoordinatesAreIdentical(id)) {
+#if DEBUG_RESAMPLING
+            ALOGD("Not resampled, past two historical events have duplicate coordinates");
+#endif
+            return;
+        }
     }
 
     // Find the data to use for resampling.
@@ -723,12 +739,12 @@
     if (next) {
         // Interpolate between current sample and future sample.
         // So current->eventTime <= sampleTime <= future.eventTime.
-        future.initializeFrom(next);
+        future.initializeFrom(*next);
         other = &future;
         nsecs_t delta = future.eventTime - current->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
 #endif
             return;
         }
@@ -740,12 +756,12 @@
         nsecs_t delta = current->eventTime - other->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
 #endif
             return;
         } else if (delta > RESAMPLE_MAX_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too large: %" PRId64 " ns.", delta);
 #endif
             return;
         }
@@ -753,7 +769,7 @@
         if (sampleTime > maxPredict) {
 #if DEBUG_RESAMPLING
             ALOGD("Sample time is too far in the future, adjusting prediction "
-                    "from %lld to %lld ns.",
+                    "from %" PRId64 " to %" PRId64 " ns.",
                     sampleTime - current->eventTime, maxPredict - current->eventTime);
 #endif
             sampleTime = maxPredict;
@@ -842,15 +858,14 @@
         }
         if (status) {
             // An error occurred so at least one signal was not sent, reconstruct the chain.
-            do {
+            for (;;) {
                 SeqChain seqChain;
                 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
                 seqChain.chain = chainSeqs[chainIndex];
                 mSeqChains.push(seqChain);
-                if (chainIndex != 0) {
-                    chainIndex--;
-                }
-            } while (chainIndex > 0);
+                if (!chainIndex) break;
+                chainIndex--;
+            }
             return status;
         }
     }
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 7f6b157..b174fa8 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -23,13 +23,14 @@
 // Log debug messages about the progress of the algorithm itself.
 #define DEBUG_STRATEGY 0
 
-#include <math.h>
+#include <inttypes.h>
 #include <limits.h>
+#include <math.h>
 
+#include <android-base/stringprintf.h>
 #include <cutils/properties.h>
 #include <input/VelocityTracker.h>
 #include <utils/BitSet.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 namespace android {
@@ -46,8 +47,7 @@
 
 static float vectorDot(const float* a, const float* b, uint32_t m) {
     float r = 0;
-    while (m) {
-        m--;
+    for (size_t i = 0; i < m; i++) {
         r += *(a++) * *(b++);
     }
     return r;
@@ -55,8 +55,7 @@
 
 static float vectorNorm(const float* a, uint32_t m) {
     float r = 0;
-    while (m) {
-        m--;
+    for (size_t i = 0; i < m; i++) {
         float t = *(a++);
         r += t * t;
     }
@@ -64,36 +63,36 @@
 }
 
 #if DEBUG_STRATEGY || DEBUG_VELOCITY
-static String8 vectorToString(const float* a, uint32_t m) {
-    String8 str;
-    str.append("[");
-    while (m--) {
-        str.appendFormat(" %f", *(a++));
-        if (m) {
-            str.append(",");
+static std::string vectorToString(const float* a, uint32_t m) {
+    std::string str;
+    str += "[";
+    for (size_t i = 0; i < m; i++) {
+        if (i) {
+            str += ",";
         }
+        str += android::base::StringPrintf(" %f", *(a++));
     }
-    str.append(" ]");
+    str += " ]";
     return str;
 }
 
-static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
-    String8 str;
-    str.append("[");
+static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
+    std::string str;
+    str = "[";
     for (size_t i = 0; i < m; i++) {
         if (i) {
-            str.append(",");
+            str += ",";
         }
-        str.append(" [");
+        str += " [";
         for (size_t j = 0; j < n; j++) {
             if (j) {
-                str.append(",");
+                str += ",";
             }
-            str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]);
+            str += android::base::StringPrintf(" %f", a[rowMajor ? i * n + j : j * m + i]);
         }
-        str.append(" ]");
+        str += " ]";
     }
-    str.append(" ]");
+    str += " ]";
     return str;
 }
 #endif
@@ -244,7 +243,7 @@
     mStrategy->addMovement(eventTime, idBits, positions);
 
 #if DEBUG_VELOCITY
-    ALOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
+    ALOGD("VelocityTracker: addMovement eventTime=%" PRId64 ", idBits=0x%08x, activePointerId=%d",
             eventTime, idBits.value, mActivePointerId);
     for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
         uint32_t id = iterBits.firstMarkedBit();
@@ -256,8 +255,8 @@
                 "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)",
                 id, positions[index].x, positions[index].y,
                 int(estimator.degree),
-                vectorToString(estimator.xCoeff, estimator.degree + 1).string(),
-                vectorToString(estimator.yCoeff, estimator.degree + 1).string(),
+                vectorToString(estimator.xCoeff, estimator.degree + 1).c_str(),
+                vectorToString(estimator.yCoeff, estimator.degree + 1).c_str(),
                 estimator.confidence);
     }
 #endif
@@ -443,8 +442,8 @@
         const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) {
 #if DEBUG_STRATEGY
     ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
-            vectorToString(x, m).string(), vectorToString(y, m).string(),
-            vectorToString(w, m).string());
+            vectorToString(x, m).c_str(), vectorToString(y, m).c_str(),
+            vectorToString(w, m).c_str());
 #endif
 
     // Expand the X vector to a matrix A, pre-multiplied by the weights.
@@ -456,7 +455,7 @@
         }
     }
 #if DEBUG_STRATEGY
-    ALOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
+    ALOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str());
 #endif
 
     // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
@@ -491,8 +490,8 @@
         }
     }
 #if DEBUG_STRATEGY
-    ALOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
-    ALOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
+    ALOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).c_str());
+    ALOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).c_str());
 
     // calculate QR, if we factored A correctly then QR should equal A
     float qr[n][m];
@@ -504,7 +503,7 @@
             }
         }
     }
-    ALOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
+    ALOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).c_str());
 #endif
 
     // Solve R B = Qt W Y to find B.  This is easy because R is upper triangular.
@@ -522,7 +521,7 @@
         outB[i] /= r[i][i];
     }
 #if DEBUG_STRATEGY
-    ALOGD("  - b=%s", vectorToString(outB, n).string());
+    ALOGD("  - b=%s", vectorToString(outB, n).c_str());
 #endif
 
     // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
@@ -608,8 +607,8 @@
 #if DEBUG_STRATEGY
             ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
                     int(outEstimator->degree),
-                    vectorToString(outEstimator->xCoeff, n).string(),
-                    vectorToString(outEstimator->yCoeff, n).string(),
+                    vectorToString(outEstimator->xCoeff, n).c_str(),
+                    vectorToString(outEstimator->yCoeff, n).c_str(),
                     outEstimator->confidence);
 #endif
             return true;
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 8e69c9c..a136738 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,7 +89,8 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+            0);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -132,6 +133,7 @@
     const uint32_t seq = 15;
     const int32_t deviceId = 1;
     const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+    const int32_t displayId = 0;
     const int32_t action = AMOTION_EVENT_ACTION_MOVE;
     const int32_t actionButton = 0;
     const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -164,7 +166,7 @@
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
     }
 
-    status = mPublisher->publishMotionEvent(seq, deviceId, source, action, actionButton,
+    status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
             flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
             downTime, eventTime, pointerCount,
             pointerProperties, pointerCoords);
@@ -173,7 +175,8 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+            0);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -256,7 +259,7 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -272,7 +275,7 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 81b9953..d19f3b8 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -38,31 +38,33 @@
   CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
   CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
   CHECK_OFFSET(InputMessage::Body::Key, source, 20);
-  CHECK_OFFSET(InputMessage::Body::Key, action, 24);
-  CHECK_OFFSET(InputMessage::Body::Key, flags, 28);
-  CHECK_OFFSET(InputMessage::Body::Key, keyCode, 32);
-  CHECK_OFFSET(InputMessage::Body::Key, scanCode, 36);
-  CHECK_OFFSET(InputMessage::Body::Key, metaState, 40);
-  CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 44);
-  CHECK_OFFSET(InputMessage::Body::Key, downTime, 48);
+  CHECK_OFFSET(InputMessage::Body::Key, displayId, 24);
+  CHECK_OFFSET(InputMessage::Body::Key, action, 28);
+  CHECK_OFFSET(InputMessage::Body::Key, flags, 32);
+  CHECK_OFFSET(InputMessage::Body::Key, keyCode, 36);
+  CHECK_OFFSET(InputMessage::Body::Key, scanCode, 40);
+  CHECK_OFFSET(InputMessage::Body::Key, metaState, 44);
+  CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 48);
+  CHECK_OFFSET(InputMessage::Body::Key, downTime, 56);
 
   CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
   CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
   CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
   CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
-  CHECK_OFFSET(InputMessage::Body::Motion, action, 24);
-  CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 28);
-  CHECK_OFFSET(InputMessage::Body::Motion, flags, 32);
-  CHECK_OFFSET(InputMessage::Body::Motion, metaState, 36);
-  CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 40);
-  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 44);
-  CHECK_OFFSET(InputMessage::Body::Motion, downTime, 48);
-  CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 56);
-  CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 60);
-  CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 64);
-  CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 68);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 72);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 80);
+  CHECK_OFFSET(InputMessage::Body::Motion, displayId, 24);
+  CHECK_OFFSET(InputMessage::Body::Motion, action, 28);
+  CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 32);
+  CHECK_OFFSET(InputMessage::Body::Motion, flags, 36);
+  CHECK_OFFSET(InputMessage::Body::Motion, metaState, 40);
+  CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 44);
+  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, downTime, 56);
+  CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 64);
+  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);
 }
 
 } // namespace android
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3ef8b4a..693bace 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -15,6 +15,7 @@
 cc_library_static {
     name: "libmath",
     host_supported: true,
+    vendor_available: true,
     export_include_dirs: ["include"],
 }
 
diff --git a/libs/math/include/math/TMatHelpers.h b/libs/math/include/math/TMatHelpers.h
index 5cb725d..1423ade 100644
--- a/libs/math/include/math/TMatHelpers.h
+++ b/libs/math/include/math/TMatHelpers.h
@@ -342,9 +342,9 @@
 template <typename MATRIX>
 String8 asString(const MATRIX& m) {
     String8 s;
-    for (size_t c = 0; c < MATRIX::col_size(); c++) {
+    for (size_t c = 0; c < MATRIX::COL_SIZE; c++) {
         s.append("|  ");
-        for (size_t r = 0; r < MATRIX::row_size(); r++) {
+        for (size_t r = 0; r < MATRIX::ROW_SIZE; r++) {
             s.appendFormat("%7.2f  ", m[r][c]);
         }
         s.append("|\n");
diff --git a/libs/math/include/math/half.h b/libs/math/include/math/half.h
index 615b840..7682973 100644
--- a/libs/math/include/math/half.h
+++ b/libs/math/include/math/half.h
@@ -56,8 +56,8 @@
  */
 class half {
     struct fp16 {
-        uint16_t bits = 0;
-        fp16() noexcept = default;
+        uint16_t bits;
+        explicit constexpr fp16() noexcept : bits(0) { }
         explicit constexpr fp16(uint16_t b) noexcept : bits(b) { }
         void setS(unsigned int s) noexcept { bits = uint16_t((bits & 0x7FFF) | (s<<15)); }
         void setE(unsigned int s) noexcept { bits = uint16_t((bits & 0xE3FF) | (s<<10)); }
@@ -68,11 +68,11 @@
     };
     struct fp32 {
         union {
-            uint32_t bits = 0;
+            uint32_t bits;
             float fp;
         };
-        fp32() noexcept = default;
-        explicit constexpr fp32(float f) : fp(f) { }
+        explicit constexpr fp32() noexcept : bits(0) { }
+        explicit constexpr fp32(float f) noexcept : fp(f) { }
         void setS(unsigned int s) noexcept { bits = uint32_t((bits & 0x7FFFFFFF) | (s<<31)); }
         void setE(unsigned int s) noexcept { bits = uint32_t((bits & 0x807FFFFF) | (s<<23)); }
         void setM(unsigned int s) noexcept { bits = uint32_t((bits & 0xFF800000) | (s<< 0)); }
diff --git a/libs/math/tests/mat_test.cpp b/libs/math/tests/mat_test.cpp
index c365366..3217a1a 100644
--- a/libs/math/tests/mat_test.cpp
+++ b/libs/math/tests/mat_test.cpp
@@ -487,7 +487,7 @@
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_FLOAT_EQ(v1[i], v2[i]);                      \
         }                                                       \
-    } else if (std::is_same<TypeParam,float>::value) {          \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_DOUBLE_EQ(v1[i], v2[i]);                     \
         }                                                       \
@@ -506,7 +506,7 @@
     const decltype(T2) t2 = T2;                                 \
     if (std::is_same<TypeParam,float>::value) {                 \
         ASSERT_FLOAT_EQ(t1, t2);                                \
-    } else if (std::is_same<TypeParam,float>::value) {         \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         ASSERT_DOUBLE_EQ(t1, t2);                               \
     } else {                                                    \
         ASSERT_EQ(t1, t2);                                      \
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
new file mode 100644
index 0000000..7375a2b
--- /dev/null
+++ b/libs/nativebase/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "libnativebase_headers",
+    vendor_available: true,
+    host_supported: true,
+    export_include_dirs: ["include"],
+
+    target: {
+        linux_bionic: {
+            enabled: true,
+        },
+        windows: {
+            enabled: true,
+        },
+    }
+}
diff --git a/cmds/dumpstate/testdata/empty-file.txt b/libs/nativebase/MODULE_LICENSE_APACHE2
similarity index 100%
copy from cmds/dumpstate/testdata/empty-file.txt
copy to libs/nativebase/MODULE_LICENSE_APACHE2
diff --git a/libs/nativebase/NOTICE b/libs/nativebase/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/libs/nativebase/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libs/nativebase/include/nativebase/nativebase.h b/libs/nativebase/include/nativebase/nativebase.h
new file mode 100644
index 0000000..7ecdfbd
--- /dev/null
+++ b/libs/nativebase/include/nativebase/nativebase.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <system/graphics-base.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+#ifdef __cplusplus
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
+#else
+#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
+#endif
+
+#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d)  \
+    ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
+     (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
+     (ANDROID_NATIVE_UNSIGNED_CAST(c) <<  8) | \
+     (ANDROID_NATIVE_UNSIGNED_CAST(d)))
+
+#define ANDROID_NATIVE_BUFFER_MAGIC     ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
+
+
+typedef struct android_native_base_t
+{
+    /* a magic value defined by the actual EGL native type */
+    int magic;
+
+    /* the sizeof() of the actual EGL native type */
+    int version;
+
+    void* reserved[4];
+
+    /* reference-counting interface */
+    void (*incRef)(struct android_native_base_t* base);
+    void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+typedef struct android_native_rect_t
+{
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} android_native_rect_t;
+
+typedef struct ANativeWindowBuffer
+{
+#ifdef __cplusplus
+    ANativeWindowBuffer() {
+        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
+        common.version = sizeof(ANativeWindowBuffer);
+        memset(common.reserved, 0, sizeof(common.reserved));
+    }
+
+    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
+    // can be used to automatically refcount ANativeWindowBuffer's.
+    void incStrong(const void* /*id*/) const {
+        common.incRef(const_cast<android_native_base_t*>(&common));
+    }
+    void decStrong(const void* /*id*/) const {
+        common.decRef(const_cast<android_native_base_t*>(&common));
+    }
+#endif
+
+    struct android_native_base_t common;
+
+    int width;
+    int height;
+    int stride;
+    int format;
+    int usage_deprecated;
+    uintptr_t layerCount;
+
+    void* reserved[1];
+
+    const native_handle_t* handle;
+    uint64_t usage;
+
+    // we needed extra space for storing the 64-bits usage flags
+    // the number of slots to use from reserved_proc depends on the
+    // architecture.
+    void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
+} ANativeWindowBuffer_t;
+
+typedef struct ANativeWindowBuffer ANativeWindowBuffer;
+
+// Old typedef for backwards compatibility.
+typedef ANativeWindowBuffer_t android_native_buffer_t;
+
+__END_DECLS
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index f64bab1..c6994c3 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "ANativeWindow"
 
-#include <android/native_window.h>
-
 #include <grallocusage/GrallocUsageConversion.h>
 // from nativewindow/includes/system/window.h
 // (not to be confused with the compatibility-only window.h from system/core/includes)
@@ -192,8 +190,7 @@
 }
 
 int ANativeWindow_setUsage(ANativeWindow* window, uint64_t usage) {
-    usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
-    return native_window_set_usage(window, (uint32_t)usage); // FIXME: we need a 64-bits version
+    return native_window_set_usage(window, usage);
 }
 
 int ANativeWindow_setBufferCount(ANativeWindow* window, size_t bufferCount) {
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index d759acb..e61fbd6 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -57,10 +57,25 @@
         "libgrallocusage",
     ],
 
+    header_libs: [
+        "libnativebase_headers",
+    ],
+
     // headers we include in our public headers
     export_static_lib_headers: [
         "libarect",
     ],
+
+    export_header_lib_headers: [
+        "libnativebase_headers",
+    ],
+}
+
+llndk_library {
+    name: "libnativewindow",
+    symbol_file: "libnativewindow.map.txt",
+    unversioned: true,
+    export_include_dirs: ["include"],
 }
 
 subdirs = ["tests"]
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 45110c4..6490804 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -60,25 +60,6 @@
 
 // ---------------------------------------------------------------------------
 
-typedef const native_handle_t* buffer_handle_t;
-
-// ---------------------------------------------------------------------------
-
-typedef struct android_native_rect_t
-{
-    int32_t left;
-    int32_t top;
-    int32_t right;
-    int32_t bottom;
-} android_native_rect_t;
-
-// ---------------------------------------------------------------------------
-
-// Old typedef for backwards compatibility.
-typedef ANativeWindowBuffer_t android_native_buffer_t;
-
-// ---------------------------------------------------------------------------
-
 /* attributes queriable with query() */
 enum {
     NATIVE_WINDOW_WIDTH     = 0,
@@ -134,7 +115,7 @@
      * The consumer gralloc usage bits currently set by the consumer.
      * The values are defined in hardware/libhardware/include/gralloc.h.
      */
-    NATIVE_WINDOW_CONSUMER_USAGE_BITS = 10,
+    NATIVE_WINDOW_CONSUMER_USAGE_BITS = 10, /* deprecated */
 
     /**
      * Transformation that will by applied to buffers by the hwcomposer.
@@ -212,36 +193,38 @@
  */
 enum {
 // clang-format off
-    NATIVE_WINDOW_SET_USAGE                 =  0,
-    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,   /* private */
-    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_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,
 // clang-format on
 };
 
@@ -549,24 +532,21 @@
  /* Backwards compatibility: use ANativeWindow (struct ANativeWindow in C).
   * android_native_window_t is deprecated.
   */
-typedef struct ANativeWindow ANativeWindow;
 typedef struct ANativeWindow android_native_window_t __deprecated;
 
 /*
- *  native_window_set_usage(..., usage)
+ *  native_window_set_usage64(..., usage)
  *  Sets the intended usage flags for the next buffers
  *  acquired with (*lockBuffer)() and on.
- *  By default (if this function is never called), a usage of
- *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
- *  is assumed.
+ *
+ *  Valid usage flags are defined in android/hardware_buffer.h
+ *  All AHARDWAREBUFFER_USAGE_* flags can be specified as needed.
+ *
  *  Calling this function will usually cause following buffers to be
  *  reallocated.
  */
-
-static inline int native_window_set_usage(
-        struct ANativeWindow* window, int usage)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+static inline int native_window_set_usage(struct ANativeWindow* window, uint64_t usage) {
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE64, usage);
 }
 
 /* deprecated. Always returns 0. Don't call. */
@@ -609,45 +589,6 @@
 }
 
 /*
- * native_window_set_post_transform_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * Depending on the scaling mode, a buffer's crop region is scaled and/or
- * cropped to match the surface's size.  This function sets the crop in
- * post-transformed pixel coordinates.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * If 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid, out of the
- * buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_post_transform_crop(
-        struct ANativeWindow* window,
-        android_native_rect_t const * crop)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
-}
-
-/*
- * native_window_set_active_rect(..., active_rect)
- *
- * This function is deprecated and will be removed soon.  For now it simply
- * sets the post-transform crop for compatibility while multi-project commits
- * get checked.
- */
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect) __deprecated;
-
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect)
-{
-    return native_window_set_post_transform_crop(window, active_rect);
-}
-
-/*
  * native_window_set_buffer_count(..., count)
  * Sets the number of buffers associated with this native window.
  */
@@ -960,13 +901,18 @@
 
 static inline int native_window_get_wide_color_support(
     struct ANativeWindow* window, bool* outSupport) {
-  return window->perform(window, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT,
-                         outSupport);
+    return window->perform(window, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT,
+            outSupport);
 }
 
 static inline int native_window_get_hdr_support(struct ANativeWindow* window,
                                                 bool* outSupport) {
-  return window->perform(window, NATIVE_WINDOW_GET_HDR_SUPPORT, outSupport);
+    return window->perform(window, NATIVE_WINDOW_GET_HDR_SUPPORT, outSupport);
+}
+
+static inline int native_window_get_consumer_usage(struct ANativeWindow* window,
+                                                   uint64_t* outUsage) {
+    return window->perform(window, NATIVE_WINDOW_GET_CONSUMER_USAGE64, outUsage);
 }
 
 __END_DECLS
diff --git a/libs/nativewindow/include/vndk/window.h b/libs/nativewindow/include/vndk/window.h
index 95618c4..a7b340a 100644
--- a/libs/nativewindow/include/vndk/window.h
+++ b/libs/nativewindow/include/vndk/window.h
@@ -17,88 +17,14 @@
 #ifndef ANDROID_VNDK_NATIVEWINDOW_ANATIVEWINDOW_H
 #define ANDROID_VNDK_NATIVEWINDOW_ANATIVEWINDOW_H
 
-#include <stdint.h>
-#include <stdbool.h>
-#include <sys/cdefs.h>
-#include <system/graphics-base.h>
-#include <cutils/native_handle.h>
+#include <nativebase/nativebase.h>
 
 // vndk is a superset of the NDK
 #include <android/native_window.h>
 
+
 __BEGIN_DECLS
 
-/*****************************************************************************/
-
-#ifdef __cplusplus
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
-#else
-#define ANDROID_NATIVE_UNSIGNED_CAST(x) ((unsigned int)(x))
-#endif
-
-#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d)  \
-    ((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(c) <<  8) | \
-     (ANDROID_NATIVE_UNSIGNED_CAST(d)))
-
-#define ANDROID_NATIVE_BUFFER_MAGIC     ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r')
-
-
-/*****************************************************************************/
-
-typedef struct android_native_base_t
-{
-    /* a magic value defined by the actual EGL native type */
-    int magic;
-
-    /* the sizeof() of the actual EGL native type */
-    int version;
-
-    void* reserved[4];
-
-    /* reference-counting interface */
-    void (*incRef)(struct android_native_base_t* base);
-    void (*decRef)(struct android_native_base_t* base);
-} android_native_base_t;
-
-typedef struct ANativeWindowBuffer
-{
-#ifdef __cplusplus
-    ANativeWindowBuffer() {
-        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
-        common.version = sizeof(ANativeWindowBuffer);
-        memset(common.reserved, 0, sizeof(common.reserved));
-    }
-
-    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
-    // can be used to automatically refcount ANativeWindowBuffer's.
-    void incStrong(const void* /*id*/) const {
-        common.incRef(const_cast<android_native_base_t*>(&common));
-    }
-    void decStrong(const void* /*id*/) const {
-        common.decRef(const_cast<android_native_base_t*>(&common));
-    }
-#endif
-
-    struct android_native_base_t common;
-
-    int width;
-    int height;
-    int stride;
-    int format;
-    int usage;
-    uintptr_t layerCount;
-
-    void* reserved[1];
-
-    const native_handle_t* handle;
-
-    void* reserved_proc[8];
-} ANativeWindowBuffer_t;
-
-typedef struct ANativeWindowBuffer ANativeWindowBuffer;
-
 /*
  * Convert this ANativeWindowBuffer into a AHardwareBuffer
  */
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index b1d1a72..58045be 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -4,22 +4,40 @@
     AHardwareBuffer_allocate;
     AHardwareBuffer_describe;
     AHardwareBuffer_fromHardwareBuffer;
+    AHardwareBuffer_getNativeHandle; # vndk
     AHardwareBuffer_lock;
     AHardwareBuffer_recvHandleFromUnixSocket;
     AHardwareBuffer_release;
     AHardwareBuffer_sendHandleToUnixSocket;
     AHardwareBuffer_toHardwareBuffer;
     AHardwareBuffer_unlock;
+    ANativeWindowBuffer_getHardwareBuffer; # vndk
+    ANativeWindow_OemStorageGet; # vndk
+    ANativeWindow_OemStorageSet; # vndk
     ANativeWindow_acquire;
+    ANativeWindow_cancelBuffer; # vndk
+    ANativeWindow_dequeueBuffer; # vndk
     ANativeWindow_fromSurface;
     ANativeWindow_fromSurfaceTexture;
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getWidth;
     ANativeWindow_lock;
+    ANativeWindow_query; # vndk
+    ANativeWindow_queryf; # vndk
+    ANativeWindow_queueBuffer; # vndk
     ANativeWindow_release;
+    ANativeWindow_setAutoRefresh; # vndk
+    ANativeWindow_setBufferCount; # vndk
+    ANativeWindow_setBufferDataSpace; # vndk
+    ANativeWindow_setBuffersDimensions; # vndk
+    ANativeWindow_setBuffersFormat; # vndk
     ANativeWindow_setBuffersGeometry;
+    ANativeWindow_setBuffersTimestamp; # vndk
     ANativeWindow_setBuffersTransform;
+    ANativeWindow_setSharedBufferMode; # vndk
+    ANativeWindow_setSwapInterval; # vndk
+    ANativeWindow_setUsage; # vndk
     ANativeWindow_unlockAndPost;
   local:
     *;
diff --git a/libs/sensor/ISensorEventConnection.cpp b/libs/sensor/ISensorEventConnection.cpp
index 8a3a623..1cd8e01 100644
--- a/libs/sensor/ISensorEventConnection.cpp
+++ b/libs/sensor/ISensorEventConnection.cpp
@@ -36,7 +36,8 @@
     ENABLE_DISABLE,
     SET_EVENT_RATE,
     FLUSH_SENSOR,
-    CONFIGURE_CHANNEL
+    CONFIGURE_CHANNEL,
+    DESTROY,
 };
 
 class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
@@ -96,11 +97,22 @@
         remote()->transact(CONFIGURE_CHANNEL, data, &reply);
         return reply.readInt32();
     }
+
+    virtual void onLastStrongRef(const void* id) {
+        destroy();
+        BpInterface<ISensorEventConnection>::onLastStrongRef(id);
+    }
+
+protected:
+    virtual void destroy() {
+        Parcel data, reply;
+        remote()->transact(DESTROY, data, &reply);
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
 // translation unit (see clang warning -Wweak-vtables)
-BpSensorEventConnection::~BpSensorEventConnection() {}
+BpSensorEventConnection::~BpSensorEventConnection() { }
 
 IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection");
 
@@ -150,6 +162,10 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case DESTROY: {
+            destroy();
+            return NO_ERROR;
+        }
 
     }
     return BBinder::onTransact(code, data, reply, flags);
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index 74186df..f20668d 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -119,10 +119,12 @@
         return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
     }
 
-    virtual int setOperationParameter(
-            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+    virtual int setOperationParameter(int32_t handle, int32_t type,
+                                      const Vector<float> &floats,
+                                      const Vector<int32_t> &ints) {
         Parcel data, reply;
         data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+        data.writeInt32(handle);
         data.writeInt32(type);
         data.writeUint32(static_cast<uint32_t>(floats.size()));
         for (auto i : floats) {
@@ -203,10 +205,12 @@
         }
         case SET_OPERATION_PARAMETER: {
             CHECK_INTERFACE(ISensorServer, data, reply);
+            int32_t handle;
             int32_t type;
             Vector<float> floats;
             Vector<int32_t> ints;
 
+            handle = data.readInt32();
             type = data.readInt32();
             floats.resize(data.readUint32());
             for (auto &i : floats) {
@@ -217,7 +221,7 @@
                 i = data.readInt32();
             }
 
-            int32_t ret = setOperationParameter(type, floats, ints);
+            int32_t ret = setOperationParameter(handle, type, floats, ints);
             reply->writeInt32(ret);
             return NO_ERROR;
         }
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index c2d477e..a0e368c 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -30,7 +30,7 @@
         mName(name), mHandle(0), mType(0),
         mMinValue(0), mMaxValue(0), mResolution(0),
         mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
-        mFifoMaxEventCount(0), mRequiredAppOp(0),
+        mFifoMaxEventCount(0), mRequiredAppOp(-1),
         mMaxDelay(0), mFlags(0) {
 }
 
@@ -38,7 +38,8 @@
         Sensor(*hwSensor, uuid_t(), halVersion) {
 }
 
-Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) :
+        Sensor("") {
     mName = hwSensor.name;
     mVendor = hwSensor.vendor;
     mVersion = hwSensor.version;
@@ -412,6 +413,10 @@
     return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
 }
 
+bool Sensor::isDataInjectionSupported() const {
+    return (mFlags & SENSOR_FLAG_DATA_INJECTION) != 0;
+}
+
 bool Sensor::hasAdditionalInfo() const {
     return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
 }
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 3fbc5eb..6fe72a1 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -305,12 +305,13 @@
 }
 
 int SensorManager::setOperationParameter(
-        int type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+        int handle, int type,
+        const Vector<float> &floats, const Vector<int32_t> &ints) {
     Mutex::Autolock _l(mLock);
     if (assertStateLocked() != NO_ERROR) {
         return NO_INIT;
     }
-    return mSensorServer->setOperationParameter(type, floats, ints);
+    return mSensorServer->setOperationParameter(handle, type, floats, ints);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/ISensorEventConnection.h b/libs/sensor/include/sensor/ISensorEventConnection.h
index 07cc7e8..b62e18c 100644
--- a/libs/sensor/include/sensor/ISensorEventConnection.h
+++ b/libs/sensor/include/sensor/ISensorEventConnection.h
@@ -42,6 +42,8 @@
     virtual status_t setEventRate(int handle, nsecs_t ns) = 0;
     virtual status_t flush() = 0;
     virtual int32_t configureChannel(int32_t handle, int32_t rateLevel) = 0;
+protected:
+    virtual void destroy() = 0; // synchronously release resource hold by remote object
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index 8d50062..edf3e0f 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -52,7 +52,7 @@
             uint32_t size, int32_t type, int32_t format, const native_handle_t *resource) = 0;
 
     virtual int setOperationParameter(
-            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) = 0;
+            int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 043e635..6926f7f 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -90,6 +90,7 @@
     uint32_t getFlags() const;
     bool isWakeUpSensor() const;
     bool isDynamicSensor() const;
+    bool isDataInjectionSupported() const;
     bool hasAdditionalInfo() const;
     int32_t getHighestDirectReportRateLevel() const;
     bool isDirectChannelTypeSupported(int32_t sharedMemType) const;
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 5fc85d3..23f7a91 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -64,7 +64,7 @@
     int createDirectChannel(size_t size, int channelType, const native_handle_t *channelData);
     void destroyDirectChannel(int channelNativeHandle);
     int configureDirectChannel(int channelNativeHandle, int sensorHandle, int rateLevel);
-    int setOperationParameter(int type, const Vector<float> &floats, const Vector<int32_t> &ints);
+    int setOperationParameter(int handle, int type, const Vector<float> &floats, const Vector<int32_t> &ints);
 
 private:
     // DeathRecipient interface
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 5edd664..59173cb 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -15,6 +15,9 @@
 cc_library_shared {
     name: "libui",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     clang: true,
     cppflags: [
@@ -54,7 +57,6 @@
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
-        "GraphicsEnv.cpp",
         "HdrCapabilities.cpp",
         "PixelFormat.cpp",
         "Rect.cpp",
@@ -70,9 +72,8 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.configstore@1.0",
-	"android.hardware.configstore-utils",
+        "android.hardware.configstore-utils",
         "libbase",
-        "libnativeloader",
         "libcutils",
         "libhardware",
         "libhidlbase",
@@ -89,10 +90,28 @@
         "libmath",
     ],
 
+    header_libs: [
+        "libnativebase_headers",
+        "libhardware_headers",
+    ],
+
+    export_include_dirs: ["include"],
+
     export_static_lib_headers: [
         "libarect",
         "libmath",
     ],
+
+    export_header_lib_headers: [
+        "libnativebase_headers",
+        "libhardware_headers",
+    ],
+}
+
+cc_library_headers {
+    name: "libui_headers",
+    export_include_dirs: ["include"],
+    vendor_available: true,
 }
 
 subdirs = ["tests"]
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 882bd7c..d5676cc 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ui/DebugUtils.h>
+#include <ui/PixelFormat.h>
 
 #include <android-base/stringprintf.h>
 #include <string>
@@ -58,24 +59,20 @@
         case 0:
             switch (dataspace & 0xffff) {
                 case HAL_DATASPACE_JFIF:
-                    return std::string("(deprecated) JFIF (BT601_625, SMPTE_170M Full range)");
+                    return std::string("(deprecated) JFIF (BT601_625)");
 
                 case HAL_DATASPACE_BT601_625:
-                    return std::string("(deprecated) BT601_625 (BT601_625, SMPTE_170M Limited "
-                                       "range)");
+                    return std::string("(deprecated) BT601_625");
 
                 case HAL_DATASPACE_BT601_525:
-                    return std::string("(deprecated) BT601_525 (BT601_525, SMPTE_170M Limited "
-                                       "range)");
+                    return std::string("(deprecated) BT601_525");
 
                 case HAL_DATASPACE_SRGB_LINEAR:
-                    return std::string("(deprecated) SRGB Linear Full range");
-
                 case HAL_DATASPACE_SRGB:
                     return std::string("(deprecated) sRGB");
 
                 case HAL_DATASPACE_V0_BT709:
-                    return std::string("(deprecated) BT709 (BT709, SMPTE_170M Limited range)");
+                    return std::string("(deprecated) BT709");
 
                 case HAL_DATASPACE_ARBITRARY:
                     return std::string("ARBITRARY");
@@ -92,6 +89,29 @@
 }
 
 std::string decodeTransfer(android_dataspace dataspace) {
+    const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
+    if (dataspaceSelect == 0) {
+        switch (dataspace & 0xffff) {
+            case HAL_DATASPACE_JFIF:
+            case HAL_DATASPACE_BT601_625:
+            case HAL_DATASPACE_BT601_525:
+            case HAL_DATASPACE_V0_BT709:
+                return std::string("SMPTE_170M");
+
+            case HAL_DATASPACE_SRGB_LINEAR:
+            case HAL_DATASPACE_ARBITRARY:
+                return std::string("Linear");
+
+            case HAL_DATASPACE_SRGB:
+                return std::string("sRGB");
+
+            case HAL_DATASPACE_UNKNOWN:
+            // Fallthrough
+            default:
+                return std::string("");
+        }
+    }
+
     const uint32_t dataspaceTransfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK);
     switch (dataspaceTransfer) {
         case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
@@ -126,6 +146,27 @@
 }
 
 std::string decodeRange(android_dataspace dataspace) {
+    const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
+    if (dataspaceSelect == 0) {
+        switch (dataspace & 0xffff) {
+            case HAL_DATASPACE_JFIF:
+            case HAL_DATASPACE_SRGB_LINEAR:
+            case HAL_DATASPACE_SRGB:
+                return std::string("Full range");
+
+            case HAL_DATASPACE_BT601_625:
+            case HAL_DATASPACE_BT601_525:
+            case HAL_DATASPACE_V0_BT709:
+                return std::string("Limited range)");
+
+            case HAL_DATASPACE_ARBITRARY:
+            case HAL_DATASPACE_UNKNOWN:
+            // Fallthrough
+            default:
+                return std::string("unspecified range");
+        }
+    }
+
     const uint32_t dataspaceRange = (dataspace & HAL_DATASPACE_RANGE_MASK);
     switch (dataspaceRange) {
         case HAL_DATASPACE_RANGE_UNSPECIFIED:
@@ -145,6 +186,9 @@
 }
 
 std::string dataspaceDetails(android_dataspace dataspace) {
+    if (dataspace == 0) {
+        return "Default (0)";
+    }
     return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
                                        decodeTransfer(dataspace).c_str(),
                                        decodeRange(dataspace).c_str());
@@ -185,3 +229,36 @@
 
     return android::base::StringPrintf("Unknown color mode %d", colorMode);
 }
+
+// Converts a PixelFormat to a human-readable string.  Max 11 chars.
+// (Could use a table of prefab String8 objects.)
+std::string decodePixelFormat(android::PixelFormat format) {
+    switch (format) {
+        case android::PIXEL_FORMAT_UNKNOWN:
+            return std::string("Unknown/None");
+        case android::PIXEL_FORMAT_CUSTOM:
+            return std::string("Custom");
+        case android::PIXEL_FORMAT_TRANSLUCENT:
+            return std::string("Translucent");
+        case android::PIXEL_FORMAT_TRANSPARENT:
+            return std::string("Transparent");
+        case android::PIXEL_FORMAT_OPAQUE:
+            return std::string("Opaque");
+        case android::PIXEL_FORMAT_RGBA_8888:
+            return std::string("RGBA_8888");
+        case android::PIXEL_FORMAT_RGBX_8888:
+            return std::string("RGBx_8888");
+        case android::PIXEL_FORMAT_RGBA_FP16:
+            return std::string("RGBA_FP16");
+        case android::PIXEL_FORMAT_RGBA_1010102:
+            return std::string("RGBA_1010102");
+        case android::PIXEL_FORMAT_RGB_888:
+            return std::string("RGB_888");
+        case android::PIXEL_FORMAT_RGB_565:
+            return std::string("RGB_565");
+        case android::PIXEL_FORMAT_BGRA_8888:
+            return std::string("BGRA_8888");
+        default:
+            return android::base::StringPrintf("Unknown %#08x", format);
+    }
+}
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 87dbaf4..0eb08e5 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "Gralloc2"
 
+#include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
 #include <ui/Gralloc2.h>
 
@@ -31,6 +32,10 @@
 
 static constexpr Error kTransactionError = Error::NO_RESOURCES;
 
+void Mapper::preload() {
+    android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
+}
+
 Mapper::Mapper()
 {
     mMapper = IMapper::getService();
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index ee85c9b..c880500 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -51,6 +51,7 @@
     height =
     stride =
     format =
+    usage_deprecated = 0;
     usage  = 0;
     layerCount = 0;
     handle = NULL;
@@ -59,14 +60,12 @@
 // deprecated
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
         PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
-    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage),
-            requestorName)
+    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
 {
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage,
-        std::string requestorName)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
     : GraphicBuffer()
 {
     mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
@@ -139,7 +138,7 @@
             static_cast<int>(inHeight) == height &&
             inFormat == format &&
             inLayerCount == layerCount &&
-            static_cast<int>(inUsage) == usage)
+            inUsage == usage)
         return NO_ERROR;
 
     if (handle) {
@@ -147,8 +146,7 @@
         allocator.free(handle);
         handle = 0;
     }
-    return initWithSize(inWidth, inHeight, inFormat, inLayerCount,
-            inUsage, "[Reallocation]");
+    return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
 }
 
 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
@@ -158,7 +156,7 @@
     if (static_cast<int>(inHeight) != height) return true;
     if (inFormat != format) return true;
     if (inLayerCount != layerCount) return true;
-    if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
+    if ((usage & inUsage) != inUsage) return true;
     return false;
 }
 
@@ -176,7 +174,8 @@
         height = static_cast<int>(inHeight);
         format = inFormat;
         layerCount = inLayerCount;
-        usage = static_cast<int>(inUsage);
+        usage = inUsage;
+        usage_deprecated = int(usage);
         stride = static_cast<int>(outStride);
     }
     return err;
@@ -191,7 +190,8 @@
     ANativeWindowBuffer::height = static_cast<int>(height);
     ANativeWindowBuffer::stride = static_cast<int>(stride);
     ANativeWindowBuffer::format = format;
-    ANativeWindowBuffer::usage  = static_cast<int>(usage);
+    ANativeWindowBuffer::usage  = usage;
+    ANativeWindowBuffer::usage_deprecated = int(usage);
 
     ANativeWindowBuffer::layerCount = layerCount;
 
@@ -312,8 +312,7 @@
                 width, height);
         return BAD_VALUE;
     }
-    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
-            ycbcr, fenceFd);
+    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, ycbcr, fenceFd);
     return res;
 }
 
@@ -324,7 +323,7 @@
 }
 
 size_t GraphicBuffer::getFlattenedSize() const {
-    return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
+    return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
@@ -339,25 +338,25 @@
     if (count < fdCountNeeded) return NO_MEMORY;
 
     int32_t* buf = static_cast<int32_t*>(buffer);
-    buf[0] = 'GBFR';
+    buf[0] = 'GB01';
     buf[1] = width;
     buf[2] = height;
     buf[3] = stride;
     buf[4] = format;
     buf[5] = static_cast<int32_t>(layerCount);
-    buf[6] = usage;
+    buf[6] = int(usage); // low 32-bits
     buf[7] = static_cast<int32_t>(mId >> 32);
     buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
     buf[9] = static_cast<int32_t>(mGenerationNumber);
     buf[10] = 0;
     buf[11] = 0;
+    buf[12] = int(usage >> 32); // high 32-bits
 
     if (handle) {
         buf[10] = handle->numFds;
         buf[11] = handle->numInts;
-        memcpy(fds, handle->data,
-                static_cast<size_t>(handle->numFds) * sizeof(int));
-        memcpy(&buf[12], handle->data + handle->numFds,
+        memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
+        memcpy(buf + 13, handle->data + handle->numFds,
                 static_cast<size_t>(handle->numInts) * sizeof(int));
     }
 
@@ -373,10 +372,21 @@
 
 status_t GraphicBuffer::unflatten(
         void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-    if (size < 12 * sizeof(int)) return NO_MEMORY;
 
     int const* buf = static_cast<int const*>(buffer);
-    if (buf[0] != 'GBFR') return BAD_TYPE;
+
+    // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
+    // see H2BGraphicBufferProducer.cpp
+    uint32_t flattenWordCount = 0;
+    if (buf[0] == 'GB01') {
+        // new version with 64-bits usage bits
+        flattenWordCount = 13;
+    } else if (buf[0] == 'GBFR') {
+        // old version, when usage bits were 32-bits
+        flattenWordCount = 12;
+    } else {
+        return BAD_TYPE;
+    }
 
     const size_t numFds  = static_cast<size_t>(buf[10]);
     const size_t numInts = static_cast<size_t>(buf[11]);
@@ -386,15 +396,16 @@
     // chosen to be high enough to not cause issues and low enough to prevent
     // overflow problems.
     const size_t maxNumber = 4096;
-    if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
-        width = height = stride = format = layerCount = usage = 0;
+    if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
+        width = height = stride = format = usage_deprecated = 0;
+        layerCount = 0;
+        usage = 0;
         handle = NULL;
-        ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
-                numFds, numInts);
+        ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
         return BAD_VALUE;
     }
 
-    const size_t sizeNeeded = (12 + numInts) * sizeof(int);
+    const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
     size_t fdCountNeeded = numFds;
@@ -411,20 +422,29 @@
         stride = buf[3];
         format = buf[4];
         layerCount = static_cast<uintptr_t>(buf[5]);
-        usage  = buf[6];
+        usage_deprecated = buf[6];
+        if (flattenWordCount == 13) {
+            usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
+        } else {
+            usage = uint64_t(usage_deprecated);
+        }
         native_handle* h = native_handle_create(
                 static_cast<int>(numFds), static_cast<int>(numInts));
         if (!h) {
-            width = height = stride = format = layerCount = usage = 0;
+            width = height = stride = format = usage_deprecated = 0;
+            layerCount = 0;
+            usage = 0;
             handle = NULL;
             ALOGE("unflatten: native_handle_create failed");
             return NO_MEMORY;
         }
         memcpy(h->data, fds, numFds * sizeof(int));
-        memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
+        memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
         handle = h;
     } else {
-        width = height = stride = format = layerCount = usage = 0;
+        width = height = stride = format = usage_deprecated = 0;
+        layerCount = 0;
+        usage = 0;
         handle = NULL;
     }
 
@@ -439,10 +459,11 @@
         buffer_handle_t importedHandle;
         status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
         if (err != NO_ERROR) {
-            width = height = stride = format = layerCount = usage = 0;
+            width = height = stride = format = usage_deprecated = 0;
+            layerCount = 0;
+            usage = 0;
             handle = NULL;
-            ALOGE("unflatten: registerBuffer failed: %s (%d)",
-                    strerror(-err), err);
+            ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
             return err;
         }
 
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index b9fa640..d52c508 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -42,6 +42,10 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
 
+void GraphicBufferMapper::preloadHal() {
+    Gralloc2::Mapper::preload();
+}
+
 GraphicBufferMapper::GraphicBufferMapper()
   : mMapper(std::make_unique<const Gralloc2::Mapper>())
 {
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index 39adc5e..755e60c 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -76,7 +76,7 @@
     mMaxAverageLuminance = reinterpret_cast<float const&>(buf[1]);
     mMinLuminance        = reinterpret_cast<float const&>(buf[2]);
     if (itemCount) {
-        mSupportedHdrTypes.reserve(itemCount);
+        mSupportedHdrTypes.resize(itemCount);
         for (size_t i = 0; i < itemCount; ++i) {
             mSupportedHdrTypes[i] = buf[4 + i];
         }
diff --git a/include/ui/ANativeObjectBase.h b/libs/ui/include/ui/ANativeObjectBase.h
similarity index 71%
rename from include/ui/ANativeObjectBase.h
rename to libs/ui/include/ui/ANativeObjectBase.h
index 640e34b..e9d5d8d 100644
--- a/include/ui/ANativeObjectBase.h
+++ b/libs/ui/include/ui/ANativeObjectBase.h
@@ -19,26 +19,8 @@
 
 #include <sys/types.h>
 
-#include <system/window.h>
+#include <nativebase/nativebase.h>
 
-// ---------------------------------------------------------------------------
-
-/* FIXME: this is legacy for pixmaps */
-typedef struct egl_native_pixmap_t
-{
-    int32_t     version;    /* must be 32 */
-    int32_t     width;
-    int32_t     height;
-    int32_t     stride;
-    uint8_t*    data;
-    uint8_t     format;
-    uint8_t     rfu[3];
-    union {
-        uint32_t    compressedFormat;
-        int32_t     vstride;
-    };
-    int32_t     reserved;
-} egl_native_pixmap_t;
 
 /*****************************************************************************/
 
@@ -52,7 +34,8 @@
  * This helper class turns a ANativeXXX object type into a C++
  * reference-counted object; with proper type conversions.
  */
-template <typename NATIVE_TYPE, typename TYPE, typename REF>
+template <typename NATIVE_TYPE, typename TYPE, typename REF,
+        typename NATIVE_BASE = android_native_base_t>
 class ANativeObjectBase : public NATIVE_TYPE, public REF
 {
 public:
@@ -65,7 +48,7 @@
     }
 
 protected:
-    typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;
+    typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF, NATIVE_BASE> BASE;
     ANativeObjectBase() : NATIVE_TYPE(), REF() {
         NATIVE_TYPE::common.incRef = incRef;
         NATIVE_TYPE::common.decRef = decRef;
@@ -76,17 +59,17 @@
     static inline TYPE const* getSelf(NATIVE_TYPE const* self) {
         return static_cast<TYPE const *>(self);
     }
-    static inline TYPE* getSelf(android_native_base_t* base) {
+    static inline TYPE* getSelf(NATIVE_BASE* base) {
         return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));
     }
-    static inline TYPE const * getSelf(android_native_base_t const* base) {
+    static inline TYPE const * getSelf(NATIVE_BASE const* base) {
         return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));
     }
-    static void incRef(android_native_base_t* base) {
+    static void incRef(NATIVE_BASE* base) {
         ANativeObjectBase* self = getSelf(base);
         self->incStrong(self);
     }
-    static void decRef(android_native_base_t* base) {
+    static void decRef(NATIVE_BASE* base) {
         ANativeObjectBase* self = getSelf(base);
         self->decStrong(self);
     }
diff --git a/include/ui/BufferQueueDefs.h b/libs/ui/include/ui/BufferQueueDefs.h
similarity index 100%
rename from include/ui/BufferQueueDefs.h
rename to libs/ui/include/ui/BufferQueueDefs.h
diff --git a/include/ui/ColorSpace.h b/libs/ui/include/ui/ColorSpace.h
similarity index 100%
rename from include/ui/ColorSpace.h
rename to libs/ui/include/ui/ColorSpace.h
diff --git a/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
similarity index 91%
rename from include/ui/DebugUtils.h
rename to libs/ui/include/ui/DebugUtils.h
index 8483808..30f4a59 100644
--- a/include/ui/DebugUtils.h
+++ b/libs/ui/include/ui/DebugUtils.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <system/graphics.h>
+#include <ui/PixelFormat.h>
 
 #include <string>
 
@@ -25,3 +26,4 @@
 std::string decodeRange(android_dataspace dataspace);
 std::string dataspaceDetails(android_dataspace dataspace);
 std::string decodeColorMode(android_color_mode colormode);
+std::string decodePixelFormat(android::PixelFormat format);
diff --git a/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h
similarity index 100%
rename from include/ui/DisplayInfo.h
rename to libs/ui/include/ui/DisplayInfo.h
diff --git a/include/ui/DisplayStatInfo.h b/libs/ui/include/ui/DisplayStatInfo.h
similarity index 100%
rename from include/ui/DisplayStatInfo.h
rename to libs/ui/include/ui/DisplayStatInfo.h
diff --git a/include/ui/Fence.h b/libs/ui/include/ui/Fence.h
similarity index 100%
rename from include/ui/Fence.h
rename to libs/ui/include/ui/Fence.h
diff --git a/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
similarity index 100%
rename from include/ui/FenceTime.h
rename to libs/ui/include/ui/FenceTime.h
diff --git a/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h
similarity index 100%
rename from include/ui/FloatRect.h
rename to libs/ui/include/ui/FloatRect.h
diff --git a/include/ui/FrameStats.h b/libs/ui/include/ui/FrameStats.h
similarity index 100%
rename from include/ui/FrameStats.h
rename to libs/ui/include/ui/FrameStats.h
diff --git a/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
similarity index 98%
rename from include/ui/Gralloc2.h
rename to libs/ui/include/ui/Gralloc2.h
index f826b92..8aee160 100644
--- a/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -21,7 +21,6 @@
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -39,6 +38,8 @@
 // A wrapper to IMapper
 class Mapper {
 public:
+    static void preload();
+
     Mapper();
 
     Error createDescriptor(
diff --git a/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
similarity index 97%
rename from include/ui/GraphicBuffer.h
rename to libs/ui/include/ui/GraphicBuffer.h
index 4b82cff..95c2d22 100644
--- a/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -28,9 +28,9 @@
 #include <utils/Flattenable.h>
 #include <utils/RefBase.h>
 
-#include <hardware/gralloc.h>
+#include <nativebase/nativebase.h>
 
-struct ANativeWindowBuffer;
+#include <hardware/gralloc.h>
 
 namespace android {
 
@@ -41,7 +41,7 @@
 // ===========================================================================
 
 class GraphicBuffer
-    : public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
+    : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
       public Flattenable<GraphicBuffer>
 {
     friend class Flattenable<GraphicBuffer>;
@@ -141,7 +141,7 @@
     uint32_t getWidth() const           { return static_cast<uint32_t>(width); }
     uint32_t getHeight() const          { return static_cast<uint32_t>(height); }
     uint32_t getStride() const          { return static_cast<uint32_t>(stride); }
-    uint32_t getUsage() const           { return static_cast<uint32_t>(usage); }
+    uint64_t getUsage() const           { return usage; }
     PixelFormat getPixelFormat() const  { return format; }
     uint32_t getLayerCount() const      { return static_cast<uint32_t>(layerCount); }
     Rect getBounds() const              { return Rect(width, height); }
diff --git a/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
similarity index 98%
rename from include/ui/GraphicBufferAllocator.h
rename to libs/ui/include/ui/GraphicBufferAllocator.h
index fe99de1..14a865e 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -25,8 +25,6 @@
 
 #include <cutils/native_handle.h>
 
-#include <system/window.h>
-
 #include <ui/PixelFormat.h>
 
 #include <utils/Errors.h>
diff --git a/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
similarity index 98%
rename from include/ui/GraphicBufferMapper.h
rename to libs/ui/include/ui/GraphicBufferMapper.h
index e0702e9..06961b1 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -43,6 +43,7 @@
 class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
 {
 public:
+    static void preloadHal();
     static inline GraphicBufferMapper& get() { return getInstance(); }
 
     // The imported outHandle must be freed with freeBuffer when no longer
diff --git a/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
similarity index 100%
rename from include/ui/HdrCapabilities.h
rename to libs/ui/include/ui/HdrCapabilities.h
diff --git a/include/ui/PixelFormat.h b/libs/ui/include/ui/PixelFormat.h
similarity index 100%
rename from include/ui/PixelFormat.h
rename to libs/ui/include/ui/PixelFormat.h
diff --git a/include/ui/Point.h b/libs/ui/include/ui/Point.h
similarity index 100%
rename from include/ui/Point.h
rename to libs/ui/include/ui/Point.h
diff --git a/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
similarity index 100%
rename from include/ui/Rect.h
rename to libs/ui/include/ui/Rect.h
diff --git a/include/ui/Region.h b/libs/ui/include/ui/Region.h
similarity index 100%
rename from include/ui/Region.h
rename to libs/ui/include/ui/Region.h
diff --git a/include/ui/UiConfig.h b/libs/ui/include/ui/UiConfig.h
similarity index 100%
rename from include/ui/UiConfig.h
rename to libs/ui/include/ui/UiConfig.h
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
index 69cb648..f2e5034 100644
--- a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -174,8 +174,6 @@
   //
   // There must be at least |MemorySize(record_count)| bytes of space already
   // allocated at |mmap|. The ring does not take ownership.
-  //
-  // Use this function for dynamically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size,
                               uint32_t record_count) {
     BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@
   //
   // There must be at least |MemorySize()| bytes of space already allocated at
   // |mmap|. The ring does not take ownership.
-  //
-  // Use this function for statically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size) {
-    static_assert(Traits::kUseStaticRecordCount,
-                  "Wrong Create() function called for dynamic record count");
-    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+    return Create(mmap, mmap_size,
+                  Traits::kUseStaticRecordCount
+                      ? Traits::kStaticRecordCount
+                      : BroadcastRing::GetRecordCount(mmap_size));
   }
 
   // Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@
     return MemorySize(Traits::kStaticRecordCount);
   }
 
+  static uint32_t NextPowerOf2(uint32_t n) {
+    if (n == 0)
+      return 0;
+    n -= 1;
+    n |= n >> 16;
+    n |= n >> 8;
+    n |= n >> 4;
+    n |= n >> 2;
+    n |= n >> 1;
+    return n + 1;
+  }
+
+  // Gets the biggest power of 2 record count that can fit into this mmap.
+  //
+  // The header size has been taken into account.
+  static uint32_t GetRecordCount(size_t mmap_size) {
+    if (mmap_size <= sizeof(Header)) {
+      return 0;
+    }
+    uint32_t count =
+        static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record));
+    return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2);
+  }
+
   // Writes a record to the ring.
   //
   // The oldest record is overwritten unless the ring is not already full.
@@ -348,6 +369,9 @@
     return Get(sequence, record);
   }
 
+  // Returns true if this instance has been created or imported.
+  bool is_valid() const { return !!data_.mmap; }
+
   uint32_t record_count() const { return record_count_internal(); }
   uint32_t record_size() const { return record_size_internal(); }
   static constexpr uint32_t mmap_alignment() { return alignof(Mmap); }
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 452bad0..f327200 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -34,18 +34,29 @@
     "liblog",
     "libui",
     "libutils",
+    "libnativewindow"
+]
+
+headerLibraries = [
+    "libdvr_headers",
+    "libnativebase_headers",
 ]
 
 cc_library {
     srcs: sourceFiles,
     cflags: [
         "-DLOG_TAG=\"libbufferhub\"",
-        "-DTRACE=0"
+        "-DTRACE=0",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
     export_include_dirs: localIncludeFiles,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: headerLibraries,
     name: "libbufferhub",
+    export_header_lib_headers: [
+        "libnativebase_headers",
+    ],
 }
 
 cc_test {
@@ -53,6 +64,7 @@
     srcs: ["bufferhub_tests.cpp"],
     static_libs: ["libbufferhub"] + staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: headerLibraries,
     name: "bufferhub_tests",
 }
 
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index b9a53b0..97341b1 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -2,7 +2,7 @@
 
 #include <log/log.h>
 #include <poll.h>
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <sys/epoll.h>
 #include <utils/Trace.h>
 
 #include <mutex>
@@ -12,9 +12,8 @@
 
 #include "include/private/dvr/bufferhub_rpc.h"
 
-using android::pdx::LocalHandle;
 using android::pdx::LocalChannelHandle;
-using android::pdx::rpc::WrapBuffer;
+using android::pdx::LocalHandle;
 using android::pdx::Status;
 
 namespace android {
@@ -29,7 +28,11 @@
           endpoint_path)},
       id_(-1) {}
 
-BufferHubBuffer::~BufferHubBuffer() {}
+BufferHubBuffer::~BufferHubBuffer() {
+  if (metadata_header_ != nullptr) {
+    metadata_buffer_.Unlock();
+  }
+}
 
 Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
   Status<LocalChannelHandle> status =
@@ -43,7 +46,7 @@
 int BufferHubBuffer::ImportBuffer() {
   ATRACE_NAME("BufferHubBuffer::ImportBuffer");
 
-  Status<NativeBufferHandle<LocalHandle>> status =
+  Status<BufferDescription<LocalHandle>> status =
       InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
   if (!status) {
     ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
@@ -54,24 +57,135 @@
     return -EIO;
   }
 
-  auto buffer_handle = status.take();
+  auto buffer_desc = status.take();
 
   // Stash the buffer id to replace the value in id_.
-  const int new_id = buffer_handle.id();
+  const int new_id = buffer_desc.id();
 
   // Import the buffer.
   IonBuffer ion_buffer;
-  ALOGD_IF(
-      TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu",
-      buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount());
+  ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id());
 
-  const int ret = buffer_handle.Import(&ion_buffer);
-  if (ret < 0)
+  if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
     return ret;
 
-  // If the import succeeds, replace the previous buffer and id.
+  // Import the metadata.
+  IonBuffer metadata_buffer;
+  if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
+    ALOGE("Failed to import metadata buffer, error=%d", ret);
+    return ret;
+  }
+  size_t metadata_buf_size = metadata_buffer.width();
+  if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
+    ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu",
+          metadata_buf_size);
+    return -ENOMEM;
+  }
+
+  // If all imports succee, replace the previous buffer and id.
   buffer_ = std::move(ion_buffer);
+  metadata_buffer_ = std::move(metadata_buffer);
+  metadata_buf_size_ = metadata_buf_size;
+  user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
+
+  void* metadata_ptr = nullptr;
+  if (const int ret =
+          metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+                                /*y=*/0, metadata_buf_size_,
+                                /*height=*/1, &metadata_ptr)) {
+    ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata.");
+    return ret;
+  }
+
+  // Set up shared fences.
+  shared_acquire_fence_ = buffer_desc.take_acquire_fence();
+  shared_release_fence_ = buffer_desc.take_release_fence();
+  if (!shared_acquire_fence_ || !shared_release_fence_) {
+    ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences.");
+    return -EIO;
+  }
+
+  metadata_header_ =
+      reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+  if (user_metadata_size_) {
+    user_metadata_ptr_ =
+        reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
+                                BufferHubDefs::kMetadataHeaderSize);
+  } else {
+    user_metadata_ptr_ = nullptr;
+  }
+
   id_ = new_id;
+  buffer_state_bit_ = buffer_desc.buffer_state_bit();
+
+  // Note that here the buffer state is mapped from shared memory as an atomic
+  // object. The std::atomic's constructor will not be called so that the
+  // original value stored in the memory region will be preserved.
+  buffer_state_ = &metadata_header_->buffer_state;
+  ALOGD_IF(TRACE,
+           "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
+           id(), buffer_state_->load());
+  fence_state_ = &metadata_header_->fence_state;
+  ALOGD_IF(TRACE,
+           "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".",
+           id(), fence_state_->load());
+
+  return 0;
+}
+
+inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const {
+  if (user_metadata_size && !user_metadata_ptr_) {
+    ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata.");
+    return -EINVAL;
+  }
+  if (user_metadata_size > user_metadata_size_) {
+    ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.",
+          user_metadata_size, user_metadata_size_);
+    return -E2BIG;
+  }
+  return 0;
+}
+
+int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence,
+                                       const LocalHandle& shared_fence) {
+  if (pending_fence_fd_.Get() != new_fence.Get()) {
+    // First, replace the old fd if there was already one. Skipping if the new
+    // one is the same as the old.
+    if (pending_fence_fd_.IsValid()) {
+      const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
+                                pending_fence_fd_.Get(), nullptr);
+      ALOGW_IF(ret,
+               "BufferHubBuffer::UpdateSharedFence: failed to remove old fence "
+               "fd from epoll set, error: %s.",
+               strerror(errno));
+    }
+
+    if (new_fence.IsValid()) {
+      // If ready fence is valid, we put that into the epoll set.
+      epoll_event event;
+      event.events = EPOLLIN;
+      event.data.u64 = buffer_state_bit();
+      pending_fence_fd_ = new_fence.Duplicate();
+      if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
+                    &event) < 0) {
+        const int error = errno;
+        ALOGE(
+            "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd "
+            "into epoll set, error: %s.",
+            strerror(error));
+        return -error;
+      }
+      // Set bit in fence state to indicate that there is a fence from this
+      // producer or consumer.
+      fence_state_->fetch_or(buffer_state_bit());
+    } else {
+      // Unset bit in fence state to indicate that there is no fence, so that
+      // when consumer to acquire or producer to acquire, it knows no need to
+      // check fence for this buffer.
+      fence_state_->fetch_and(~buffer_state_bit());
+    }
+  }
+
   return 0;
 }
 
@@ -131,31 +245,144 @@
                        : LocalChannelHandle{nullptr, -status.error()});
 }
 
+int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
+                                 LocalHandle* out_fence) {
+  if (!out_meta)
+    return -EINVAL;
+
+  // Only check producer bit and this consumer buffer's particular consumer bit.
+  // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
+  // is not set.
+  uint64_t buffer_state = buffer_state_->load();
+  if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
+    ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64
+          " buffer_state_bit=%" PRIx64 ".",
+          id(), buffer_state, buffer_state_bit());
+    return -EBUSY;
+  }
+
+  // Copy the canonical metadata.
+  void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+  memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
+  // Fill in the user_metadata_ptr in address space of the local process.
+  if (out_meta->user_metadata_size) {
+    out_meta->user_metadata_ptr =
+        reinterpret_cast<uint64_t>(user_metadata_ptr_);
+  } else {
+    out_meta->user_metadata_ptr = 0;
+  }
+
+  uint64_t fence_state = fence_state_->load();
+  // If there is an acquire fence from producer, we need to return it.
+  if (fence_state & BufferHubDefs::kProducerStateBit) {
+    *out_fence = shared_acquire_fence_.Duplicate();
+  }
+
+  // Set the consumer bit unique to this consumer.
+  BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
+  return 0;
+}
+
 int BufferConsumer::Acquire(LocalHandle* ready_fence) {
   return Acquire(ready_fence, nullptr, 0);
 }
 
 int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
-                            size_t meta_size_bytes) {
+                            size_t user_metadata_size) {
   ATRACE_NAME("BufferConsumer::Acquire");
-  LocalFence fence;
-  auto return_value =
-      std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes));
-  auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>(
-      &return_value, meta_size_bytes);
-  if (status && ready_fence)
-    *ready_fence = fence.take();
-  return status ? 0 : -status.error();
+
+  if (const int error = CheckMetadata(user_metadata_size))
+    return error;
+
+  DvrNativeBufferMetadata canonical_meta;
+  if (const int error = LocalAcquire(&canonical_meta, ready_fence))
+    return error;
+
+  if (meta && user_metadata_size) {
+    void* metadata_src =
+        reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
+    if (metadata_src) {
+      memcpy(meta, metadata_src, user_metadata_size);
+    } else {
+      ALOGW("BufferConsumer::Acquire: no user-defined metadata.");
+    }
+  }
+
+  auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
+  if (!status)
+    return -status.error();
+  return 0;
+}
+
+int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
+                                 LocalHandle* out_fence) {
+  ATRACE_NAME("BufferConsumer::AcquireAsync");
+
+  if (const int error = LocalAcquire(out_meta, out_fence))
+    return error;
+
+  auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
+  if (!status)
+    return -status.error();
+  return 0;
+}
+
+int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta,
+                                 const LocalHandle& release_fence) {
+  if (const int error = CheckMetadata(meta->user_metadata_size))
+    return error;
+
+  // Check invalid state transition.
+  uint64_t buffer_state = buffer_state_->load();
+  if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
+    ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
+          id(), buffer_state);
+    return -EBUSY;
+  }
+
+  // On release, only the user requested metadata is copied back into the shared
+  // memory for metadata. Since there are multiple consumers, it doesn't make
+  // sense to send the canonical metadata back to the producer. However, one of
+  // the consumer can still choose to write up to user_metadata_size bytes of
+  // data into user_metadata_ptr.
+  if (meta->user_metadata_ptr && meta->user_metadata_size) {
+    void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+    memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+  }
+
+  // Send out the release fence through the shared epoll fd. Note that during
+  // releasing the producer is not expected to be polling on the fence.
+  if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
+    return error;
+
+  // For release operation, the client don't need to change the state as it's
+  // bufferhubd's job to flip the produer bit once all consumers are released.
+  return 0;
 }
 
 int BufferConsumer::Release(const LocalHandle& release_fence) {
   ATRACE_NAME("BufferConsumer::Release");
+
+  DvrNativeBufferMetadata meta;
+  if (const int error = LocalRelease(&meta, release_fence))
+    return error;
+
   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
       BorrowedFence(release_fence.Borrow())));
 }
 
 int BufferConsumer::ReleaseAsync() {
+  DvrNativeBufferMetadata meta;
+  return ReleaseAsync(&meta, LocalHandle());
+}
+
+int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
+                                 const LocalHandle& release_fence) {
   ATRACE_NAME("BufferConsumer::ReleaseAsync");
+
+  if (const int error = LocalRelease(meta, release_fence))
+    return error;
+
   return ReturnStatusOrError(
       SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
 }
@@ -168,24 +395,25 @@
 }
 
 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
-                               uint32_t usage, size_t metadata_size)
-    : BufferProducer(width, height, format, usage, usage, metadata_size) {}
+                               uint32_t usage, size_t user_metadata_size)
+    : BufferProducer(width, height, format, usage, usage, user_metadata_size) {}
 
 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
                                uint64_t producer_usage, uint64_t consumer_usage,
-                               size_t metadata_size)
+                               size_t user_metadata_size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
            "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
-           " metadata_size=%zu",
+           " user_metadata_size=%zu",
            event_fd(), width, height, format, producer_usage, consumer_usage,
-           metadata_size);
+           user_metadata_size);
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, (producer_usage | consumer_usage), metadata_size);
+      width, height, format, (producer_usage | consumer_usage),
+      user_metadata_size);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -206,27 +434,28 @@
 BufferProducer::BufferProducer(const std::string& name, int user_id,
                                int group_id, uint32_t width, uint32_t height,
                                uint32_t format, uint32_t usage,
-                               size_t meta_size_bytes)
+                               size_t user_metadata_size)
     : BufferProducer(name, user_id, group_id, width, height, format, usage,
-                     usage, meta_size_bytes) {}
+                     usage, user_metadata_size) {}
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
                                int group_id, uint32_t width, uint32_t height,
                                uint32_t format, uint64_t producer_usage,
-                               uint64_t consumer_usage, size_t meta_size_bytes)
+                               uint64_t consumer_usage,
+                               size_t user_metadata_size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
            "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
-           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu",
+           " consumer_usage=%" PRIx64 " user_metadata_size=%zu",
            event_fd(), name.c_str(), user_id, group_id, width, height, format,
-           producer_usage, consumer_usage, meta_size_bytes);
+           producer_usage, consumer_usage, user_metadata_size);
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
       name, user_id, group_id, width, height, format,
-      (producer_usage | consumer_usage), meta_size_bytes);
+      (producer_usage | consumer_usage), user_metadata_size);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,12 +489,12 @@
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
-  const size_t meta_size_bytes = 0;
+  const size_t user_metadata_size = 0;
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
       width, height, format, (producer_usage | consumer_usage),
-      meta_size_bytes);
+      user_metadata_size);
   if (!status) {
     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
           status.GetErrorMessage().c_str());
@@ -299,12 +528,12 @@
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
-  const size_t meta_size_bytes = 0;
+  const size_t user_metadata_size = 0;
 
   // (b/37881101) Deprecate producer/consumer usage
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
       name, user_id, group_id, width, height, format,
-      (producer_usage | consumer_usage), meta_size_bytes);
+      (producer_usage | consumer_usage), user_metadata_size);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create persistent "
@@ -360,28 +589,141 @@
   }
 }
 
+int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta,
+                              const LocalHandle& ready_fence) {
+  if (const int error = CheckMetadata(meta->user_metadata_size))
+    return error;
+
+  // Check invalid state transition.
+  uint64_t buffer_state = buffer_state_->load();
+  if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+    ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
+          id(), buffer_state);
+    return -EBUSY;
+  }
+
+  // Copy the canonical metadata.
+  void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+  memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
+  // Copy extra user requested metadata.
+  if (meta->user_metadata_ptr && meta->user_metadata_size) {
+    void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+    memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+  }
+
+  // Send out the acquire fence through the shared epoll fd. Note that during
+  // posting no consumer is not expected to be polling on the fence.
+  if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
+    return error;
+
+  // Set the producer bit atomically to transit into posted state.
+  BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
+                                   BufferHubDefs::kProducerStateBit);
+  return 0;
+}
+
 int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
-                         size_t meta_size_bytes) {
+                         size_t user_metadata_size) {
   ATRACE_NAME("BufferProducer::Post");
+
+  // Populate cononical metadata for posting.
+  DvrNativeBufferMetadata canonical_meta;
+  canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
+  canonical_meta.user_metadata_size = user_metadata_size;
+
+  if (const int error = LocalPost(&canonical_meta, ready_fence))
+    return error;
+
   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
-      BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes)));
+      BorrowedFence(ready_fence.Borrow())));
+}
+
+int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta,
+                              const LocalHandle& ready_fence) {
+  ATRACE_NAME("BufferProducer::PostAsync");
+
+  if (const int error = LocalPost(meta, ready_fence))
+    return error;
+
+  return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
+}
+
+int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta,
+                              LocalHandle* out_fence) {
+  uint64_t buffer_state = buffer_state_->load();
+  ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".",
+           id(), buffer_state);
+
+  if (!out_meta)
+    return -EINVAL;
+
+  if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
+    if (BufferHubDefs::IsBufferGained(buffer_state)) {
+      // We don't want to log error when gaining a newly allocated
+      // buffer.
+      ALOGI("BufferProducer::LocalGain: already gained id=%d.", id());
+      return -EALREADY;
+    }
+    ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".",
+          id(), buffer_state);
+    return -EBUSY;
+  }
+
+  // Canonical metadata is undefined on Gain. Except for user_metadata and
+  // release_fence_mask. Fill in the user_metadata_ptr in address space of the
+  // local process.
+  if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
+    out_meta->user_metadata_size =
+        metadata_header_->metadata.user_metadata_size;
+    out_meta->user_metadata_ptr =
+        reinterpret_cast<uint64_t>(user_metadata_ptr_);
+  } else {
+    out_meta->user_metadata_size = 0;
+    out_meta->user_metadata_ptr = 0;
+  }
+
+  uint64_t fence_state = fence_state_->load();
+  // If there is an release fence from consumer, we need to return it.
+  if (fence_state & BufferHubDefs::kConsumerStateMask) {
+    *out_fence = shared_release_fence_.Duplicate();
+    out_meta->release_fence_mask =
+        fence_state & BufferHubDefs::kConsumerStateMask;
+  }
+
+  // Clear out all bits and the buffer is now back to gained state.
+  buffer_state_->store(0ULL);
+  return 0;
 }
 
 int BufferProducer::Gain(LocalHandle* release_fence) {
   ATRACE_NAME("BufferProducer::Gain");
+
+  DvrNativeBufferMetadata meta;
+  if (const int error = LocalGain(&meta, release_fence))
+    return error;
+
   auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
   if (!status)
     return -status.error();
-  if (release_fence)
-    *release_fence = status.take().take();
   return 0;
 }
 
-int BufferProducer::GainAsync() {
+int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta,
+                              LocalHandle* release_fence) {
   ATRACE_NAME("BufferProducer::GainAsync");
+
+  if (const int error = LocalGain(out_meta, release_fence))
+    return error;
+
   return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
 }
 
+int BufferProducer::GainAsync() {
+  DvrNativeBufferMetadata meta;
+  LocalHandle fence;
+  return GainAsync(&meta, &fence);
+}
+
 std::unique_ptr<BufferProducer> BufferProducer::Import(
     LocalChannelHandle channel) {
   ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
diff --git a/libs/vr/libbufferhub/bufferhub_tests.cpp b/libs/vr/libbufferhub/bufferhub_tests.cpp
index fa61c4a..c4b9a8c 100644
--- a/libs/vr/libbufferhub/bufferhub_tests.cpp
+++ b/libs/vr/libbufferhub/bufferhub_tests.cpp
@@ -1,5 +1,9 @@
 #include <gtest/gtest.h>
+#include <poll.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
 
 #include <mutex>
 #include <thread>
@@ -13,8 +17,10 @@
     return result;                            \
   })()
 
-using android::dvr::BufferProducer;
 using android::dvr::BufferConsumer;
+using android::dvr::BufferHubDefs::kConsumerStateMask;
+using android::dvr::BufferHubDefs::kProducerStateBit;
+using android::dvr::BufferProducer;
 using android::pdx::LocalHandle;
 
 const int kWidth = 640;
@@ -37,29 +43,201 @@
       BufferConsumer::Import(c->CreateConsumer());
   ASSERT_TRUE(c2.get() != nullptr);
 
+  // Producer state mask is unique, i.e. 1.
+  EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
+  // Consumer state mask cannot have producer bit on.
+  EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
+  // Consumer state mask must be a single, i.e. power of 2.
+  EXPECT_NE(c->buffer_state_bit(), 0);
+  EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
+  // Consumer state mask cannot have producer bit on.
+  EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
+  // Consumer state mask must be a single, i.e. power of 2.
+  EXPECT_NE(c2->buffer_state_bit(), 0);
+  EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
+  // Each consumer should have unique bit.
+  EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
+
+  // Initial state: producer not available, consumers not available.
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+
   EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
-  // Both consumers should be triggered.
-  EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
-  EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
+
+  // New state: producer not available, consumers available.
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+  EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
+  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
 
   uint64_t context;
   LocalHandle fence;
-  EXPECT_LE(0, c->Acquire(&fence, &context));
+  EXPECT_EQ(0, c->Acquire(&fence, &context));
   EXPECT_EQ(kContext, context);
-  EXPECT_GE(0, RETRY_EINTR(c->Poll(0)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
 
-  EXPECT_LE(0, c2->Acquire(&fence, &context));
+  EXPECT_EQ(0, c2->Acquire(&fence, &context));
   EXPECT_EQ(kContext, context);
-  EXPECT_GE(0, RETRY_EINTR(c2->Poll(0)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
 
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
   EXPECT_EQ(0, c2->Discard());
 
-  EXPECT_LE(0, RETRY_EINTR(p->Poll(0)));
+  EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
   EXPECT_EQ(0, p->Gain(&fence));
-  EXPECT_GE(0, RETRY_EINTR(p->Poll(0)));
+  EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+}
+
+TEST_F(LibBufferHubTest, TestEpoll) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+
+  LocalHandle epoll_fd{epoll_create1(EPOLL_CLOEXEC)};
+  ASSERT_TRUE(epoll_fd.IsValid());
+
+  epoll_event event;
+  std::array<epoll_event, 64> events;
+
+  auto event_sources = p->GetEventSources();
+  ASSERT_LT(event_sources.size(), events.size());
+
+  for (const auto& event_source : event_sources) {
+    event = {.events = event_source.event_mask | EPOLLET,
+             .data = {.fd = p->event_fd()}};
+    ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
+                           &event));
+  }
+
+  event_sources = c->GetEventSources();
+  ASSERT_LT(event_sources.size(), events.size());
+
+  for (const auto& event_source : event_sources) {
+    event = {.events = event_source.event_mask | EPOLLET,
+             .data = {.fd = c->event_fd()}};
+    ASSERT_EQ(0, epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_source.event_fd,
+                           &event));
+  }
+
+  // No events should be signaled initially.
+  ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
+
+  // Post the producer and check for consumer signal.
+  EXPECT_EQ(0, p->Post({}, kContext));
+  ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  ASSERT_TRUE(events[0].events & EPOLLIN);
+  ASSERT_EQ(c->event_fd(), events[0].data.fd);
+
+  // Save the event bits to translate later.
+  event = events[0];
+
+  // Check for events again. Edge-triggered mode should prevent any.
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+
+  // Translate the events.
+  auto event_status = c->GetEventMask(event.events);
+  ASSERT_TRUE(event_status);
+  ASSERT_TRUE(event_status.get() & EPOLLIN);
+
+  // Check for events again. Edge-triggered mode should prevent any.
+  EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+}
+
+TEST_F(LibBufferHubTest, TestStateMask) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+
+  // It's ok to create up to 63 consumer buffers.
+  uint64_t buffer_state_bits = p->buffer_state_bit();
+  std::array<std::unique_ptr<BufferConsumer>, 63> cs;
+  for (size_t i = 0; i < 63; i++) {
+    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    ASSERT_TRUE(cs[i].get() != nullptr);
+    // Expect all buffers have unique state mask.
+    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+    buffer_state_bits |= cs[i]->buffer_state_bit();
+  }
+  EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
+
+  // The 64th creation will fail with out-of-memory error.
+  auto state = p->CreateConsumer();
+  EXPECT_EQ(state.error(), E2BIG);
+
+  // Release any consumer should allow us to re-create.
+  for (size_t i = 0; i < 63; i++) {
+    buffer_state_bits &= ~cs[i]->buffer_state_bit();
+    cs[i] = nullptr;
+    cs[i] = BufferConsumer::Import(p->CreateConsumer());
+    ASSERT_TRUE(cs[i].get() != nullptr);
+    // The released state mask will be reused.
+    EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+    buffer_state_bits |= cs[i]->buffer_state_bit();
+    EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
+  }
+}
+
+TEST_F(LibBufferHubTest, TestStateTransitions) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+
+  uint64_t context;
+  LocalHandle fence;
+
+  // The producer buffer starts in gained state.
+
+  // Acquire, release, and gain in gained state should fail.
+  EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
+  EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
+  EXPECT_EQ(-EALREADY, p->Gain(&fence));
+
+  // Post in gained state should succeed.
+  EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
+
+  // Post, release, and gain in posted state should fail.
+  EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+  EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
+  EXPECT_EQ(-EBUSY, p->Gain(&fence));
+
+  // Acquire in posted state should succeed.
+  EXPECT_LE(0, c->Acquire(&fence, &context));
+
+  // Acquire, post, and gain in acquired state should fail.
+  EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
+  EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+  EXPECT_EQ(-EBUSY, p->Gain(&fence));
+
+  // Release in acquired state should succeed.
+  EXPECT_EQ(0, c->Release(LocalHandle()));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+
+  // Release, acquire, and post in released state should fail.
+  EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
+  EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
+  EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+
+  // Gain in released state should succeed.
+  EXPECT_EQ(0, p->Gain(&fence));
+
+  // Acquire, release, and gain in gained state should fail.
+  EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
+  EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
+  EXPECT_EQ(-EALREADY, p->Gain(&fence));
 }
 
 TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
@@ -93,6 +271,11 @@
     int64_t field1;
     int64_t field2;
   };
+  struct OverSizedMetadata {
+    int64_t field1;
+    int64_t field2;
+    int64_t field3;
+  };
   std::unique_ptr<BufferProducer> p = BufferProducer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
   ASSERT_TRUE(p.get() != nullptr);
@@ -100,9 +283,16 @@
       BufferConsumer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
 
-  int64_t sequence = 3;
-  EXPECT_NE(0, p->Post(LocalHandle(), sequence));
+  // It is illegal to post metadata larger than originally requested during
+  // buffer allocation.
+  OverSizedMetadata evil_meta = {};
+  EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
   EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
+
+  // It is ok to post metadata smaller than originally requested during
+  // buffer allocation.
+  int64_t sequence = 42;
+  EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
 }
 
 TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
@@ -110,6 +300,11 @@
     int64_t field1;
     int64_t field2;
   };
+  struct OverSizedMetadata {
+    int64_t field1;
+    int64_t field2;
+    int64_t field3;
+  };
   std::unique_ptr<BufferProducer> p = BufferProducer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(Metadata));
   ASSERT_TRUE(p.get() != nullptr);
@@ -122,7 +317,16 @@
 
   LocalHandle fence;
   int64_t sequence;
-  EXPECT_NE(0, c->Acquire(&fence, &sequence));
+  OverSizedMetadata e;
+
+  // It is illegal to acquire metadata larger than originally requested during
+  // buffer allocation.
+  EXPECT_NE(0, c->Acquire(&fence, &e));
+
+  // It is ok to acquire metadata smaller than originally requested during
+  // buffer allocation.
+  EXPECT_EQ(0, c->Acquire(&fence, &sequence));
+  EXPECT_EQ(m.field1, sequence);
 }
 
 TEST_F(LibBufferHubTest, TestAcquireWithNoMeta) {
@@ -215,12 +419,140 @@
   LocalHandle fence;
   auto c = BufferConsumer::Import(p->CreateConsumer());
   ASSERT_NE(nullptr, c);
-  EXPECT_NE(-EPIPE, c->Acquire(&fence));
+  EXPECT_EQ(0, p->Post<void>(LocalHandle()));
+  EXPECT_EQ(0, c->Acquire(&fence));
+  EXPECT_EQ(0, c->Release(LocalHandle()));
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
 
   // Test that removing persistence and closing the producer orphans the
   // consumer.
+  EXPECT_EQ(0, p->Gain(&fence));
+  EXPECT_EQ(0, p->Post<void>(LocalHandle()));
   EXPECT_EQ(0, p->RemovePersistence());
   p = nullptr;
 
+  // Orphaned consumer can acquire the posted buffer one more time in
+  // asynchronous manner. But synchronous call will fail.
+  DvrNativeBufferMetadata meta;
+  EXPECT_EQ(0, c->AcquireAsync(&meta, &fence));
   EXPECT_EQ(-EPIPE, c->Release(LocalHandle()));
 }
+
+namespace {
+
+int PollFd(int fd, int timeout_ms) {
+  pollfd p = {fd, POLLIN, 0};
+  return poll(&p, 1, timeout_ms);
+}
+
+}  // namespace
+
+TEST_F(LibBufferHubTest, TestAcquireFence) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, /*metadata_size=*/0);
+  ASSERT_TRUE(p.get() != nullptr);
+  std::unique_ptr<BufferConsumer> c =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c.get() != nullptr);
+
+  DvrNativeBufferMetadata meta;
+  LocalHandle f1(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+
+  // Post with unsignaled fence.
+  EXPECT_EQ(0, p->PostAsync(&meta, f1));
+
+  // Should acquire a valid fence.
+  LocalHandle f2;
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
+  EXPECT_TRUE(f2.IsValid());
+  // The original fence and acquired fence should have different fd number.
+  EXPECT_NE(f1.Get(), f2.Get());
+  EXPECT_GE(0, PollFd(f2.Get(), 0));
+
+  // Signal the original fence will trigger the new fence.
+  eventfd_write(f1.Get(), 1);
+  // Now the original FD has been signaled.
+  EXPECT_LT(0, PollFd(f2.Get(), 10));
+
+  // Release the consumer with an invalid fence.
+  EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
+
+  // Should gain an invalid fence.
+  LocalHandle f3;
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_EQ(0, p->GainAsync(&meta, &f3));
+  EXPECT_FALSE(f3.IsValid());
+
+  // Post with a signaled fence.
+  EXPECT_EQ(0, p->PostAsync(&meta, f1));
+
+  // Should acquire a valid fence and it's already signalled.
+  LocalHandle f4;
+  EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+  EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
+  EXPECT_TRUE(f4.IsValid());
+  EXPECT_LT(0, PollFd(f4.Get(), 10));
+
+  // Release with an unsignalled fence and signal it immediately after release
+  // without producer gainning.
+  LocalHandle f5(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  EXPECT_EQ(0, c->ReleaseAsync(&meta, f5));
+  eventfd_write(f5.Get(), 1);
+
+  // Should gain a valid fence, which is already signaled.
+  LocalHandle f6;
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+  EXPECT_EQ(0, p->GainAsync(&meta, &f6));
+  EXPECT_TRUE(f6.IsValid());
+  EXPECT_LT(0, PollFd(f6.Get(), 10));
+}
+
+TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
+  std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+  std::unique_ptr<BufferConsumer> c1 =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c1.get() != nullptr);
+  const uint64_t consumer_state_bit1 = c1->buffer_state_bit();
+
+  DvrNativeBufferMetadata meta;
+  EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
+
+  LocalHandle fence;
+  EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
+  EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
+  // Destroy the consumer now will make it orphaned and the buffer is still
+  // acquired.
+  c1 = nullptr;
+  EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
+
+  std::unique_ptr<BufferConsumer> c2 =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c2.get() != nullptr);
+  const uint64_t consumer_state_bit2 = c2->buffer_state_bit();
+  EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
+
+  // The new consumer is available for acquire.
+  EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
+  EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
+  // Releasing the consumer makes the buffer gainable.
+  EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
+
+  // The buffer is now available for the producer to gain.
+  EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+
+  // But if another consumer is created in released state.
+  std::unique_ptr<BufferConsumer> c3 =
+      BufferConsumer::Import(p->CreateConsumer());
+  ASSERT_TRUE(c3.get() != nullptr);
+  const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
+  EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
+  // The consumer buffer is not acquirable.
+  EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
+  EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
+
+  // Producer should be able to gain no matter what.
+  EXPECT_EQ(0, p->GainAsync(&meta, &fence));
+}
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index be20e72..1186f93 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -11,6 +11,8 @@
 
 #include <private/dvr/ion_buffer.h>
 
+#include "bufferhub_rpc.h"
+
 namespace android {
 namespace dvr {
 
@@ -75,6 +77,14 @@
     }
   }
 
+  std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
+    if (auto* client_channel = GetChannel()) {
+      return client_channel->GetEventSources();
+    } else {
+      return {};
+    }
+  }
+
   native_handle_t* native_handle() const {
     return const_cast<native_handle_t*>(buffer_.handle());
   }
@@ -84,6 +94,10 @@
 
   int id() const { return id_; }
 
+  // A state mask which is unique to a buffer hub client among all its siblings
+  // sharing the same concrete graphic buffer.
+  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
@@ -98,6 +112,9 @@
   uint64_t producer_usage() const { return buffer_.usage(); }
   uint64_t consumer_usage() const { return buffer_.usage(); }
 
+  uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
+  void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
+
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
   explicit BufferHubBuffer(const std::string& endpoint_path);
@@ -106,6 +123,31 @@
   // Initialization helper.
   int ImportBuffer();
 
+  // Check invalid metadata operation. Returns 0 if requested metadata is valid.
+  int CheckMetadata(size_t user_metadata_size) const;
+
+  // Send out the new fence by updating the shared fence (shared_release_fence
+  // for producer and shared_acquire_fence for consumer). Note that during this
+  // should only be used in LocalPost() or LocalRelease, and the shared fence
+  // shouldn't be poll'ed by the other end.
+  int UpdateSharedFence(const LocalHandle& new_fence,
+                        const LocalHandle& shared_fence);
+
+  // IonBuffer that is shared between bufferhubd, producer, and consumers.
+  size_t metadata_buf_size_{0};
+  size_t user_metadata_size_{0};
+  BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
+  void* user_metadata_ptr_{nullptr};
+  std::atomic<uint64_t>* buffer_state_{nullptr};
+  std::atomic<uint64_t>* fence_state_{nullptr};
+
+  LocalHandle shared_acquire_fence_;
+  LocalHandle shared_release_fence_;
+
+  // A local fence fd that holds the ownership of the fence fd on Post (for
+  // producer) and Release (for consumer).
+  LocalHandle pending_fence_fd_;
+
  private:
   BufferHubBuffer(const BufferHubBuffer&) = delete;
   void operator=(const BufferHubBuffer&) = delete;
@@ -114,8 +156,9 @@
   // for logging and debugging purposes only and should not be used for lookup
   // or any other functional purpose as a security precaution.
   int id_;
-
+  uint64_t buffer_state_bit_{0ULL};
   IonBuffer buffer_;
+  IonBuffer metadata_buffer_;
 };
 
 // This represents a writable buffer. Calling Post notifies all clients and
@@ -136,12 +179,17 @@
   static std::unique_ptr<BufferProducer> Import(
       Status<LocalChannelHandle> status);
 
+  // Asynchronously posts a buffer. The fence and metadata are passed to
+  // consumer via shared fd and shared memory.
+  int PostAsync(const DvrNativeBufferMetadata* meta,
+                const LocalHandle& ready_fence);
+
   // Post this buffer, passing |ready_fence| to the consumers. The bytes in
   // |meta| are passed unaltered to the consumers. The producer must not modify
   // the buffer until it is re-gained.
   // This returns zero or a negative unix error code.
   int Post(const LocalHandle& ready_fence, const void* meta,
-           size_t meta_size_bytes);
+           size_t user_metadata_size);
 
   template <typename Meta,
             typename = typename std::enable_if<std::is_void<Meta>::value>::type>
@@ -160,16 +208,15 @@
   // is in the released state.
   // This returns zero or a negative unix error code.
   int Gain(LocalHandle* release_fence);
+  int GainAsync();
 
   // Asynchronously marks a released buffer as gained. This method is similar to
   // the synchronous version above, except that it does not wait for BufferHub
-  // to acknowledge success or failure, nor does it transfer a release fence to
-  // the client. This version may be used in situations where a release fence is
-  // not needed. Because of the asynchronous nature of the underlying message,
-  // no error is returned if this method is called when the buffer is in an
-  // incorrect state. Returns zero if sending the message succeeded, or a
-  // negative errno code otherwise.
-  int GainAsync();
+  // to acknowledge success or failure. Because of the asynchronous nature of
+  // the underlying message, no error is returned if this method is called when
+  // the buffer is in an incorrect state. Returns zero if sending the message
+  // succeeded, or a negative errno code if local error check fails.
+  int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
 
   // Attaches the producer to |name| so that it becomes a persistent buffer that
   // may be retrieved by name at a later time. This may be used in cases where a
@@ -216,7 +263,7 @@
   BufferProducer(const std::string& name, int user_id, int group_id,
                  uint32_t width, uint32_t height, uint32_t format,
                  uint64_t producer_usage, uint64_t consumer_usage,
-                 size_t meta_size_bytes);
+                 size_t user_metadata_size);
 
   // Constructs a blob (flat) buffer with the given usage flags.
   BufferProducer(uint32_t usage, size_t size);
@@ -234,6 +281,11 @@
 
   // Imports the given file handle to a producer channel, taking ownership.
   explicit BufferProducer(LocalChannelHandle channel);
+
+  // Local state transition helpers.
+  int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+  int LocalPost(const DvrNativeBufferMetadata* meta,
+                const LocalHandle& ready_fence);
 };
 
 // This is a connection to a producer buffer, which can be located in another
@@ -263,7 +315,7 @@
   // are available. This call will only succeed if the buffer is in the posted
   // state.
   // Returns zero on success, or a negative errno code otherwise.
-  int Acquire(LocalHandle* ready_fence, void* meta, size_t meta_size_bytes);
+  int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
 
   // Attempt to retrieve a post event from buffer hub. If successful,
   // |ready_fence| is set to a fence to wait on until the buffer is ready. This
@@ -274,20 +326,22 @@
     return Acquire(ready_fence, meta, sizeof(*meta));
   }
 
+  // Asynchronously acquires a bufer.
+  int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
   // This should be called after a successful Acquire call. If the fence is
   // valid the fence determines the buffer usage, otherwise the buffer is
   // released immediately.
   // This returns zero or a negative unix error code.
   int Release(const LocalHandle& release_fence);
+  int ReleaseAsync();
 
   // Asynchronously releases a buffer. Similar to the synchronous version above,
-  // except that it does not wait for BufferHub to reply with success or error,
-  // nor does it transfer a release fence. This version may be used in
-  // situations where a release fence is not needed. Because of the asynchronous
-  // nature of the underlying message, no error is returned if this method is
-  // called when the buffer is in an incorrect state. Returns zero if sending
-  // the message succeeded, or a negative errno code otherwise.
-  int ReleaseAsync();
+  // except that it does not wait for BufferHub to reply with success or error.
+  // The fence and metadata are passed to consumer via shared fd and shared
+  // memory.
+  int ReleaseAsync(const DvrNativeBufferMetadata* meta,
+                   const LocalHandle& release_fence);
 
   // May be called after or instead of Acquire to indicate that the consumer
   // does not need to access the buffer this cycle. This returns zero or a
@@ -305,6 +359,11 @@
   friend BASE;
 
   explicit BufferConsumer(LocalChannelHandle channel);
+
+  // Local state transition helpers.
+  int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+  int LocalRelease(const DvrNativeBufferMetadata* meta,
+                   const LocalHandle& release_fence);
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ffdc9e2..f9fd42d 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -5,6 +5,7 @@
 #include <gui/BufferQueueDefs.h>
 #include <sys/types.h>
 
+#include <dvr/dvr_api.h>
 #include <pdx/channel_handle.h>
 #include <pdx/file_handle.h>
 #include <pdx/rpc/remote_method.h>
@@ -14,6 +15,71 @@
 namespace android {
 namespace dvr {
 
+namespace BufferHubDefs {
+
+static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB;
+static constexpr uint32_t kMetadataUsage =
+    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+// Single producuer multiple (up to 63) consumers ownership signal.
+// 64-bit atomic unsigned int.
+//
+// MSB           LSB
+//  |             |
+//  v             v
+// [P|C62|...|C1|C0]
+// Gain'ed state:     [0|..|0|0] -> Exclusively Writable.
+// Post'ed state:     [1|..|0|0]
+// Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits
+// Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits
+static constexpr uint64_t kProducerStateBit = 1ULL << 63;
+static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1;
+
+static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state,
+                                     uint64_t clear_mask, uint64_t set_mask) {
+  uint64_t old_state;
+  uint64_t new_state;
+  do {
+    old_state = buffer_state->load();
+    new_state = (old_state & ~clear_mask) | set_mask;
+  } while (!buffer_state->compare_exchange_weak(old_state, new_state));
+}
+
+static inline bool IsBufferGained(uint64_t state) { return state == 0; }
+
+static inline bool IsBufferPosted(uint64_t state,
+                                  uint64_t consumer_bit = kConsumerStateMask) {
+  return (state & kProducerStateBit) && !(state & consumer_bit);
+}
+
+static inline bool IsBufferAcquired(uint64_t state) {
+  return (state & kProducerStateBit) && (state & kConsumerStateMask);
+}
+
+static inline bool IsBufferReleased(uint64_t state) {
+  return !(state & kProducerStateBit) && (state & kConsumerStateMask);
+}
+
+struct __attribute__((packed, aligned(8))) MetadataHeader {
+  // Internal data format, which can be updated as long as the size, padding and
+  // field alignment of the struct is consistent within the same ABI. As this
+  // part is subject for future updates, it's not stable cross Android version,
+  // so don't have it visible from outside of the Android platform (include Apps
+  // and vendor HAL).
+  std::atomic<uint64_t> buffer_state;
+  std::atomic<uint64_t> fence_state;
+  uint64_t queue_index;
+
+  // Public data format, which should be updated with caution. See more details
+  // in dvr_api.h
+  DvrNativeBufferMetadata metadata;
+};
+
+static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size");
+static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);
+
+}  // namespace BufferHubDefs
+
 template <typename FileHandleType>
 class NativeBufferHandle {
  public:
@@ -93,6 +159,57 @@
   void operator=(const NativeBufferHandle&) = delete;
 };
 
+template <typename FileHandleType>
+class BufferDescription {
+ public:
+  BufferDescription() = default;
+  BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id,
+                    uint64_t buffer_state_bit,
+                    const FileHandleType& acquire_fence_fd,
+                    const FileHandleType& release_fence_fd)
+      : id_(id),
+        buffer_state_bit_(buffer_state_bit),
+        buffer_(buffer, id),
+        metadata_(metadata, id),
+        acquire_fence_fd_(acquire_fence_fd.Borrow()),
+        release_fence_fd_(release_fence_fd.Borrow()) {}
+
+  BufferDescription(BufferDescription&& other) = default;
+  BufferDescription& operator=(BufferDescription&& other) = default;
+
+  // ID of the buffer client. All BufferHubBuffer clients derived from the same
+  // buffer in bufferhubd share the same buffer id.
+  int id() const { return id_; }
+  // State mask of the buffer client. Each BufferHubBuffer client backed by the
+  // same buffer channel has uniqued state bit among its siblings. For a
+  // producer buffer the bit must be kProducerStateBit; for a consumer the bit
+  // must be one of the kConsumerStateMask.
+  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+  FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); }
+  FileHandleType take_release_fence() { return std::move(release_fence_fd_); }
+
+  int ImportBuffer(IonBuffer* buffer) { return buffer_.Import(buffer); }
+  int ImportMetadata(IonBuffer* metadata) { return metadata_.Import(metadata); }
+
+ private:
+  int id_{-1};
+  uint64_t buffer_state_bit_{0};
+  // Two IonBuffers: one for the graphic buffer and one for metadata.
+  NativeBufferHandle<FileHandleType> buffer_;
+  NativeBufferHandle<FileHandleType> metadata_;
+
+  // Pamameters for shared fences.
+  FileHandleType acquire_fence_fd_;
+  FileHandleType release_fence_fd_;
+
+  PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_,
+                           buffer_state_bit_, buffer_, metadata_,
+                           acquire_fence_fd_, release_fence_fd_);
+
+  BufferDescription(const BufferDescription&) = delete;
+  void operator=(const BufferDescription&) = delete;
+};
+
 using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
 using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
 
@@ -129,19 +246,102 @@
 using LocalFence = FenceHandle<pdx::LocalHandle>;
 using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
 
+struct ProducerQueueConfig {
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async;
+
+  // Default buffer width that is set during ProducerQueue's creation.
+  uint32_t default_width;
+
+  // Default buffer height that is set during ProducerQueue's creation.
+  uint32_t default_height;
+
+  // Default buffer format that is set during ProducerQueue's creation.
+  uint32_t default_format;
+
+  // Size of the meta data associated with all the buffers allocated from the
+  // queue.
+  size_t user_metadata_size;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
+                           default_height, default_format, user_metadata_size);
+};
+
+class ProducerQueueConfigBuilder {
+ public:
+  // Build a ProducerQueueConfig object.
+  ProducerQueueConfig Build() {
+    return {is_async_, default_width_, default_height_, default_format_,
+            user_metadata_size_};
+  }
+
+  ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
+    is_async_ = is_async;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
+    default_width_ = width;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
+    default_height_ = height;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
+    default_format_ = format;
+    return *this;
+  }
+
+  template <typename Meta>
+  ProducerQueueConfigBuilder& SetMetadata() {
+    user_metadata_size_ = sizeof(Meta);
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetMetadataSize(size_t user_metadata_size) {
+    user_metadata_size_ = user_metadata_size;
+    return *this;
+  }
+
+ private:
+  bool is_async_{false};
+  uint32_t default_width_{1};
+  uint32_t default_height_{1};
+  uint32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
+  size_t user_metadata_size_{0};
+};
+
+// Explicit specializations of ProducerQueueConfigBuilder::Build for void
+// metadata type.
+template <>
+inline ProducerQueueConfigBuilder&
+ProducerQueueConfigBuilder::SetMetadata<void>() {
+  user_metadata_size_ = 0;
+  return *this;
+}
+
 struct QueueInfo {
-  size_t meta_size_bytes;
+  ProducerQueueConfig producer_config;
   int id;
 
  private:
-  PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
+  PDX_SERIALIZABLE_MEMBERS(QueueInfo, producer_config, id);
 };
 
 struct UsagePolicy {
-  uint64_t usage_set_mask;
-  uint64_t usage_clear_mask;
-  uint64_t usage_deny_set_mask;
-  uint64_t usage_deny_clear_mask;
+  uint64_t usage_set_mask{0};
+  uint64_t usage_clear_mask{0};
+  uint64_t usage_deny_set_mask{0};
+  uint64_t usage_deny_clear_mask{0};
 
  private:
   PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
@@ -181,12 +381,11 @@
     kOpCreateConsumerQueue,
     kOpGetQueueInfo,
     kOpProducerQueueAllocateBuffers,
-    kOpProducerQueueDetachBuffer,
+    kOpProducerQueueRemoveBuffer,
     kOpConsumerQueueImportBuffers,
   };
 
   // Aliases.
-  using MetaData = pdx::rpc::BufferWrapper<std::uint8_t*>;
   using LocalChannelHandle = pdx::LocalChannelHandle;
   using LocalHandle = pdx::LocalHandle;
   using Void = pdx::rpc::Void;
@@ -194,42 +393,41 @@
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
                     void(uint32_t width, uint32_t height, uint32_t format,
-                         uint64_t usage, size_t meta_size_bytes));
+                         uint64_t usage, size_t user_metadata_size));
   PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
                     void(const std::string& name, int user_id, int group_id,
                          uint32_t width, uint32_t height, uint32_t format,
-                         uint64_t usage, size_t meta_size_bytes));
+                         uint64_t usage, size_t user_metadata_size));
   PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
                     void(const std::string& name));
   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
-                    NativeBufferHandle<LocalHandle>(Void));
+                    BufferDescription<LocalHandle>(Void));
   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
                     void(const std::string& name, int user_id, int group_id));
   PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
                     void(Void));
   PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
-                    void(LocalFence acquire_fence, MetaData));
+                    void(LocalFence acquire_fence));
   PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
-  PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
-                    std::pair<LocalFence, MetaData>(std::size_t metadata_size));
+  PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void));
   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
                     void(LocalFence release_fence));
   PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    QueueInfo(size_t meta_size_bytes,
+                    QueueInfo(const ProducerQueueConfig& producer_config,
                               const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
-                    LocalChannelHandle(Void));
+                    LocalChannelHandle(bool silent_queue));
   PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
                         uint32_t width, uint32_t height, uint32_t layer_count,
                         uint32_t format, uint64_t usage, size_t buffer_count));
-  PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
+  PDX_REMOTE_METHOD(ProducerQueueRemoveBuffer, kOpProducerQueueRemoveBuffer,
                     void(size_t slot));
   PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(Void));
diff --git a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
index b4ef2f5..140ffc5 100644
--- a/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/native_buffer.h
@@ -4,9 +4,9 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <log/log.h>
-#include <system/window.h>
 #include <ui/ANativeObjectBase.h>
 #include <utils/RefBase.h>
+#include <nativebase/nativebase.h>
 
 #include <private/dvr/buffer_hub_client.h>
 
@@ -52,8 +52,6 @@
   void operator=(NativeBuffer&) = delete;
 };
 
-// NativeBufferProducer is an implementation of ANativeWindowBuffer backed by a
-// BufferProducer.
 class NativeBufferProducer : public android::ANativeObjectBase<
                                  ANativeWindowBuffer, NativeBufferProducer,
                                  android::LightRefBase<NativeBufferProducer>> {
@@ -71,20 +69,25 @@
     ANativeWindowBuffer::stride = buffer_->stride();
     ANativeWindowBuffer::format = buffer_->format();
     ANativeWindowBuffer::usage = buffer_->usage();
-    handle = buffer_->native_handle();
+    ANativeWindowBuffer::handle = buffer_->native_handle();
+    if (display_) {
+      image_khr_ =
+          eglCreateImageKHR(display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                            static_cast<ANativeWindowBuffer*>(this), nullptr);
+    } else {
+      image_khr_ = EGL_NO_IMAGE_KHR;
+    }
   }
 
   explicit NativeBufferProducer(const std::shared_ptr<BufferProducer>& buffer)
       : NativeBufferProducer(buffer, nullptr, 0) {}
 
   virtual ~NativeBufferProducer() {
-    for (EGLImageKHR egl_image : egl_images_) {
-      if (egl_image != EGL_NO_IMAGE_KHR)
-        eglDestroyImageKHR(display_, egl_image);
-    }
+    if (image_khr_ != EGL_NO_IMAGE_KHR)
+      eglDestroyImageKHR(display_, image_khr_);
   }
 
-  EGLImageKHR image_khr(int index) const { return egl_images_[index]; }
+  EGLImageKHR image_khr() const { return image_khr_; }
   std::shared_ptr<BufferProducer> buffer() const { return buffer_; }
   int release_fence() const { return release_fence_.Get(); }
   uint32_t surface_buffer_index() const { return surface_buffer_index_; }
@@ -112,7 +115,7 @@
 
   std::shared_ptr<BufferProducer> buffer_;
   pdx::LocalHandle release_fence_;
-  std::vector<EGLImageKHR> egl_images_;
+  EGLImageKHR image_khr_;
   uint32_t surface_buffer_index_;
   EGLDisplay display_;
 
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index a587f95..93ccd0f 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -21,10 +21,6 @@
     "include",
 ]
 
-headerLibraries = [
-    "libdvr_headers",
-]
-
 staticLibraries = [
     "libbufferhub",
     "libdvrcommon",
@@ -42,18 +38,24 @@
     "libgui",
 ]
 
+headerLibraries = [
+    "libdvr_headers",
+    "libnativebase_headers",
+]
+
 cc_library {
     name: "libbufferhubqueue",
     cflags: [
         "-DLOG_TAG=\"libbufferhubqueue\"",
         "-DTRACE=0",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
     srcs: sourceFiles,
     export_include_dirs: includeFiles,
     export_static_lib_headers: staticLibraries,
-    header_libs: headerLibraries,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: headerLibraries,
 }
 
 subdirs = ["tests"]
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 012a4e7..8bea0cd 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -10,7 +10,7 @@
 #include <pdx/default_transport/client_channel.h>
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
+#include <pdx/trace.h>
 
 #define RETRY_EINTR(fnc_call)                 \
   ([&]() -> decltype(fnc_call) {              \
@@ -23,34 +23,50 @@
 
 using android::pdx::ErrorStatus;
 using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
 using android::pdx::Status;
 
 namespace android {
 namespace dvr {
 
+namespace {
+
+// Polls an fd for the given events.
+Status<int> PollEvents(int fd, short events) {
+  const int kTimeoutMs = 0;
+  pollfd pfd{fd, events, 0};
+  const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
+  if (count < 0) {
+    return ErrorStatus(errno);
+  } else if (count == 0) {
+    return ErrorStatus(ETIMEDOUT);
+  } else {
+    return {pfd.revents};
+  }
+}
+
+std::pair<int32_t, int32_t> Unstuff(uint64_t value) {
+  return {static_cast<int32_t>(value >> 32),
+          static_cast<int32_t>(value & ((1ull << 32) - 1))};
+}
+
+uint64_t Stuff(int32_t a, int32_t b) {
+  const uint32_t ua = static_cast<uint32_t>(a);
+  const uint32_t ub = static_cast<uint32_t>(b);
+  return (static_cast<uint64_t>(ua) << 32) | static_cast<uint64_t>(ub);
+}
+
+}  // anonymous namespace
+
 BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle)
     : Client{pdx::default_transport::ClientChannel::Create(
-          std::move(channel_handle))},
-      meta_size_(0),
-      buffers_(BufferHubQueue::kMaxQueueCapacity),
-      epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
-      available_buffers_(BufferHubQueue::kMaxQueueCapacity),
-      fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0),
-      id_(-1) {
+          std::move(channel_handle))} {
   Initialize();
 }
 
 BufferHubQueue::BufferHubQueue(const std::string& endpoint_path)
-    : Client{pdx::default_transport::ClientChannelFactory::Create(
-          endpoint_path)},
-      meta_size_(0),
-      buffers_(BufferHubQueue::kMaxQueueCapacity),
-      epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
-      available_buffers_(BufferHubQueue::kMaxQueueCapacity),
-      fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0),
-      id_(-1) {
+    : Client{
+          pdx::default_transport::ClientChannelFactory::Create(endpoint_path)} {
   Initialize();
 }
 
@@ -62,9 +78,9 @@
     return;
   }
 
-  epoll_event event = {.events = EPOLLIN | EPOLLET,
-                       .data = {.u64 = static_cast<uint64_t>(
-                                    BufferHubQueue::kEpollQueueEventIndex)}};
+  epoll_event event = {
+      .events = EPOLLIN | EPOLLET,
+      .data = {.u64 = Stuff(-1, BufferHubQueue::kEpollQueueEventIndex)}};
   ret = epoll_fd_.Control(EPOLL_CTL_ADD, event_fd(), &event);
   if (ret < 0) {
     ALOGE("BufferHubQueue::Initialize: Failed to add event fd to epoll set: %s",
@@ -79,34 +95,37 @@
           status.GetErrorMessage().c_str());
     return ErrorStatus(status.error());
   } else {
-    SetupQueue(status.get().meta_size_bytes, status.get().id);
+    SetupQueue(status.get());
     return {};
   }
 }
 
-void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
-  meta_size_ = meta_size_bytes;
-  id_ = id;
-  meta_buffer_tmp_.reset(meta_size_ > 0 ? new uint8_t[meta_size_] : nullptr);
+void BufferHubQueue::SetupQueue(const QueueInfo& queue_info) {
+  is_async_ = queue_info.producer_config.is_async;
+  default_width_ = queue_info.producer_config.default_width;
+  default_height_ = queue_info.producer_config.default_height;
+  default_format_ = queue_info.producer_config.default_format;
+  user_metadata_size_ = queue_info.producer_config.user_metadata_size;
+  id_ = queue_info.id;
 }
 
 std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
-  if (auto status = CreateConsumerQueueHandle())
+  if (auto status = CreateConsumerQueueHandle(/*silent*/ false))
     return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
   else
     return nullptr;
 }
 
 std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateSilentConsumerQueue() {
-  if (auto status = CreateConsumerQueueHandle())
-    return std::unique_ptr<ConsumerQueue>(
-        new ConsumerQueue(status.take(), true));
+  if (auto status = CreateConsumerQueueHandle(/*silent*/ true))
+    return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
   else
     return nullptr;
 }
 
-Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
-  auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
+Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle(
+    bool silent) {
+  auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>(silent);
   if (!status) {
     ALOGE(
         "BufferHubQueue::CreateConsumerQueue: Failed to create consumer queue: "
@@ -119,6 +138,7 @@
 }
 
 bool BufferHubQueue::WaitForBuffers(int timeout) {
+  ATRACE_NAME("BufferHubQueue::WaitForBuffers");
   std::array<epoll_event, kMaxEvents> events;
 
   // Loop at least once to check for hangups.
@@ -149,22 +169,32 @@
     const int num_events = ret;
 
     // A BufferQueue's epoll fd tracks N+1 events, where there are N events,
-    // one for each buffer, in the queue and one extra event for the queue
+    // one for each buffer in the queue, and one extra event for the queue
     // client itself.
     for (int i = 0; i < num_events; i++) {
-      int64_t index = static_cast<int64_t>(events[i].data.u64);
+      int32_t event_fd;
+      int32_t index;
+      std::tie(event_fd, index) = Unstuff(events[i].data.u64);
+
+      PDX_TRACE_FORMAT(
+          "epoll_event|queue_id=%d;num_events=%d;event_index=%d;event_fd=%d;"
+          "slot=%d|",
+          id(), num_events, i, event_fd, index);
 
       ALOGD_IF(TRACE,
-               "BufferHubQueue::WaitForBuffers: event %d: index=%" PRId64, i,
-               index);
+               "BufferHubQueue::WaitForBuffers: event %d: event_fd=%d index=%d",
+               i, event_fd, index);
 
       if (is_buffer_event_index(index)) {
-        HandleBufferEvent(static_cast<size_t>(index), events[i].events);
+        HandleBufferEvent(static_cast<size_t>(index), event_fd,
+                          events[i].events);
       } else if (is_queue_event_index(index)) {
         HandleQueueEvent(events[i].events);
       } else {
-        ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
-              index);
+        ALOGW(
+            "BufferHubQueue::WaitForBuffers: Unknown event type event_fd=%d "
+            "index=%d",
+            event_fd, index);
       }
     }
   } while (count() == 0 && capacity() > 0 && !hung_up());
@@ -172,67 +202,52 @@
   return count() != 0;
 }
 
-void BufferHubQueue::HandleBufferEvent(size_t slot, int poll_events) {
-  auto buffer = buffers_[slot];
-  if (!buffer) {
+Status<void> BufferHubQueue::HandleBufferEvent(size_t slot, int event_fd,
+                                               int poll_events) {
+  ATRACE_NAME("BufferHubQueue::HandleBufferEvent");
+  if (!buffers_[slot]) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
-    return;
+    return ErrorStatus(ENOENT);
   }
 
-  auto status = buffer->GetEventMask(poll_events);
+  auto status = buffers_[slot]->GetEventMask(poll_events);
   if (!status) {
     ALOGW("BufferHubQueue::HandleBufferEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
-    return;
+    return status.error_status();
   }
 
   const int events = status.get();
+  PDX_TRACE_FORMAT(
+      "buffer|queue_id=%d;buffer_id=%d;slot=%zu;event_fd=%d;poll_events=%x;"
+      "events=%d|",
+      id(), buffers_[slot]->id(), slot, event_fd, poll_events, events);
+
   if (events & EPOLLIN) {
-    const int ret = OnBufferReady(buffer, &fences_[slot]);
-    if (ret == 0 || ret == -EALREADY || ret == -EBUSY) {
-      // Only enqueue the buffer if it moves to or is already in the state
-      // requested in OnBufferReady(). If the buffer is busy this means that the
-      // buffer moved from released to posted when a new consumer was created
-      // before the ProducerQueue had a chance to regain it. This is a valid
-      // transition that we have to handle because edge triggered poll events
-      // latch the ready state even if it is later de-asserted -- don't enqueue
-      // or print an error log in this case.
-      if (ret != -EBUSY)
-        Enqueue(buffer, slot);
-    } else {
-      ALOGE(
-          "BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
-          "queue_id=%d buffer_id=%d: %s",
-          id(), buffer->id(), strerror(-ret));
-    }
+    return Enqueue({buffers_[slot], slot, buffers_[slot]->GetQueueIndex()});
   } else if (events & EPOLLHUP) {
-    // This might be caused by producer replacing an existing buffer slot, or
-    // when BufferHubQueue is shutting down. For the first case, currently the
-    // epoll FD is cleaned up when the replacement consumer client is imported,
-    // we shouldn't detach again if |epollhub_pending_[slot]| is set.
     ALOGW(
-        "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP at slot: %zu, "
-        "buffer event fd: %d, EPOLLHUP pending: %d",
-        slot, buffer->event_fd(), int{epollhup_pending_[slot]});
-    if (epollhup_pending_[slot]) {
-      epollhup_pending_[slot] = false;
-    } else {
-      DetachBuffer(slot);
-    }
+        "BufferHubQueue::HandleBufferEvent: Received EPOLLHUP event: slot=%zu "
+        "event_fd=%d buffer_id=%d",
+        slot, buffers_[slot]->event_fd(), buffers_[slot]->id());
+    return RemoveBuffer(slot);
   } else {
     ALOGW(
         "BufferHubQueue::HandleBufferEvent: Unknown event, slot=%zu, epoll "
         "events=%d",
         slot, events);
   }
+
+  return {};
 }
 
-void BufferHubQueue::HandleQueueEvent(int poll_event) {
+Status<void> BufferHubQueue::HandleQueueEvent(int poll_event) {
+  ATRACE_NAME("BufferHubQueue::HandleQueueEvent");
   auto status = GetEventMask(poll_event);
   if (!status) {
     ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
           status.GetErrorMessage().c_str());
-    return;
+    return status.error_status();
   }
 
   const int events = status.get();
@@ -250,115 +265,144 @@
   } else {
     ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%x", events);
   }
+
+  return {};
 }
 
-int BufferHubQueue::AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf,
-                              size_t slot) {
+Status<void> BufferHubQueue::AddBuffer(
+    const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+  ALOGD_IF(TRACE, "BufferHubQueue::AddBuffer: buffer_id=%d slot=%zu",
+           buffer->id(), slot);
+
   if (is_full()) {
-    // TODO(jwcai) Move the check into Producer's AllocateBuffer and consumer's
-    // import buffer.
     ALOGE("BufferHubQueue::AddBuffer queue is at maximum capacity: %zu",
           capacity_);
-    return -E2BIG;
+    return ErrorStatus(E2BIG);
   }
 
-  if (buffers_[slot] != nullptr) {
-    // Replace the buffer if the slot is preoccupied. This could happen when the
-    // producer side replaced the slot with a newly allocated buffer. Detach the
+  if (buffers_[slot]) {
+    // Replace the buffer if the slot is occupied. This could happen when the
+    // producer side replaced the slot with a newly allocated buffer. Remove the
     // buffer before setting up with the new one.
-    DetachBuffer(slot);
-    epollhup_pending_[slot] = true;
+    auto remove_status = RemoveBuffer(slot);
+    if (!remove_status)
+      return remove_status.error_status();
   }
 
-  epoll_event event = {.events = EPOLLIN | EPOLLET, .data = {.u64 = slot}};
-  const int ret = epoll_fd_.Control(EPOLL_CTL_ADD, buf->event_fd(), &event);
-  if (ret < 0) {
-    ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s",
-          strerror(-ret));
-    return ret;
+  for (const auto& event_source : buffer->GetEventSources()) {
+    epoll_event event = {.events = event_source.event_mask | EPOLLET,
+                         .data = {.u64 = Stuff(buffer->event_fd(), slot)}};
+    const int ret =
+        epoll_fd_.Control(EPOLL_CTL_ADD, event_source.event_fd, &event);
+    if (ret < 0) {
+      ALOGE("BufferHubQueue::AddBuffer: Failed to add buffer to epoll set: %s",
+            strerror(-ret));
+      return ErrorStatus(-ret);
+    }
   }
 
-  buffers_[slot] = buf;
+  buffers_[slot] = buffer;
   capacity_++;
-  return 0;
+  return {};
 }
 
-int BufferHubQueue::DetachBuffer(size_t slot) {
-  auto& buf = buffers_[slot];
-  if (buf == nullptr) {
-    ALOGE("BufferHubQueue::DetachBuffer: Invalid slot: %zu", slot);
-    return -EINVAL;
+Status<void> BufferHubQueue::RemoveBuffer(size_t slot) {
+  ALOGD_IF(TRACE, "BufferHubQueue::RemoveBuffer: slot=%zu", slot);
+
+  if (buffers_[slot]) {
+    for (const auto& event_source : buffers_[slot]->GetEventSources()) {
+      const int ret =
+          epoll_fd_.Control(EPOLL_CTL_DEL, event_source.event_fd, nullptr);
+      if (ret < 0) {
+        ALOGE(
+            "BufferHubQueue::RemoveBuffer: Failed to remove buffer from epoll "
+            "set: %s",
+            strerror(-ret));
+        return ErrorStatus(-ret);
+      }
+    }
+
+    // Trigger OnBufferRemoved callback if registered.
+    if (on_buffer_removed_)
+      on_buffer_removed_(buffers_[slot]);
+
+    buffers_[slot] = nullptr;
+    capacity_--;
   }
 
-  const int ret = epoll_fd_.Control(EPOLL_CTL_DEL, buf->event_fd(), nullptr);
-  if (ret < 0) {
-    ALOGE(
-        "BufferHubQueue::DetachBuffer: Failed to detach buffer from epoll set: "
-        "%s",
-        strerror(-ret));
-    return ret;
-  }
-
-  buffers_[slot] = nullptr;
-  capacity_--;
-  return 0;
+  return {};
 }
 
-void BufferHubQueue::Enqueue(const std::shared_ptr<BufferHubBuffer>& buf,
-                             size_t slot) {
-  if (count() == capacity_) {
+Status<void> BufferHubQueue::Enqueue(Entry entry) {
+  if (!is_full()) {
+    available_buffers_.push(std::move(entry));
+
+    // Trigger OnBufferAvailable callback if registered.
+    if (on_buffer_available_)
+      on_buffer_available_();
+
+    return {};
+  } else {
     ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
-    return;
+    return ErrorStatus(E2BIG);
   }
-
-  // Set slot buffer back to vector.
-  // TODO(jwcai) Here have to dynamically allocate BufferInfo::metadata due to
-  // the limitation of the RingBuffer we are using. Would be better to refactor
-  // that.
-  BufferInfo buffer_info(slot, meta_size_);
-  buffer_info.buffer = buf;
-  // Swap metadata loaded during onBufferReady into vector.
-  std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
-  available_buffers_.Append(std::move(buffer_info));
 }
 
-Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(
-    int timeout, size_t* slot, void* meta, LocalHandle* fence) {
-  ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
+Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(int timeout,
+                                                                 size_t* slot) {
+  ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
+           timeout);
 
-  if (!WaitForBuffers(timeout))
-    return ErrorStatus(ETIMEDOUT);
+  PDX_TRACE_FORMAT("BufferHubQueue::Dequeue|count=%zu|", count());
 
-  std::shared_ptr<BufferHubBuffer> buf;
-  BufferInfo& buffer_info = available_buffers_.Front();
-
-  *fence = std::move(fences_[buffer_info.slot]);
-
-  // Report current pos as the output slot.
-  std::swap(buffer_info.slot, *slot);
-  // Swap buffer from vector to be returned later.
-  std::swap(buffer_info.buffer, buf);
-  // Swap metadata from vector into tmp so that we can write out to |meta|.
-  std::swap(buffer_info.metadata, meta_buffer_tmp_);
-
-  available_buffers_.PopFront();
-
-  if (!buf) {
-    ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
-    return ErrorStatus(ENOBUFS);
+  if (count() == 0) {
+    if (!WaitForBuffers(timeout))
+      return ErrorStatus(ETIMEDOUT);
   }
 
-  if (meta) {
-    std::copy(meta_buffer_tmp_.get(), meta_buffer_tmp_.get() + meta_size_,
-              reinterpret_cast<uint8_t*>(meta));
-  }
+  auto& entry = available_buffers_.top();
+  PDX_TRACE_FORMAT("buffer|buffer_id=%d;slot=%zu|", entry.buffer->id(),
+                   entry.slot);
 
-  return {std::move(buf)};
+  std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
+  *slot = entry.slot;
+
+  available_buffers_.pop();
+
+  return {std::move(buffer)};
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+void BufferHubQueue::SetBufferAvailableCallback(
+    BufferAvailableCallback callback) {
+  on_buffer_available_ = callback;
+}
+
+void BufferHubQueue::SetBufferRemovedCallback(BufferRemovedCallback callback) {
+  on_buffer_removed_ = callback;
+}
+
+pdx::Status<void> BufferHubQueue::FreeAllBuffers() {
+  // Clear all available buffers.
+  while (!available_buffers_.empty())
+    available_buffers_.pop();
+
+  pdx::Status<void> last_error;  // No error.
+  // Clear all buffers this producer queue is tracking.
+  for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
+    if (buffers_[slot] != nullptr) {
+      auto status = RemoveBuffer(slot);
+      if (!status) {
+        ALOGE(
+            "ProducerQueue::FreeAllBuffers: Failed to remove buffer at "
+            "slot=%zu.",
+            slot);
+        last_error = status.error_status();
+      }
+    }
+  }
+
+  return last_error;
+}
 
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
@@ -370,14 +414,11 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                             uint64_t usage_clear_mask,
-                             uint64_t usage_deny_set_mask,
-                             uint64_t usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(const ProducerQueueConfig& config,
+                             const UsagePolicy& usage)
     : BASE(BufferHubRPC::kClientPath) {
-  auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size, UsagePolicy{usage_set_mask, usage_clear_mask,
-                             usage_deny_set_mask, usage_deny_clear_mask});
+  auto status =
+      InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(config, usage);
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -385,102 +426,137 @@
     return;
   }
 
-  SetupQueue(status.get().meta_size_bytes, status.get().id);
+  SetupQueue(status.get());
 }
 
-int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
-                                  uint32_t layer_count, uint32_t format,
-                                  uint64_t usage, size_t* out_slot) {
-  if (out_slot == nullptr) {
-    ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
-    return -EINVAL;
+Status<std::vector<size_t>> ProducerQueue::AllocateBuffers(
+    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+    uint64_t usage, size_t buffer_count) {
+  if (capacity() + buffer_count > kMaxQueueCapacity) {
+    ALOGE(
+        "ProducerQueue::AllocateBuffers: queue is at capacity: %zu, cannot "
+        "allocate %zu more buffer(s).",
+        capacity(), buffer_count);
+    return ErrorStatus(E2BIG);
   }
 
-  if (is_full()) {
-    ALOGE("ProducerQueue::AllocateBuffer queue is at maximum capacity: %zu",
-          capacity());
-    return -E2BIG;
-  }
-
-  const size_t kBufferCount = 1U;
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, layer_count, format, usage, kBufferCount);
+          width, height, layer_count, format, usage, buffer_count);
   if (!status) {
-    ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
+    ALOGE("ProducerQueue::AllocateBuffers: failed to allocate buffers: %s",
           status.GetErrorMessage().c_str());
-    return -status.error();
+    return status.error_status();
   }
 
   auto buffer_handle_slots = status.take();
-  LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != kBufferCount,
+  LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != buffer_count,
                       "BufferHubRPC::ProducerQueueAllocateBuffers should "
-                      "return one and only one buffer handle.");
+                      "return %zu buffer handle(s), but returned %zu instead.",
+                      buffer_count, buffer_handle_slots.size());
 
-  // We only allocate one buffer at a time.
-  auto& buffer_handle = buffer_handle_slots[0].first;
-  size_t buffer_slot = buffer_handle_slots[0].second;
-  ALOGD_IF(TRACE,
-           "ProducerQueue::AllocateBuffer, new buffer, channel_handle: %d",
-           buffer_handle.value());
+  std::vector<size_t> buffer_slots;
+  buffer_slots.reserve(buffer_count);
 
-  *out_slot = buffer_slot;
-  return AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
-                   buffer_slot);
-}
+  // Bookkeeping for each buffer.
+  for (auto& hs : buffer_handle_slots) {
+    auto& buffer_handle = hs.first;
+    size_t buffer_slot = hs.second;
 
-int ProducerQueue::AddBuffer(const std::shared_ptr<BufferProducer>& buf,
-                             size_t slot) {
-  ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
-           id(), buf->id(), slot);
-  // For producer buffer, we need to enqueue the newly added buffer
-  // immediately. Producer queue starts with all buffers in available state.
-  const int ret = BufferHubQueue::AddBuffer(buf, slot);
-  if (ret < 0)
-    return ret;
-
-  Enqueue(buf, slot);
-  return 0;
-}
-
-int ProducerQueue::DetachBuffer(size_t slot) {
-  auto status =
-      InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
-  if (!status) {
-    ALOGE("ProducerQueue::DetachBuffer: Failed to detach producer buffer: %s",
-          status.GetErrorMessage().c_str());
-    return -status.error();
+    // Note that import might (though very unlikely) fail. If so, buffer_handle
+    // will be closed and included in returned buffer_slots.
+    if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
+                  buffer_slot)) {
+      ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
+               buffer_slot);
+      buffer_slots.push_back(buffer_slot);
+    }
   }
 
-  return BufferHubQueue::DetachBuffer(slot);
+  if (buffer_slots.size() == 0) {
+    // Error out if no buffer is allocated and improted.
+    ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffers: no buffer allocated.");
+    ErrorStatus(ENOMEM);
+  }
+
+  return {std::move(buffer_slots)};
+}
+
+Status<size_t> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                             uint32_t layer_count,
+                                             uint32_t format, uint64_t usage) {
+  // We only allocate one buffer at a time.
+  constexpr size_t buffer_count = 1;
+  auto status =
+      AllocateBuffers(width, height, layer_count, format, usage, buffer_count);
+  if (!status) {
+    ALOGE("ProducerQueue::AllocateBuffer: Failed to allocate buffer: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  if (status.get().size() == 0) {
+    ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffer: no buffer allocated.");
+    ErrorStatus(ENOMEM);
+  }
+
+  return {status.get()[0]};
+}
+
+Status<void> ProducerQueue::AddBuffer(
+    const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
+  ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
+           id(), buffer->id(), slot);
+  // For producer buffer, we need to enqueue the newly added buffer
+  // immediately. Producer queue starts with all buffers in available state.
+  auto status = BufferHubQueue::AddBuffer(buffer, slot);
+  if (!status)
+    return status;
+
+  return BufferHubQueue::Enqueue({buffer, slot, 0ULL});
+}
+
+Status<void> ProducerQueue::RemoveBuffer(size_t slot) {
+  auto status =
+      InvokeRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>(slot);
+  if (!status) {
+    ALOGE("ProducerQueue::RemoveBuffer: Failed to remove producer buffer: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  return BufferHubQueue::RemoveBuffer(slot);
 }
 
 Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, LocalHandle* release_fence) {
-  if (slot == nullptr || release_fence == nullptr) {
-    ALOGE("ProducerQueue::Dequeue: Invalid parameter: slot=%p release_fence=%p",
-          slot, release_fence);
+  DvrNativeBufferMetadata canonical_meta;
+  return Dequeue(timeout, slot, &canonical_meta, release_fence);
+}
+
+pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+    int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
+    pdx::LocalHandle* release_fence) {
+  ATRACE_NAME("ProducerQueue::Dequeue");
+  if (slot == nullptr || out_meta == nullptr || release_fence == nullptr) {
+    ALOGE("ProducerQueue::Dequeue: Invalid parameter.");
     return ErrorStatus(EINVAL);
   }
 
-  auto buffer_status =
-      BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
-  if (!buffer_status)
-    return buffer_status.error_status();
+  auto status = BufferHubQueue::Dequeue(timeout, slot);
+  if (!status)
+    return status.error_status();
 
-  return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
+  auto buffer = std::static_pointer_cast<BufferProducer>(status.take());
+  const int ret = buffer->GainAsync(out_meta, release_fence);
+  if (ret < 0 && ret != -EALREADY)
+    return ErrorStatus(-ret);
+
+  return {std::move(buffer)};
 }
 
-int ProducerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                                 LocalHandle* release_fence) {
-  ALOGD_IF(TRACE, "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
-           id(), buf->id());
-  auto buffer = std::static_pointer_cast<BufferProducer>(buf);
-  return buffer->Gain(release_fence);
-}
-
-ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
-    : BufferHubQueue(std::move(handle)), ignore_on_import_(ignore_on_import) {
+ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
+    : BufferHubQueue(std::move(handle)) {
   auto status = ImportQueue();
   if (!status) {
     ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
@@ -501,14 +577,22 @@
 Status<size_t> ConsumerQueue::ImportBuffers() {
   auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
   if (!status) {
-    ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
+    if (status.error() == EBADR) {
+      ALOGI(
+          "ConsumerQueue::ImportBuffers: Queue is silent, no buffers "
+          "imported.");
+      return {0};
+    } else {
+      ALOGE(
+          "ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
           status.GetErrorMessage().c_str());
-    return ErrorStatus(status.error());
+      return status.error_status();
+    }
   }
 
   int ret;
-  int last_error = 0;
-  int imported_buffers = 0;
+  Status<void> last_error;
+  size_t imported_buffers_count = 0;
 
   auto buffer_handle_slots = status.take();
   for (auto& buffer_handle_slot : buffer_handle_slots) {
@@ -517,104 +601,110 @@
 
     std::unique_ptr<BufferConsumer> buffer_consumer =
         BufferConsumer::Import(std::move(buffer_handle_slot.first));
-
-    // Setup ignore state before adding buffer to the queue.
-    if (ignore_on_import_) {
-      ALOGD_IF(TRACE,
-               "ConsumerQueue::ImportBuffers: Setting buffer to ignored state: "
-               "buffer_id=%d",
-               buffer_consumer->id());
-      ret = buffer_consumer->SetIgnore(true);
-      if (ret < 0) {
-        ALOGE(
-            "ConsumerQueue::ImportBuffers: Failed to set ignored state on "
-            "imported buffer buffer_id=%d: %s",
-            buffer_consumer->id(), strerror(-ret));
-        last_error = ret;
-      }
+    if (!buffer_consumer) {
+      ALOGE("ConsumerQueue::ImportBuffers: Failed to import buffer: slot=%zu",
+            buffer_handle_slot.second);
+      last_error = ErrorStatus(EPIPE);
+      continue;
     }
 
-    ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
-    if (ret < 0) {
+    auto add_status =
+        AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+    if (!add_status) {
       ALOGE("ConsumerQueue::ImportBuffers: Failed to add buffer: %s",
-            strerror(-ret));
-      last_error = ret;
-      continue;
+            add_status.GetErrorMessage().c_str());
+      last_error = add_status;
     } else {
-      imported_buffers++;
+      imported_buffers_count++;
     }
   }
 
-  if (imported_buffers > 0)
-    return {imported_buffers};
+  if (imported_buffers_count > 0)
+    return {imported_buffers_count};
   else
-    return ErrorStatus(-last_error);
+    return last_error.error_status();
 }
 
-int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
-                             size_t slot) {
+Status<void> ConsumerQueue::AddBuffer(
+    const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "ConsumerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
-           id(), buf->id(), slot);
-  const int ret = BufferHubQueue::AddBuffer(buf, slot);
-  if (ret < 0)
-    return ret;
+           id(), buffer->id(), slot);
+  auto status = BufferHubQueue::AddBuffer(buffer, slot);
+  if (!status)
+    return status;
 
   // Check to see if the buffer is already signaled. This is necessary to catch
   // cases where buffers are already available; epoll edge triggered mode does
-  // not fire until and edge transition when adding new buffers to the epoll
-  // set.
-  const int kTimeoutMs = 0;
-  pollfd pfd{buf->event_fd(), POLLIN, 0};
-  const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
-  if (count < 0) {
-    const int error = errno;
+  // not fire until an edge transition when adding new buffers to the epoll
+  // set. Note that we only poll the fd events because HandleBufferEvent() takes
+  // care of checking the translated buffer events.
+  auto poll_status = PollEvents(buffer->event_fd(), POLLIN);
+  if (!poll_status && poll_status.error() != ETIMEDOUT) {
     ALOGE("ConsumerQueue::AddBuffer: Failed to poll consumer buffer: %s",
-          strerror(errno));
-    return -error;
+          poll_status.GetErrorMessage().c_str());
+    return poll_status.error_status();
   }
 
-  if (count == 1)
-    HandleBufferEvent(slot, pfd.revents);
-
-  return 0;
+  // Update accounting if the buffer is available.
+  if (poll_status)
+    return HandleBufferEvent(slot, buffer->event_fd(), poll_status.get());
+  else
+    return {};
 }
 
 Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
-    int timeout, size_t* slot, void* meta, size_t meta_size,
+    int timeout, size_t* slot, void* meta, size_t user_metadata_size,
     LocalHandle* acquire_fence) {
-  if (meta_size != meta_size_) {
+  if (user_metadata_size != user_metadata_size_) {
     ALOGE(
         "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
         "does not match metadata size (%zu) for the queue.",
-        meta_size, meta_size_);
+        user_metadata_size, user_metadata_size_);
     return ErrorStatus(EINVAL);
   }
 
-  if (slot == nullptr || acquire_fence == nullptr) {
-    ALOGE(
-        "ConsumerQueue::Dequeue: Invalid parameter: slot=%p meta=%p "
-        "acquire_fence=%p",
-        slot, meta, acquire_fence);
-    return ErrorStatus(EINVAL);
+  DvrNativeBufferMetadata canonical_meta;
+  auto status = Dequeue(timeout, slot, &canonical_meta, acquire_fence);
+  if (!status)
+    return status.error_status();
+
+  if (meta && user_metadata_size) {
+    void* metadata_src =
+        reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
+    if (metadata_src) {
+      memcpy(meta, metadata_src, user_metadata_size);
+    } else {
+      ALOGW("ConsumerQueue::Dequeue: no user-defined metadata.");
+    }
   }
 
-  auto buffer_status =
-      BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
-  if (!buffer_status)
-    return buffer_status.error_status();
-
-  return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())};
+  return status;
 }
 
-int ConsumerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                                 LocalHandle* acquire_fence) {
-  ALOGD_IF(TRACE, "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
-           id(), buf->id());
-  auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
-  return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
+Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+    int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
+    pdx::LocalHandle* acquire_fence) {
+  ATRACE_NAME("ConsumerQueue::Dequeue");
+  if (slot == nullptr || out_meta == nullptr || acquire_fence == nullptr) {
+    ALOGE("ConsumerQueue::Dequeue: Invalid parameter.");
+    return ErrorStatus(EINVAL);
+  }
+
+  auto status = BufferHubQueue::Dequeue(timeout, slot);
+  if (!status)
+    return status.error_status();
+
+  auto buffer = std::static_pointer_cast<BufferConsumer>(status.take());
+  const int ret = buffer->AcquireAsync(out_meta, acquire_fence);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+
+  return {std::move(buffer)};
 }
 
 Status<void> ConsumerQueue::OnBufferAllocated() {
+  ALOGD_IF(TRACE, "ConsumerQueue::OnBufferAllocated: queue_id=%d", id());
+
   auto status = ImportBuffers();
   if (!status) {
     ALOGE("ConsumerQueue::OnBufferAllocated: Failed to import buffers: %s",
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 8582bbf..221bc4f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -3,6 +3,7 @@
 #include <dvr/dvr_api.h>
 #include <inttypes.h>
 #include <log/log.h>
+#include <system/window.h>
 
 namespace android {
 namespace dvr {
@@ -10,7 +11,10 @@
 /* static */
 sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
   sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
-  producer->queue_ = ProducerQueue::Create<DvrNativeBufferMetadata>();
+  auto config = ProducerQueueConfigBuilder()
+                    .SetMetadata<DvrNativeBufferMetadata>()
+                    .Build();
+  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
   return producer;
 }
 
@@ -127,9 +131,9 @@
 
 status_t BufferHubQueueProducer::dequeueBuffer(
     int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
-    PixelFormat format, uint32_t usage,
+    PixelFormat format, uint64_t usage, uint64_t* /*outBufferAge*/,
     FrameEventHistoryDelta* /* out_timestamps */) {
-  ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
+  ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width,
            height, format, usage);
 
   status_t ret;
@@ -158,6 +162,8 @@
   for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
     LocalHandle fence;
     auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
+    if (!buffer_status)
+      return NO_MEMORY;
 
     buffer_producer = buffer_status.take();
     if (!buffer_producer)
@@ -200,11 +206,11 @@
   // It's either in free state (if the buffer has never been used before) or
   // in queued state (if the buffer has been dequeued and queued back to
   // BufferHubQueue).
-  // TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
-  // model.
-  LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
-                       !buffers_[slot].mBufferState.isQueued()),
-                      "dequeueBuffer: slot %zu is not free or queued.", slot);
+  LOG_ALWAYS_FATAL_IF(
+      (!buffers_[slot].mBufferState.isFree() &&
+       !buffers_[slot].mBufferState.isQueued()),
+      "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
+      buffers_[slot].mBufferState.string());
 
   buffers_[slot].mBufferState.freeQueued();
   buffers_[slot].mBufferState.dequeue();
@@ -322,7 +328,7 @@
 
   LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
 
-  DvrNativeBufferMetadata meta_data = {};
+  DvrNativeBufferMetadata meta_data;
   meta_data.timestamp = timestamp;
   meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
   meta_data.dataspace = static_cast<int32_t>(dataspace);
@@ -333,7 +339,7 @@
   meta_data.scaling_mode = static_cast<int32_t>(scaling_mode);
   meta_data.transform = static_cast<int32_t>(transform);
 
-  buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
+  buffer_producer->PostAsync(&meta_data, fence_fd);
   buffers_[slot].mBufferState.queue();
 
   output->width = buffer_producer->width();
@@ -378,7 +384,7 @@
   }
 
   auto buffer_producer = buffers_[slot].mBufferProducer;
-  queue_->Enqueue(buffer_producer, slot);
+  queue_->Enqueue(buffer_producer, slot, 0ULL);
   buffers_[slot].mBufferState.cancel();
   buffers_[slot].mFence = fence;
   ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
@@ -508,6 +514,7 @@
     return BAD_VALUE;
   }
 
+  FreeAllBuffers();
   connected_api_ = kNoConnectedApi;
   return NO_ERROR;
 }
@@ -526,7 +533,7 @@
 void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
                                              uint32_t /* height */,
                                              PixelFormat /* format */,
-                                             uint32_t /* usage */) {
+                                             uint64_t /* usage */) {
   // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
   // of buffers permitted by the current BufferQueue configuration (aka
   // |max_buffer_count_|).
@@ -602,18 +609,28 @@
   return NO_ERROR;
 }
 
+status_t BufferHubQueueProducer::getConsumerUsage(uint64_t* out_usage) const {
+  ALOGD_IF(TRACE, __FUNCTION__);
+
+  // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
+  *out_usage = 0;
+  return NO_ERROR;
+}
+
 status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
                                                 uint32_t layer_count,
                                                 PixelFormat format,
                                                 uint64_t usage) {
-  size_t slot;
-
-  if (queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot) <
-      0) {
-    ALOGE("Failed to allocate new buffer in BufferHub.");
+  auto status =
+      queue_->AllocateBuffer(width, height, layer_count, format, usage);
+  if (!status) {
+    ALOGE(
+        "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
+        status.GetErrorMessage().c_str());
     return NO_MEMORY;
   }
 
+  size_t slot = status.get();
   auto buffer_producer = queue_->GetBuffer(slot);
 
   LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
@@ -625,11 +642,11 @@
 }
 
 status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
-  int ret = queue_->DetachBuffer(slot);
-  if (ret < 0) {
-    ALOGE("BufferHubQueueProducer::RemoveBuffer failed through RPC, ret=%s",
-          strerror(-ret));
-    return ret;
+  auto status = queue_->RemoveBuffer(slot);
+  if (!status) {
+    ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to remove buffer: %s",
+          status.GetErrorMessage().c_str());
+    return INVALID_OPERATION;
   }
 
   // Reset in memory objects related the the buffer.
@@ -639,5 +656,31 @@
   return NO_ERROR;
 }
 
+status_t BufferHubQueueProducer::FreeAllBuffers() {
+  for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
+    // Reset in memory objects related the the buffer.
+    buffers_[slot].mGraphicBuffer = nullptr;
+    buffers_[slot].mBufferState.reset();
+    buffers_[slot].mRequestBufferCalled = false;
+    buffers_[slot].mBufferProducer = nullptr;
+    buffers_[slot].mFence = Fence::NO_FENCE;
+  }
+
+  auto status = queue_->FreeAllBuffers();
+  if (!status) {
+    ALOGE(
+        "BufferHubQueueProducer::FreeAllBuffers: Failed to free all buffers on "
+        "the queue: %s",
+        status.GetErrorMessage().c_str());
+  }
+
+  if (queue_->capacity() != 0 || queue_->count() != 0) {
+    LOG_ALWAYS_FATAL(
+        "BufferHubQueueProducer::FreeAllBuffers: Not all buffers are freed.");
+  }
+
+  return NO_ERROR;
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index ed67f79..6962d6c 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -6,10 +6,12 @@
 #include <pdx/client.h>
 #include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/epoll_file_descriptor.h>
 #include <private/dvr/ring_buffer.h>
 
 #include <memory>
+#include <queue>
 #include <vector>
 
 namespace android {
@@ -21,54 +23,63 @@
 // automatically re-requeued when released by the remote side.
 class BufferHubQueue : public pdx::Client {
  public:
-  using LocalHandle = pdx::LocalHandle;
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  template <typename T>
-  using Status = pdx::Status<T>;
+  using BufferAvailableCallback = std::function<void()>;
+  using BufferRemovedCallback =
+      std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
 
   virtual ~BufferHubQueue() {}
-  void Initialize();
 
-  // Create a new consumer queue that is attached to the producer. Returns
+  // Creates a new consumer queue that is attached to the producer. Returns
   // a new consumer queue client or nullptr on failure.
   std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
 
-  // Create a new consumer queue that is attached to the producer. This queue
+  // Creates a new consumer queue that is attached to the producer. This queue
   // sets each of its imported consumer buffers to the ignored state to avoid
   // participation in lifecycle events.
   std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
 
-  // Return the default buffer width of this buffer queue.
-  size_t default_width() const { return default_width_; }
+  // Returns whether the buffer queue is in async mode.
+  bool is_async() const { return is_async_; }
 
-  // Return the default buffer height of this buffer queue.
-  size_t default_height() const { return default_height_; }
+  // Returns the default buffer width of this buffer queue.
+  uint32_t default_width() const { return default_width_; }
 
-  // Return the default buffer format of this buffer queue.
-  int32_t default_format() const { return default_format_; }
+  // Returns the default buffer height of this buffer queue.
+  uint32_t default_height() const { return default_height_; }
 
-  // Create a new consumer in handle form for immediate transport over RPC.
-  Status<LocalChannelHandle> CreateConsumerQueueHandle();
+  // Returns the default buffer format of this buffer queue.
+  uint32_t default_format() const { return default_format_; }
 
-  // Return the number of buffers avaiable for dequeue.
-  size_t count() const { return available_buffers_.GetSize(); }
+  // Creates a new consumer in handle form for immediate transport over RPC.
+  pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
+      bool silent = false);
 
-  // Return the total number of buffers that the queue is tracking.
+  // Returns the number of buffers avaiable for dequeue.
+  size_t count() const { return available_buffers_.size(); }
+
+  // Returns the total number of buffers that the queue is tracking.
   size_t capacity() const { return capacity_; }
 
-  // Return the size of metadata structure associated with this BufferBubQueue.
-  size_t metadata_size() const { return meta_size_; }
+  // Returns the size of metadata structure associated with this queue.
+  size_t metadata_size() const { return user_metadata_size_; }
 
-  // Return whether the buffer queue is alrady full.
-  bool is_full() const { return available_buffers_.IsFull(); }
+  // Returns whether the buffer queue is full.
+  bool is_full() const {
+    return available_buffers_.size() >= kMaxQueueCapacity;
+  }
 
   explicit operator bool() const { return epoll_fd_.IsValid(); }
 
+  int GetBufferId(size_t slot) const {
+    return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
+                                                      : -1;
+  }
+
   std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
     return buffers_[slot];
   }
 
-  Status<int> GetEventMask(int events) {
+  pdx::Status<int> GetEventMask(int events) {
     if (auto* client_channel = GetChannel()) {
       return client_channel->GetEventMask(events);
     } else {
@@ -86,81 +97,109 @@
   // occurred.
   bool HandleQueueEvents() { return WaitForBuffers(0); }
 
-  // Enqueue a buffer marks buffer to be available (|Gain|'ed for producer
-  // and |Acquire|'ed for consumer. This is only used for internal bookkeeping.
-  void Enqueue(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
+  // Set buffer event callbacks, which are std::function wrappers. The caller is
+  // responsible for ensuring the validity of these callbacks' callable targets.
+  void SetBufferAvailableCallback(BufferAvailableCallback callback);
+  void SetBufferRemovedCallback(BufferRemovedCallback callback);
 
-  // |BufferHubQueue| will keep track of at most this value of buffers.
+  // The queue tracks at most this many buffers.
   static constexpr size_t kMaxQueueCapacity =
       android::BufferQueueDefs::NUM_BUFFER_SLOTS;
 
-  // Special epoll data field indicating that the epoll event refers to the
-  // queue.
-  static constexpr int64_t kEpollQueueEventIndex = -1;
-
-  // When pass |kNoTimeout| to |Dequeue|, it will block indefinitely without a
-  // timeout.
   static constexpr int kNoTimeOut = -1;
 
   int id() const { return id_; }
   bool hung_up() const { return hung_up_; }
 
  protected:
-  BufferHubQueue(LocalChannelHandle channel);
+  BufferHubQueue(pdx::LocalChannelHandle channel);
   BufferHubQueue(const std::string& endpoint_path);
 
   // Imports the queue parameters by querying BufferHub for the parameters for
   // this channel.
-  Status<void> ImportQueue();
+  pdx::Status<void> ImportQueue();
 
   // Sets up the queue with the given parameters.
-  void SetupQueue(size_t meta_size_bytes_, int id);
+  void SetupQueue(const QueueInfo& queue_info);
 
-  // Called by ProducerQueue::AddBuffer and ConsumerQueue::AddBuffer only. to
-  // register a buffer for epoll and internal bookkeeping.
-  int AddBuffer(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
+  // Register a buffer for management by the queue. Used by subclasses to add a
+  // buffer to internal bookkeeping.
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
+                              size_t slot);
 
-  // Called by ProducerQueue::DetachBuffer and ConsumerQueue::DetachBuffer only.
+  // Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
   // to deregister a buffer for epoll and internal bookkeeping.
-  virtual int DetachBuffer(size_t slot);
+  virtual pdx::Status<void> RemoveBuffer(size_t slot);
+
+  // Free all buffers that belongs to this queue. Can only be called from
+  // producer side.
+  virtual pdx::Status<void> FreeAllBuffers();
 
   // Dequeue a buffer from the free queue, blocking until one is available. The
   // timeout argument specifies the number of milliseconds that |Dequeue()| will
-  // block. Specifying a timeout of -1 causes |Dequeue()| to block indefinitely,
-  // while specifying a timeout equal to zero cause |Dequeue()| to return
+  // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
+  // while specifying a timeout equal to zero cause Dequeue() to return
   // immediately, even if no buffers are available.
   pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
-                                                        size_t* slot,
-                                                        void* meta,
-                                                        LocalHandle* fence);
+                                                        size_t* slot);
 
-  // Wait for buffers to be released and re-add them to the queue.
+  // Waits for buffers to become available and adds them to the available queue.
   bool WaitForBuffers(int timeout);
-  void HandleBufferEvent(size_t slot, int poll_events);
-  void HandleQueueEvent(int poll_events);
 
-  virtual int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                            LocalHandle* fence) = 0;
+  pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
+                                      int poll_events);
+  pdx::Status<void> HandleQueueEvent(int poll_events);
+
+  // Entry in the ring buffer of available buffers that stores related
+  // per-buffer data.
+  struct Entry {
+    Entry() : slot(0) {}
+    Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot,
+          uint64_t index)
+        : buffer(buffer), slot(slot), index(index) {}
+    Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
+          std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
+          size_t slot)
+        : buffer(buffer),
+          metadata(std::move(metadata)),
+          fence(std::move(fence)),
+          slot(slot) {}
+    Entry(Entry&&) = default;
+    Entry& operator=(Entry&&) = default;
+
+    std::shared_ptr<BufferHubBuffer> buffer;
+    std::unique_ptr<uint8_t[]> metadata;
+    pdx::LocalHandle fence;
+    size_t slot;
+    uint64_t index;
+  };
+
+  struct EntryComparator {
+    bool operator()(const Entry& lhs, const Entry& rhs) {
+      return lhs.index > rhs.index;
+    }
+  };
+
+  // Enqueues a buffer to the available list (Gained for producer or Acquireed
+  // for consumer).
+  pdx::Status<void> Enqueue(Entry entry);
 
   // Called when a buffer is allocated remotely.
-  virtual Status<void> OnBufferAllocated() { return {}; }
+  virtual pdx::Status<void> OnBufferAllocated() { return {}; }
 
-  // Data members to handle arbitrary metadata passed through BufferHub. It is
-  // fair to enforce that all buffers in the same queue share the same metadata
-  // type. |meta_size_| is used to store the size of metadata on queue creation;
-  // and |meta_buffer_tmp_| is allocated and resized to |meta_size_| on queue
-  // creation to be later used as temporary space so that we can avoid
-  // additional dynamic memory allocation in each |Enqueue| and |Dequeue| call.
-  size_t meta_size_;
-
-  // Here we intentionally choose |unique_ptr<uint8_t[]>| over vector<uint8_t>
-  // to disallow dynamic resizing for stability reasons.
-  std::unique_ptr<uint8_t[]> meta_buffer_tmp_;
+  // Size of the metadata that buffers in this queue cary.
+  size_t user_metadata_size_{0};
 
  private:
+  void Initialize();
+
+  // Special epoll data field indicating that the epoll event refers to the
+  // queue.
+  static constexpr int64_t kEpollQueueEventIndex = -1;
+
   static constexpr size_t kMaxEvents = 128;
 
-  // The |u64| data field of an epoll event is interpreted as int64_t:
+  // The u64 data field of an epoll event is interpreted as int64_t:
   // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
   // element of |buffers_| as a direct index;
   static bool is_buffer_event_index(int64_t index) {
@@ -168,102 +207,42 @@
            index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
   }
 
-  // When |index| == kEpollQueueEventIndex, it refers to the queue itself.
+  // When |index| == kEpollQueueEventIndex it refers to the queue itself.
   static bool is_queue_event_index(int64_t index) {
     return index == BufferHubQueue::kEpollQueueEventIndex;
   }
 
-  struct BufferInfo {
-    // A logical slot number that is assigned to a buffer at allocation time.
-    // The slot number remains unchanged during the entire life cycle of the
-    // buffer and should not be confused with the enqueue and dequeue order.
-    size_t slot;
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async_{false};
 
-    // A BufferHubBuffer client.
-    std::shared_ptr<BufferHubBuffer> buffer;
-
-    // Metadata associated with the buffer.
-    std::unique_ptr<uint8_t[]> metadata;
-
-    BufferInfo() : BufferInfo(-1, 0) {}
-
-    BufferInfo(size_t slot, size_t metadata_size)
-        : slot(slot),
-          buffer(nullptr),
-          metadata(metadata_size ? new uint8_t[metadata_size] : nullptr) {}
-
-    BufferInfo(BufferInfo&& other)
-        : slot(other.slot),
-          buffer(std::move(other.buffer)),
-          metadata(std::move(other.metadata)) {}
-
-    BufferInfo& operator=(BufferInfo&& other) {
-      slot = other.slot;
-      buffer = std::move(other.buffer);
-      metadata = std::move(other.metadata);
-      return *this;
-    }
-
-   private:
-    BufferInfo(const BufferInfo&) = delete;
-    void operator=(BufferInfo&) = delete;
-  };
-
-  // Default buffer width that can be set to override the buffer width when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Default buffer width that is set during ProducerQueue's creation.
   size_t default_width_{1};
 
-  // Default buffer height that can be set to override the buffer height when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Default buffer height that is set during ProducerQueue's creation.
   size_t default_height_{1};
 
-  // Default buffer format that can be set to override the buffer format when it
-  // isn't specified in AllocateBuffer.
-  int32_t default_format_{PIXEL_FORMAT_RGBA_8888};
+  // Default buffer format that is set during ProducerQueue's creation.
+  int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
 
-  // Buffer queue:
-  // |buffers_| tracks all |BufferHubBuffer|s created by this |BufferHubQueue|.
-  std::vector<std::shared_ptr<BufferHubBuffer>> buffers_;
+  // Tracks the buffers belonging to this queue. Buffers are stored according to
+  // "slot" in this vector. Each slot is a logical id of the buffer within this
+  // queue regardless of its queue position or presence in the ring buffer.
+  std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
 
-  // |epollhup_pending_| tracks whether a slot of |buffers_| get detached before
-  // its corresponding EPOLLHUP event got handled. This could happen as the
-  // following sequence:
-  // 1. Producer queue's client side allocates a new buffer (at slot 1).
-  // 2. Producer queue's client side replaces an existing buffer (at slot 0).
-  //    This is implemented by first detaching the buffer and then allocating a
-  //    new buffer.
-  // 3. During the same epoll_wait, Consumer queue's client side gets EPOLLIN
-  //    event on the queue which indicates a new buffer is available and the
-  //    EPOLLHUP event for slot 0. Consumer handles these two events in order.
-  // 4. Consumer client calls BufferHubRPC::ConsumerQueueImportBuffers and both
-  //    slot 0 and (the new) slot 1 buffer will be imported. During the import
-  //    of the buffer at slot 1, consumer client detaches the old buffer so that
-  //    the new buffer can be registered. At the same time
-  //    |epollhup_pending_[slot]| is marked to indicate that buffer at this slot
-  //    was detached prior to EPOLLHUP event.
-  // 5. Consumer client continues to handle the EPOLLHUP. Since
-  //    |epollhup_pending_[slot]| is marked as true, it can safely ignore the
-  //    event without detaching the newly allocated buffer at slot 1.
-  //
-  // In normal situations where the previously described sequence doesn't
-  // happen, an EPOLLHUP event should trigger a regular buffer detach.
-  std::vector<bool> epollhup_pending_;
+  // Buffers and related data that are available for dequeue.
+  // RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
+  std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
+      available_buffers_;
 
-  // |available_buffers_| uses |dvr::RingBuffer| to implementation queue
-  // sematics. When |Dequeue|, we pop the front element from
-  // |available_buffers_|, and  that buffer's reference count will decrease by
-  // one, while another reference in |buffers_| keeps the last reference to
-  // prevent the buffer from being deleted.
-  RingBuffer<BufferInfo> available_buffers_;
+  // Keeps track with how many buffers have been added into the queue.
+  size_t capacity_{0};
 
-  // Fences (acquire fence for consumer and release fence for consumer) , one
-  // for each buffer slot.
-  std::vector<LocalHandle> fences_;
-
-  // Keep track with how many buffers have been added into the queue.
-  size_t capacity_;
-
-  // Epoll fd used to wait for BufferHub events.
+  // Epoll fd used to manage buffer events.
   EpollFileDescriptor epoll_fd_;
 
   // Flag indicating that the other side hung up. For ProducerQueues this
@@ -273,7 +252,11 @@
   bool hung_up_{false};
 
   // Global id for the queue that is consistent across processes.
-  int id_;
+  int id_{-1};
+
+  // Buffer event callbacks
+  BufferAvailableCallback on_buffer_available_;
+  BufferRemovedCallback on_buffer_removed_;
 
   BufferHubQueue(const BufferHubQueue&) = delete;
   void operator=(BufferHubQueue&) = delete;
@@ -281,14 +264,6 @@
 
 class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
  public:
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create() {
-    return BASE::Create(sizeof(Meta));
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes) {
-    return BASE::Create(meta_size_bytes);
-  }
-
   // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
   // in |usage_clear_mask| will be automatically masked off. Note that
   // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
@@ -300,59 +275,67 @@
   // this will be rejected. Note that |usage_deny_set_mask| and
   // |usage_deny_clear_mask| shall not conflict with each other. Such
   // configuration will be treated as invalid input on creation.
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
-                                               uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(meta_size_bytes, usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
+  static std::unique_ptr<ProducerQueue> Create(
+      const ProducerQueueConfig& config, const UsagePolicy& usage) {
+    return BASE::Create(config, usage);
   }
 
-  // Import a |ProducerQueue| from a channel handle.
-  static std::unique_ptr<ProducerQueue> Import(LocalChannelHandle handle) {
+  // Import a ProducerQueue from a channel handle.
+  static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
     return BASE::Create(std::move(handle));
   }
 
   // Get a buffer producer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been allocated already. When no
-  // buffer has been imported before it returns |nullptr|; otherwise it returns
-  // a shared pointer to a |BufferProducer|.
+  // buffer has been imported before it returns nullptr; otherwise it returns
+  // a shared pointer to a BufferProducer.
   std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
     return std::static_pointer_cast<BufferProducer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
+  // Batch allocate buffers. Once allocated, producer buffers are automatically
+  // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
+  // state). Upon success, returns a list of slots for each buffer allocated.
+  pdx::Status<std::vector<size_t>> AllocateBuffers(
+      uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+      uint64_t usage, size_t buffer_count);
+
   // Allocate producer buffer to populate the queue. Once allocated, a producer
   // buffer is automatically enqueue'd into the ProducerQueue and available to
-  // use (i.e. in |Gain|'ed mode).
-  // Returns Zero on success and negative error code when buffer allocation
-  // fails.
-  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
-                     uint32_t format, uint64_t usage, size_t* out_slot);
+  // use (i.e. in GAINED state). Upon success, returns the slot number for the
+  // buffer allocated.
+  pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
+                                     uint32_t layer_count, uint32_t format,
+                                     uint64_t usage);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
-  // is available to use (i.e. in |Gain|'ed mode).
-  int AddBuffer(const std::shared_ptr<BufferProducer>& buf, size_t slot);
+  // is available to use (i.e. in GAINED state).
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+                              size_t slot);
 
-  // Detach producer buffer from the queue.
-  // Returns Zero on success and negative error code when buffer detach
-  // fails.
-  int DetachBuffer(size_t slot) override;
+  // Remove producer buffer from the queue.
+  pdx::Status<void> RemoveBuffer(size_t slot) override;
+
+  // Free all buffers on this producer queue.
+  pdx::Status<void> FreeAllBuffers() override {
+    return BufferHubQueue::FreeAllBuffers();
+  }
 
   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
   // and caller should call Post() once it's done writing to release the buffer
   // to the consumer side.
   pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
-      int timeout, size_t* slot, LocalHandle* release_fence);
+      int timeout, size_t* slot, pdx::LocalHandle* release_fence);
+  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+      int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
+      pdx::LocalHandle* release_fence);
+
+  // Enqueues a producer buffer in the queue.
+  pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+                            size_t slot, uint64_t index) {
+    return BufferHubQueue::Enqueue({buffer, slot, index});
+  }
 
  private:
   friend BASE;
@@ -360,29 +343,10 @@
   // Constructors are automatically exposed through ProducerQueue::Create(...)
   // static template methods inherited from ClientBase, which take the same
   // arguments as the constructors.
-  explicit ProducerQueue(size_t meta_size);
-  ProducerQueue(LocalChannelHandle handle);
-  ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
-                uint64_t usage_deny_clear_mask);
-
-  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                    LocalHandle* release_fence) override;
+  explicit ProducerQueue(pdx::LocalChannelHandle handle);
+  ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
 };
 
-// Explicit specializations of ProducerQueue::Create for void metadata type.
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>() {
-  return ProducerQueue::Create(0);
-}
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
-    uint32_t usage_set_mask, uint32_t usage_clear_mask,
-    uint32_t usage_deny_set_mask, uint32_t usage_deny_clear_mask) {
-  return ProducerQueue::Create(0, usage_set_mask, usage_clear_mask,
-                               usage_deny_set_mask, usage_deny_clear_mask);
-}
-
 class ConsumerQueue : public BufferHubQueue {
  public:
   // Get a buffer consumer. Note that the method doesn't check whether the
@@ -399,15 +363,14 @@
   // used to avoid participation in the buffer lifecycle by a consumer queue
   // that is only used to spawn other consumer queues, such as in an
   // intermediate service.
-  static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle,
-                                               bool ignore_on_import = false) {
+  static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle) {
     return std::unique_ptr<ConsumerQueue>(
-        new ConsumerQueue(std::move(handle), ignore_on_import));
+        new ConsumerQueue(std::move(handle)));
   }
 
   // Import newly created buffers from the service side.
   // Returns number of buffers successfully imported or an error.
-  Status<size_t> ImportBuffers();
+  pdx::Status<size_t> ImportBuffers();
 
   // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
   // mode, and caller should call Releasse() once it's done writing to release
@@ -417,37 +380,34 @@
   // when the buffer is orignally created.
   template <typename Meta>
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
-      int timeout, size_t* slot, Meta* meta, LocalHandle* acquire_fence) {
+      int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
-      int timeout, size_t* slot, LocalHandle* acquire_fence) {
+      int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
   }
 
   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
-      int timeout, size_t* slot, void* meta, size_t meta_size,
-      LocalHandle* acquire_fence);
+      int timeout, size_t* slot, void* meta, size_t user_metadata_size,
+      pdx::LocalHandle* acquire_fence);
+  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+      int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
+      pdx::LocalHandle* acquire_fence);
 
  private:
   friend BufferHubQueue;
 
-  ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import = false);
+  ConsumerQueue(pdx::LocalChannelHandle handle);
 
   // Add a consumer buffer to populate the queue. Once added, a consumer buffer
   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
   // will catch the |Post| and |Acquire| the buffer to make it available for
   // consumer.
-  int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
+  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+                              size_t slot);
 
-  int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
-                    LocalHandle* acquire_fence) override;
-
-  Status<void> OnBufferAllocated() override;
-
-  // Flag indicating that imported (consumer) buffers should be ignored when
-  // imported to avoid participating in the buffer ownership flow.
-  bool ignore_on_import_;
+  pdx::Status<void> OnBufferAllocated() override;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 7890176..7ed55fb 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -42,7 +42,8 @@
 
   // See |IGraphicBufferProducer::dequeueBuffer|
   status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
-                         uint32_t height, PixelFormat format, uint32_t usage,
+                         uint32_t height, PixelFormat format, uint64_t usage,
+                         uint64_t* outBufferAge,
                          FrameEventHistoryDelta* outTimestamps) override;
 
   // See |IGraphicBufferProducer::detachBuffer|
@@ -80,7 +81,7 @@
 
   // See |IGraphicBufferProducer::allocateBuffers|
   void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
-                       uint32_t usage) override;
+                       uint64_t usage) override;
 
   // See |IGraphicBufferProducer::allowAllocation|
   status_t allowAllocation(bool allow) override;
@@ -111,6 +112,9 @@
   // See |IGraphicBufferProducer::getUniqueId|
   status_t getUniqueId(uint64_t* out_id) const override;
 
+  // See |IGraphicBufferProducer::getConsumerUsage|
+  status_t getConsumerUsage(uint64_t* out_usage) const override;
+
  private:
   using LocalHandle = pdx::LocalHandle;
 
@@ -131,6 +135,10 @@
   // Remove a buffer via BufferHubRPC.
   status_t RemoveBuffer(size_t slot);
 
+  // Free all buffers which are owned by the prodcuer. Note that if graphic
+  // buffers are acquired by the consumer, we can't .
+  status_t FreeAllBuffers();
+
   // Concreate implementation backed by BufferHubBuffer.
   std::shared_ptr<ProducerQueue> queue_;
 
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index 865573c..8bd1ef1 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -1,4 +1,7 @@
 
+header_libraries = [
+    "libdvr_headers",
+]
 
 shared_libraries = [
     "libbase",
@@ -21,6 +24,7 @@
 
 cc_test {
     srcs: ["buffer_hub_queue-test.cpp"],
+    header_libs: header_libraries,
     static_libs: static_libraries,
     shared_libs: shared_libraries,
     cflags: [
@@ -35,6 +39,7 @@
 
 cc_test {
     srcs: ["buffer_hub_queue_producer-test.cpp"],
+    header_libs: header_libraries,
     static_libs: static_libraries,
     shared_libs: shared_libraries,
     cflags: [
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index fe0b12a..8a72531 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -3,9 +3,14 @@
 #include <private/dvr/buffer_hub_queue_client.h>
 
 #include <gtest/gtest.h>
+#include <poll.h>
+#include <sys/eventfd.h>
 
 #include <vector>
 
+// Enable/disable debug logging.
+#define TRACE 0
+
 namespace android {
 namespace dvr {
 
@@ -13,22 +18,17 @@
 
 namespace {
 
-constexpr int kBufferWidth = 100;
-constexpr int kBufferHeight = 1;
-constexpr int kBufferLayerCount = 1;
-constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
-constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+constexpr uint32_t kBufferWidth = 100;
+constexpr uint32_t kBufferHeight = 1;
+constexpr uint32_t kBufferLayerCount = 1;
+constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
 
 class BufferHubQueueTest : public ::testing::Test {
  public:
-  template <typename Meta>
-  bool CreateProducerQueue(uint64_t usage_set_mask = 0,
-                           uint64_t usage_clear_mask = 0,
-                           uint64_t usage_deny_set_mask = 0,
-                           uint64_t usage_deny_clear_mask = 0) {
-    producer_queue_ =
-        ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
-                                    usage_deny_set_mask, usage_deny_clear_mask);
+  bool CreateProducerQueue(const ProducerQueueConfig& config,
+                           const UsagePolicy& usage) {
+    producer_queue_ = ProducerQueue::Create(config, usage);
     return producer_queue_ != nullptr;
   }
 
@@ -41,26 +41,42 @@
     }
   }
 
-  template <typename Meta>
-  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
-                    int usage_deny_set_mask = 0,
-                    int usage_deny_clear_mask = 0) {
-    return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
-                                     usage_deny_set_mask,
-                                     usage_deny_clear_mask) &&
-           CreateConsumerQueue();
+  bool CreateQueues(const ProducerQueueConfig& config,
+                    const UsagePolicy& usage) {
+    return CreateProducerQueue(config, usage) && CreateConsumerQueue();
   }
 
-  void AllocateBuffer() {
+  void AllocateBuffer(size_t* slot_out = nullptr) {
     // Create producer buffer.
-    size_t slot;
-    int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                              kBufferLayerCount, kBufferFormat,
-                                              kBufferUsage, &slot);
-    ASSERT_EQ(ret, 0);
+    auto status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                                  kBufferLayerCount,
+                                                  kBufferFormat, kBufferUsage);
+
+    ASSERT_TRUE(status.ok());
+    size_t slot = status.take();
+    if (slot_out)
+      *slot_out = slot;
+  }
+
+  bool WaitAndHandleOnce(BufferHubQueue* queue, int timeout_ms) {
+    pollfd pfd{queue->queue_fd(), POLLIN, 0};
+    int ret;
+    do {
+      ret = poll(&pfd, 1, timeout_ms);
+    } while (ret == -1 && errno == EINTR);
+
+    if (ret < 0) {
+      ALOGW("Failed to poll queue %d's event fd, error: %s.", queue->id(),
+            strerror(errno));
+      return false;
+    } else if (ret == 0) {
+      return false;
+    }
+    return queue->HandleQueueEvents();
   }
 
  protected:
+  ProducerQueueConfigBuilder config_builder_;
   std::unique_ptr<ProducerQueue> producer_queue_;
   std::unique_ptr<ConsumerQueue> consumer_queue_;
 };
@@ -68,7 +84,8 @@
 TEST_F(BufferHubQueueTest, TestDequeue) {
   const size_t nb_dequeue_times = 16;
 
-  ASSERT_TRUE(CreateQueues<size_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
+                           UsagePolicy{}));
 
   // Allocate only one buffer.
   AllocateBuffer();
@@ -77,7 +94,7 @@
   for (size_t i = 0; i < nb_dequeue_times; i++) {
     size_t slot;
     LocalHandle fence;
-    auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
     ASSERT_TRUE(p1_status.ok());
     auto p1 = p1_status.take();
     ASSERT_NE(nullptr, p1);
@@ -94,13 +111,14 @@
 }
 
 TEST_F(BufferHubQueueTest, TestProducerConsumer) {
-  const size_t nb_buffer = 16;
+  const size_t kBufferCount = 16;
   size_t slot;
   uint64_t seq;
 
-  ASSERT_TRUE(CreateQueues<uint64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+                           UsagePolicy{}));
 
-  for (size_t i = 0; i < nb_buffer; i++) {
+  for (size_t i = 0; i < kBufferCount; i++) {
     AllocateBuffer();
 
     // Producer queue has all the available buffers on initialize.
@@ -114,41 +132,151 @@
     // Dequeue returns timeout since no buffer is ready to consumer, but
     // this implicitly triggers buffer import and bump up |capacity|.
     LocalHandle fence;
-    auto status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+    auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
     ASSERT_FALSE(status.ok());
     ASSERT_EQ(ETIMEDOUT, status.error());
     ASSERT_EQ(consumer_queue_->capacity(), i + 1);
   }
 
-  for (size_t i = 0; i < nb_buffer; i++) {
+  // Use eventfd as a stand-in for a fence.
+  LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+
+  for (size_t i = 0; i < kBufferCount; i++) {
     LocalHandle fence;
-    // First time, there is no buffer available to dequeue.
-    auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+
+    // First time there is no buffer available to dequeue.
+    auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
     ASSERT_FALSE(consumer_status.ok());
     ASSERT_EQ(ETIMEDOUT, consumer_status.error());
 
-    // Make sure Producer buffer is Post()'ed so that it's ready to Accquire
+    // Make sure Producer buffer is POSTED so that it's ready to Accquire
     // in the consumer's Dequeue() function.
-    auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+    auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
     ASSERT_TRUE(producer_status.ok());
     auto producer = producer_status.take();
     ASSERT_NE(nullptr, producer);
 
     uint64_t seq_in = static_cast<uint64_t>(i);
-    ASSERT_EQ(producer->Post({}, &seq_in, sizeof(seq_in)), 0);
+    ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
 
-    // Second time, the just |Post()|'ed buffer should be dequeued.
+    // Second time the just the POSTED buffer should be dequeued.
     uint64_t seq_out = 0;
-    consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
+    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
     ASSERT_TRUE(consumer_status.ok());
+    EXPECT_TRUE(fence.IsValid());
+
     auto consumer = consumer_status.take();
     ASSERT_NE(nullptr, consumer);
     ASSERT_EQ(seq_in, seq_out);
   }
 }
 
+TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+
+  // Allocate buffers.
+  const size_t kBufferCount = 4u;
+  for (size_t i = 0; i < kBufferCount; i++) {
+    AllocateBuffer();
+  }
+  ASSERT_EQ(kBufferCount, producer_queue_->count());
+  ASSERT_EQ(kBufferCount, producer_queue_->capacity());
+
+  consumer_queue_ = producer_queue_->CreateConsumerQueue();
+  ASSERT_NE(nullptr, consumer_queue_);
+
+  // Check that buffers are correctly imported on construction.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_EQ(0u, consumer_queue_->count());
+
+  // Dequeue all the buffers and keep track of them in an array. This prevents
+  // the producer queue ring buffer ref counts from interfering with the tests.
+  struct Entry {
+    std::shared_ptr<BufferProducer> buffer;
+    LocalHandle fence;
+    size_t slot;
+  };
+  std::array<Entry, kBufferCount> buffers;
+
+  for (size_t i = 0; i < kBufferCount; i++) {
+    Entry* entry = &buffers[i];
+    auto producer_status = producer_queue_->Dequeue(
+        /*timeout_ms=*/100, &entry->slot, &entry->fence);
+    ASSERT_TRUE(producer_status.ok());
+    entry->buffer = producer_status.take();
+    ASSERT_NE(nullptr, entry->buffer);
+  }
+
+  // Remove a buffer and make sure both queues reflect the change.
+  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[0].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+  // As long as the removed buffer is still alive the consumer queue won't know
+  // its gone.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Release the removed buffer.
+  buffers[0].buffer = nullptr;
+
+  // Now the consumer queue should know it's gone.
+  EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
+  ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+
+  // Allocate a new buffer. This should take the first empty slot.
+  size_t slot;
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[0].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  // The consumer queue should pick up the new buffer.
+  EXPECT_EQ(kBufferCount - 1, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Remove and allocate a buffer.
+  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[1].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+  buffers[1].buffer = nullptr;
+
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[1].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  // The consumer queue should pick up the new buffer but the count shouldn't
+  // change.
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Remove and allocate a buffer, but don't free the buffer right away.
+  ASSERT_TRUE(producer_queue_->RemoveBuffer(buffers[2].slot));
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->capacity());
+
+  AllocateBuffer(&slot);
+  ALOGE_IF(TRACE, "ALLOCATE %zu", slot);
+  EXPECT_EQ(buffers[2].slot, slot);
+  EXPECT_EQ(kBufferCount, producer_queue_->capacity());
+
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+
+  // Release the producer buffer to trigger a POLLHUP event for an already
+  // removed buffer.
+  buffers[2].buffer = nullptr;
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+  EXPECT_FALSE(consumer_queue_->HandleQueueEvents());
+  EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+}
+
 TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
-  ASSERT_TRUE(CreateProducerQueue<void>());
+  // ProducerConfigureBuilder doesn't set Metadata{size}, which means there
+  // is no metadata associated with this BufferQueue's buffer.
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate buffers.
   const size_t kBufferCount = 4u;
@@ -161,17 +289,20 @@
   auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
   ASSERT_NE(nullptr, silent_queue);
 
-  // Check that buffers are correctly imported on construction.
-  EXPECT_EQ(kBufferCount, silent_queue->capacity());
+  // Check that silent queue doesn't import buffers on creation.
+  EXPECT_EQ(0, silent_queue->capacity());
 
   // Dequeue and post a buffer.
   size_t slot;
   LocalHandle fence;
-  auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+  auto producer_status =
+      producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
   ASSERT_TRUE(producer_status.ok());
   auto producer_buffer = producer_status.take();
   ASSERT_NE(nullptr, producer_buffer);
   ASSERT_EQ(0, producer_buffer->Post<void>({}));
+  // After post, check the number of remaining available buffers.
+  EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
 
   // Currently we expect no buffer to be available prior to calling
   // WaitForBuffers/HandleQueueEvents.
@@ -189,23 +320,30 @@
   EXPECT_EQ(1u, consumer_queue_->count());
 
   // Reclaim released/ignored buffers.
-  producer_queue_->HandleQueueEvents();
+  ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+
+  usleep(10000);
+  WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
   ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
 
   // Post another buffer.
-  producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+  producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
   ASSERT_TRUE(producer_status.ok());
   producer_buffer = producer_status.take();
   ASSERT_NE(nullptr, producer_buffer);
   ASSERT_EQ(0, producer_buffer->Post<void>({}));
 
   // Verify that the consumer queue receives it.
-  EXPECT_EQ(1u, consumer_queue_->count());
-  EXPECT_TRUE(consumer_queue_->HandleQueueEvents());
-  EXPECT_EQ(2u, consumer_queue_->count());
+  size_t consumer_queue_count = consumer_queue_->count();
+  WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
+  EXPECT_LT(consumer_queue_count, consumer_queue_->count());
+
+  // Save the current consumer queue buffer count to compare after the dequeue.
+  consumer_queue_count = consumer_queue_->count();
 
   // Dequeue and acquire/release (discard) buffers on the consumer end.
-  auto consumer_status = consumer_queue_->Dequeue(0, &slot, &fence);
+  auto consumer_status =
+      consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
   ASSERT_TRUE(consumer_status.ok());
   auto consumer_buffer = consumer_status.take();
   ASSERT_NE(nullptr, consumer_buffer);
@@ -213,7 +351,7 @@
 
   // Buffer should be returned to the producer queue without being handled by
   // the silent consumer queue.
-  EXPECT_EQ(1u, consumer_queue_->count());
+  EXPECT_GT(consumer_queue_count, consumer_queue_->count());
   EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
   EXPECT_TRUE(producer_queue_->HandleQueueEvents());
   EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
@@ -226,7 +364,9 @@
 };
 
 TEST_F(BufferHubQueueTest, TestMetadata) {
-  ASSERT_TRUE(CreateQueues<TestMetadata>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   std::vector<TestMetadata> ms = {
@@ -235,13 +375,13 @@
   for (auto mi : ms) {
     size_t slot;
     LocalHandle fence;
-    auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+    auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
     ASSERT_TRUE(p1_status.ok());
     auto p1 = p1_status.take();
     ASSERT_NE(nullptr, p1);
     ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
     TestMetadata mo;
-    auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+    auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
     ASSERT_TRUE(c1_status.ok());
     auto c1 = c1_status.take();
     ASSERT_EQ(mi.a, mo.a);
@@ -252,13 +392,15 @@
 }
 
 TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   int64_t mi = 3;
   size_t slot;
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
@@ -266,41 +408,43 @@
 
   int32_t mo;
   // Acquire a buffer with mismatched metadata is not OK.
-  auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
   ASSERT_FALSE(c1_status.ok());
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
   AllocateBuffer();
 
   size_t slot;
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
 
   int64_t mo;
-  producer_queue_->Enqueue(p1, slot);
-  auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+  producer_queue_->Enqueue(p1, slot, 0ULL);
+  auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
   ASSERT_FALSE(c1_status.ok());
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
 
   size_t s1;
   AllocateBuffer();
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(0, &s1, &fence);
+  auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_NE(nullptr, p1);
 
   // producer queue is exhausted
   size_t s2;
-  auto p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+  auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
   ASSERT_FALSE(p2_status.ok());
   ASSERT_EQ(ETIMEDOUT, p2_status.error());
 
@@ -310,7 +454,7 @@
   ASSERT_EQ(producer_queue_->capacity(), 2U);
 
   // now we can dequeue again
-  p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+  p2_status = producer_queue_->Dequeue(100, &s2, &fence);
   ASSERT_TRUE(p2_status.ok());
   auto p2 = p2_status.take();
   ASSERT_NE(nullptr, p2);
@@ -325,7 +469,7 @@
   int64_t seq = 1;
   ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
   size_t cs1, cs2;
-  auto c1_status = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
+  auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
   ASSERT_TRUE(c1_status.ok());
   auto c1 = c1_status.take();
   ASSERT_NE(nullptr, c1);
@@ -334,7 +478,7 @@
   ASSERT_EQ(cs1, s1);
 
   ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
-  auto c2_status = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
+  auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
   ASSERT_TRUE(c2_status.ok());
   auto c2 = c2_status.take();
   ASSERT_NE(nullptr, c2);
@@ -343,17 +487,18 @@
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{set_mask, 0, 0, 0}));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
-  size_t slot;
-  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                            kBufferFormat, kBufferLayerCount,
-                                            kBufferUsage & ~set_mask, &slot);
-  ASSERT_EQ(0, ret);
+  auto status = producer_queue_->AllocateBuffer(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage & ~set_mask);
+  ASSERT_TRUE(status.ok());
 
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  size_t slot;
+  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_EQ(p1->usage() & set_mask, set_mask);
@@ -361,17 +506,18 @@
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
   const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, clear_mask, 0, 0}));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
-  size_t slot;
-  int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                            kBufferLayerCount, kBufferFormat,
-                                            kBufferUsage | clear_mask, &slot);
-  ASSERT_EQ(0, ret);
+  auto status = producer_queue_->AllocateBuffer(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage | clear_mask);
+  ASSERT_TRUE(status.ok());
 
   LocalHandle fence;
-  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+  size_t slot;
+  auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
   ASSERT_TRUE(p1_status.ok());
   auto p1 = p1_status.take();
   ASSERT_EQ(0u, p1->usage() & clear_mask);
@@ -379,40 +525,159 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
   const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, deny_set_mask, 0}));
 
   // Now that |deny_set_mask| is illegal, allocation without those bits should
   // be able to succeed.
-  size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
+  auto status = producer_queue_->AllocateBuffer(
       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
-      kBufferUsage & ~deny_set_mask, &slot);
-  ASSERT_EQ(ret, 0);
+      kBufferUsage & ~deny_set_mask);
+  ASSERT_TRUE(status.ok());
 
   // While allocation with those bits should fail.
-  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                        kBufferLayerCount, kBufferFormat,
-                                        kBufferUsage | deny_set_mask, &slot);
-  ASSERT_EQ(ret, -EINVAL);
+  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                           kBufferLayerCount, kBufferFormat,
+                                           kBufferUsage | deny_set_mask);
+  ASSERT_FALSE(status.ok());
+  ASSERT_EQ(EINVAL, status.error());
 }
 
 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
   const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, 0, deny_clear_mask}));
 
   // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
   // mandatory), allocation with those bits should be able to succeed.
-  size_t slot;
-  int ret = producer_queue_->AllocateBuffer(
+  auto status = producer_queue_->AllocateBuffer(
       kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
-      kBufferUsage | deny_clear_mask, &slot);
-  ASSERT_EQ(ret, 0);
+      kBufferUsage | deny_clear_mask);
+  ASSERT_TRUE(status.ok());
 
   // While allocation without those bits should fail.
-  ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
-                                        kBufferLayerCount, kBufferFormat,
-                                        kBufferUsage & ~deny_clear_mask, &slot);
-  ASSERT_EQ(ret, -EINVAL);
+  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+                                           kBufferLayerCount, kBufferFormat,
+                                           kBufferUsage & ~deny_clear_mask);
+  ASSERT_FALSE(status.ok());
+  ASSERT_EQ(EINVAL, status.error());
+}
+
+TEST_F(BufferHubQueueTest, TestQueueInfo) {
+  static const bool kIsAsync = true;
+  ASSERT_TRUE(CreateQueues(config_builder_.SetIsAsync(kIsAsync)
+                               .SetDefaultWidth(kBufferWidth)
+                               .SetDefaultHeight(kBufferHeight)
+                               .SetDefaultFormat(kBufferFormat)
+                               .Build(),
+                           UsagePolicy{}));
+
+  EXPECT_EQ(producer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(producer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(producer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(producer_queue_->is_async(), kIsAsync);
+
+  EXPECT_EQ(consumer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(consumer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(consumer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(consumer_queue_->is_async(), kIsAsync);
+}
+
+TEST_F(BufferHubQueueTest, TestFreeAllBuffers) {
+  constexpr size_t kBufferCount = 2;
+
+#define CHECK_NO_BUFFER_THEN_ALLOCATE(num_buffers)  \
+  EXPECT_EQ(consumer_queue_->count(), 0U);          \
+  EXPECT_EQ(consumer_queue_->capacity(), 0U);       \
+  EXPECT_EQ(producer_queue_->count(), 0U);          \
+  EXPECT_EQ(producer_queue_->capacity(), 0U);       \
+  for (size_t i = 0; i < num_buffers; i++) {        \
+    AllocateBuffer();                               \
+  }                                                 \
+  EXPECT_EQ(producer_queue_->count(), num_buffers); \
+  EXPECT_EQ(producer_queue_->capacity(), num_buffers);
+
+  size_t slot;
+  uint64_t seq;
+  LocalHandle fence;
+  pdx::Status<void> status;
+  pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
+  pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
+  std::shared_ptr<BufferConsumer> consumer_buffer;
+  std::shared_ptr<BufferProducer> producer_buffer;
+
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+                           UsagePolicy{}));
+
+  // Free all buffers when buffers are avaible for dequeue.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // Free all buffers when one buffer is dequeued.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+  ASSERT_TRUE(producer_status.ok());
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // Free all buffers when all buffers are dequeued.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  for (size_t i = 0; i < kBufferCount; i++) {
+    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    ASSERT_TRUE(producer_status.ok());
+  }
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // Free all buffers when one buffer is posted.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+  ASSERT_TRUE(producer_status.ok());
+  producer_buffer = producer_status.take();
+  ASSERT_NE(nullptr, producer_buffer);
+  ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // Free all buffers when all buffers are posted.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  for (size_t i = 0; i < kBufferCount; i++) {
+    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    ASSERT_TRUE(producer_status.ok());
+    producer_buffer = producer_status.take();
+    ASSERT_NE(nullptr, producer_buffer);
+    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+  }
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // Free all buffers when all buffers are acquired.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+  for (size_t i = 0; i < kBufferCount; i++) {
+    producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+    ASSERT_TRUE(producer_status.ok());
+    producer_buffer = producer_status.take();
+    ASSERT_NE(nullptr, producer_buffer);
+    ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+    consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+    ASSERT_TRUE(consumer_status.ok());
+  }
+
+  status = producer_queue_->FreeAllBuffers();
+  EXPECT_TRUE(status.ok());
+
+  // In addition to FreeAllBuffers() from the queue, it is also required to
+  // delete all references to the ProducerBuffer (i.e. the PDX client).
+  producer_buffer = nullptr;
+
+  // Crank consumer queue events to pickup EPOLLHUP events on the queue.
+  consumer_queue_->HandleQueueEvents();
+
+  // One last check.
+  CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
+
+#undef CHECK_NO_BUFFER_THEN_ALLOCATE
 }
 
 }  // namespace
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 2b6239f..28cd63a 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -117,9 +117,9 @@
     ASSERT_NE(nullptr, outSlot);
     ASSERT_NE(nullptr, outFence);
 
-    int ret = mProducer->dequeueBuffer(outSlot, outFence, kDefaultWidth,
-                                       kDefaultHeight, kDefaultFormat,
-                                       kTestProducerUsageBits, nullptr);
+    int ret = mProducer->dequeueBuffer(
+        outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat,
+        kTestProducerUsageBits, nullptr, nullptr);
     // BUFFER_NEEDS_REALLOCATION can be either on or off.
     ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
 
@@ -192,7 +192,7 @@
   EXPECT_EQ(NO_ERROR,
             mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &value));
   EXPECT_LE(0, value);
-  EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, static_cast<size_t>(value));
+  EXPECT_GE(BufferQueueDefs::NUM_BUFFER_SLOTS, value);
 
   EXPECT_EQ(NO_ERROR,
             mProducer->query(NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value));
@@ -440,9 +440,10 @@
   sp<Fence> fence;
   for (int i = 0; i < 2; i++) {
     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                      (mProducer->dequeueBuffer(
-                          &slot, &fence, kDefaultWidth, kDefaultHeight,
-                          kDefaultFormat, kTestProducerUsageBits, nullptr)))
+                      (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
+                                                kDefaultHeight, kDefaultFormat,
+                                                kTestProducerUsageBits,
+                                                nullptr, nullptr)))
         << "slot: " << slot;
   }
 
@@ -458,7 +459,8 @@
 
   ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
                                               kDefaultHeight, kDefaultFormat,
-                                              kTestProducerUsageBits, nullptr));
+                                              kTestProducerUsageBits,
+                                              nullptr, nullptr));
 }
 
 TEST_F(BufferHubQueueProducerTest,
@@ -506,6 +508,44 @@
   ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, Fence::NO_FENCE));
 }
 
+TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
+  int slot = -1;
+  sp<GraphicBuffer> buffer;
+  IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+  IGraphicBufferProducer::QueueBufferOutput output;
+
+  EXPECT_NO_FATAL_FAILURE(ConnectProducer());
+
+  constexpr int maxDequeuedBuffers = 1;
+  int minUndequeuedBuffers;
+  EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                                       &minUndequeuedBuffers));
+  EXPECT_EQ(NO_ERROR, mProducer->setAsyncMode(false));
+  EXPECT_EQ(NO_ERROR, mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers));
+
+  int maxCapacity = maxDequeuedBuffers + minUndequeuedBuffers;
+
+  // Dequeue, request, and queue all buffers.
+  for (int i = 0; i < maxCapacity; i++) {
+    EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+    EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+    EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
+  }
+
+  // Disconnect then reconnect.
+  EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+  EXPECT_NO_FATAL_FAILURE(ConnectProducer());
+
+  // Dequeue, request, and queue all buffers.
+  for (int i = 0; i < maxCapacity; i++) {
+    EXPECT_NO_FATAL_FAILURE(DequeueBuffer(&slot));
+    EXPECT_EQ(NO_ERROR, mProducer->requestBuffer(slot, &buffer));
+    EXPECT_EQ(NO_ERROR, mProducer->queueBuffer(slot, input, &output));
+  }
+
+  EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index d90521a..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -17,6 +17,7 @@
     "display_manager_client.cpp",
     "display_protocol.cpp",
     "vsync_client.cpp",
+    "shared_buffer_helpers.cpp",
 ]
 
 localIncludeFiles = [
@@ -39,12 +40,13 @@
     "libdvrcommon",
     "libbufferhubqueue",
     "libbufferhub",
-    "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
 headerLibraries = [
     "vulkan_headers",
+    "libdvr_headers",
 ]
 
 cc_library {
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 935ca2e..442c82d 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -104,9 +104,16 @@
   return {};
 }
 
-Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
+    uint32_t width, uint32_t height, uint32_t format, size_t metadata_size) {
   ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
-  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
+  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
+      ProducerQueueConfigBuilder()
+          .SetDefaultWidth(width)
+          .SetDefaultHeight(height)
+          .SetDefaultFormat(format)
+          .SetMetadataSize(metadata_size)
+          .Build());
   if (!status) {
     ALOGE("Surface::CreateQueue: Failed to create queue: %s",
           status.GetErrorMessage().c_str());
@@ -124,32 +131,24 @@
 
 Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
     uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
-    uint64_t usage, size_t capacity) {
+    uint64_t usage, size_t capacity, size_t metadata_size) {
   ALOGD_IF(TRACE,
            "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
            "usage=%" PRIx64 " capacity=%zu",
            width, height, layer_count, format, usage, capacity);
-  auto status = CreateQueue();
+  auto status = CreateQueue(width, height, format, metadata_size);
   if (!status)
     return status.error_status();
 
   auto producer_queue = status.take();
 
   ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
-  for (size_t i = 0; i < capacity; i++) {
-    size_t slot;
-    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
-                                                   format, usage, &slot);
-    if (ret < 0) {
-      ALOGE(
-          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
-          producer_queue->id(), strerror(-ret));
-      return ErrorStatus(ENOMEM);
-    }
-    ALOGD_IF(
-        TRACE,
-        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
-        slot, capacity);
+  auto allocate_status = producer_queue->AllocateBuffers(
+      width, height, layer_count, format, usage, capacity);
+  if (!allocate_status) {
+    ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
+          producer_queue->id(), allocate_status.GetErrorMessage().c_str());
+    return allocate_status.error_status();
   }
 
   return {std::move(producer_queue)};
@@ -167,6 +166,19 @@
   return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
 }
 
+Status<std::string> DisplayClient::GetConfigurationData(
+    ConfigFileType config_type) {
+  auto status =
+      InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
+  if (!status && status.error() != ENOENT) {
+    ALOGE(
+        "DisplayClient::GetConfigurationData: Unable to get"
+        "configuration data. Error: %s",
+        status.GetErrorMessage().c_str());
+  }
+  return status;
+}
+
 Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
     const SurfaceAttributes& attributes) {
   int error;
@@ -176,14 +188,15 @@
     return ErrorStatus(error);
 }
 
-Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
-    const std::string& name) {
-  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
+pdx::Status<std::unique_ptr<IonBuffer>> DisplayClient::SetupGlobalBuffer(
+    DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+  auto status =
+      InvokeRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(key, size, usage);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
-        "error=%s",
-        name.c_str(), status.GetErrorMessage().c_str());
+        "DisplayClient::SetupGlobalBuffer: Failed to create the global buffer "
+        "%s",
+        status.GetErrorMessage().c_str());
     return status.error_status();
   }
 
@@ -192,9 +205,44 @@
   const int ret = native_buffer_handle.Import(ion_buffer.get());
   if (ret < 0) {
     ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
-        "name=%s; error=%s",
-        name.c_str(), strerror(-ret));
+        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
+        "key=%d; error=%s",
+        key, strerror(-ret));
+    return ErrorStatus(-ret);
+  }
+
+  return {std::move(ion_buffer)};
+}
+
+pdx::Status<void> DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
+  auto status = InvokeRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(key);
+  if (!status) {
+    ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s",
+          status.GetErrorMessage().c_str());
+  }
+
+  return status;
+}
+
+Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
+    DvrGlobalBufferKey key) {
+  auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
+  if (!status) {
+    ALOGE(
+        "DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
+        "error=%s",
+        key, status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  auto native_buffer_handle = status.take();
+  const int ret = native_buffer_handle.Import(ion_buffer.get());
+  if (ret < 0) {
+    ALOGE(
+        "DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
+        "key=%d; error=%s",
+        key, strerror(-ret));
     return ErrorStatus(-ret);
   }
 
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
index 82dacf7..974c231 100644
--- a/libs/vr/libdisplay/display_manager_client.cpp
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -32,32 +32,6 @@
   return status;
 }
 
-pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupNamedBuffer(
-    const std::string& name, size_t size, uint64_t usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
-      name, size, usage);
-  if (!status) {
-    ALOGE(
-        "DisplayManagerClient::SetupPoseBuffer: Failed to create the named "
-        "buffer %s",
-        status.GetErrorMessage().c_str());
-    return status.error_status();
-  }
-
-  auto ion_buffer = std::make_unique<IonBuffer>();
-  auto native_buffer_handle = status.take();
-  const int ret = native_buffer_handle.Import(ion_buffer.get());
-  if (ret < 0) {
-    ALOGE(
-        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
-        "name=%s; error=%s",
-        name.c_str(), strerror(-ret));
-    return ErrorStatus(-ret);
-  }
-
-  return {std::move(ion_buffer)};
-}
-
 pdx::Status<std::unique_ptr<ConsumerQueue>>
 DisplayManagerClient::GetSurfaceQueue(int surface_id, int queue_id) {
   auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 7a7f670..caf3182 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -1,6 +1,7 @@
 #ifndef ANDROID_DVR_DISPLAY_CLIENT_H_
 #define ANDROID_DVR_DISPLAY_CLIENT_H_
 
+#include <dvr/dvr_api.h>
 #include <hardware/hwcomposer.h>
 #include <pdx/client.h>
 #include <pdx/file_handle.h>
@@ -36,7 +37,10 @@
   pdx::Status<void> SetAttributes(const SurfaceAttributes& attributes);
 
   // Creates an empty queue.
-  pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue();
+  pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue(uint32_t width,
+                                                          uint32_t height,
+                                                          uint32_t format,
+                                                          size_t metadata_size);
 
   // Creates a queue and populates it with |capacity| buffers of the specified
   // parameters.
@@ -45,7 +49,8 @@
                                                           uint32_t layer_count,
                                                           uint32_t format,
                                                           uint64_t usage,
-                                                          size_t capacity);
+                                                          size_t capacity,
+                                                          size_t metadata_size);
 
  private:
   friend BASE;
@@ -67,8 +72,12 @@
 class DisplayClient : public pdx::ClientBase<DisplayClient> {
  public:
   pdx::Status<Metrics> GetDisplayMetrics();
-  pdx::Status<std::unique_ptr<IonBuffer>> GetNamedBuffer(
-      const std::string& name);
+  pdx::Status<std::string> GetConfigurationData(ConfigFileType config_type);
+  pdx::Status<std::unique_ptr<IonBuffer>> SetupGlobalBuffer(
+      DvrGlobalBufferKey key, size_t size, uint64_t usage);
+  pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key);
+  pdx::Status<std::unique_ptr<IonBuffer>> GetGlobalBuffer(
+      DvrGlobalBufferKey key);
   pdx::Status<std::unique_ptr<Surface>> CreateSurface(
       const SurfaceAttributes& attributes);
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
index fea8415..45aef51 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -21,8 +21,6 @@
   ~DisplayManagerClient() override;
 
   pdx::Status<std::vector<SurfaceState>> GetSurfaceState();
-  pdx::Status<std::unique_ptr<IonBuffer>> SetupNamedBuffer(
-      const std::string& name, size_t size, uint64_t usage);
   pdx::Status<std::unique_ptr<ConsumerQueue>> GetSurfaceQueue(int surface_id,
                                                               int queue_id);
 
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index f34d61f..eff50ba 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -8,6 +8,8 @@
 
 #include <dvr/dvr_display_types.h>
 
+#include <dvr/dvr_api.h>
+#include <pdx/rpc/buffer_wrapper.h>
 #include <pdx/rpc/remote_method.h>
 #include <pdx/rpc/serializable.h>
 #include <pdx/rpc/variant.h>
@@ -184,6 +186,12 @@
   PDX_SERIALIZABLE_MEMBERS(SurfaceInfo, surface_id, visible, z_order);
 };
 
+enum class ConfigFileType : uint32_t {
+  kLensMetrics,
+  kDeviceMetrics,
+  kDeviceConfiguration
+};
+
 struct DisplayProtocol {
   // Service path.
   static constexpr char kClientPath[] = "system/vr/display/client";
@@ -191,7 +199,10 @@
   // Op codes.
   enum {
     kOpGetMetrics = 0,
-    kOpGetNamedBuffer,
+    kOpGetConfigurationData,
+    kOpSetupGlobalBuffer,
+    kOpDeleteGlobalBuffer,
+    kOpGetGlobalBuffer,
     kOpIsVrAppRunning,
     kOpCreateSurface,
     kOpGetSurfaceInfo,
@@ -205,14 +216,22 @@
 
   // Methods.
   PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
-  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
-                    LocalNativeBufferHandle(std::string name));
+  PDX_REMOTE_METHOD(GetConfigurationData, kOpGetConfigurationData,
+                    std::string(ConfigFileType config_type));
+  PDX_REMOTE_METHOD(SetupGlobalBuffer, kOpSetupGlobalBuffer,
+                    LocalNativeBufferHandle(DvrGlobalBufferKey key, size_t size,
+                                            uint64_t usage));
+  PDX_REMOTE_METHOD(DeleteGlobalBuffer, kOpDeleteGlobalBuffer,
+                    void(DvrGlobalBufferKey key));
+  PDX_REMOTE_METHOD(GetGlobalBuffer, kOpGetGlobalBuffer,
+                    LocalNativeBufferHandle(DvrGlobalBufferKey key));
   PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, bool(Void));
   PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
                     SurfaceInfo(const SurfaceAttributes& attributes));
   PDX_REMOTE_METHOD(GetSurfaceInfo, kOpGetSurfaceInfo, SurfaceInfo(Void));
-  PDX_REMOTE_METHOD(CreateQueue, kOpCreateQueue,
-                    LocalChannelHandle(size_t meta_size_bytes));
+  PDX_REMOTE_METHOD(
+      CreateQueue, kOpCreateQueue,
+      LocalChannelHandle(const ProducerQueueConfig& producer_config));
   PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
                     void(const SurfaceAttributes& attributes));
 };
@@ -225,7 +244,6 @@
   enum {
     kOpGetSurfaceState = 0,
     kOpGetSurfaceQueue,
-    kOpSetupNamedBuffer,
   };
 
   // Aliases.
@@ -237,9 +255,6 @@
                     std::vector<SurfaceState>(Void));
   PDX_REMOTE_METHOD(GetSurfaceQueue, kOpGetSurfaceQueue,
                     LocalChannelHandle(int surface_id, int queue_id));
-  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
-                    LocalNativeBufferHandle(const std::string& name,
-                                            size_t size, uint64_t usage));
 };
 
 struct VSyncSchedInfo {
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..20541a6
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,146 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+  // This constructor will create a display client and get the buffer from it.
+  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+  // If you already have the IonBuffer, use this. It will take ownership.
+  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+  // Use this if you do not want to take ownership.
+  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+  ~CPUMappedBuffer();
+
+  // Getters.
+  size_t Size() const { return size_; }
+  void* Address() const { return address_; }
+  bool IsMapped() const { return Address() != nullptr; }
+
+  // Attempt mapping this buffer to the CPU addressable space.
+  // This will create a display client and see if the buffer exists.
+  // If the buffer has not been setup yet, you will need to try again later.
+  void TryMapping();
+
+ protected:
+  // The memory area if we managed to map it.
+  size_t size_ = 0;
+  void* address_ = nullptr;
+
+  // If we are polling the display client, the buffer key here.
+  DvrGlobalBufferKey buffer_key_;
+
+  // If we just own the IonBuffer outright, it's here.
+  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+  // The last time we connected to the display service.
+  int64_t last_display_service_connection_ns_ = 0;
+
+  // If we do not own the IonBuffer, it's here
+  IonBuffer* buffer_ = nullptr;
+
+  // The usage mode.
+  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+      : CPUMappedBuffer(key, mode) {}
+
+  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(std::move(buffer), mode) {}
+
+  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(buffer, mode) {}
+
+  // Helper function for publishing records in the ring.
+  void Publish(const typename RingType::Record& record) {
+    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      ring->Put(record);
+    }
+  }
+
+  // Helper function for getting records from the ring.
+  // Returns true if we were able to retrieve the latest.
+  bool GetNewest(typename RingType::Record* record) {
+    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      return ring->GetNewest(&sequence_, record);
+    }
+
+    return false;
+  }
+
+  // Try obtaining the ring. If the named buffer has not been created yet, it
+  // will return nullptr.
+  RingType* Ring() {
+    // No ring created yet?
+    if (ring_ == nullptr) {
+      // Not mapped the memory yet?
+      if (IsMapped() == false) {
+        TryMapping();
+      }
+
+      // If have the memory mapped, allocate the ring.
+      if (IsMapped()) {
+        switch (usage_mode_) {
+          case CPUUsageMode::READ_OFTEN:
+          case CPUUsageMode::READ_RARELY: {
+            RingType ring;
+            bool import_ok;
+            std::tie(ring, import_ok) = RingType::Import(address_, size_);
+            if (import_ok) {
+              ring_ = std::make_unique<RingType>(ring);
+            }
+          } break;
+          case CPUUsageMode::WRITE_OFTEN:
+          case CPUUsageMode::WRITE_RARELY:
+            ring_ =
+                std::make_unique<RingType>(RingType::Create(address_, size_));
+            break;
+        }
+      }
+    }
+
+    return ring_.get();
+  }
+
+ protected:
+  std::unique_ptr<RingType> ring_ = nullptr;
+
+  uint32_t sequence_ = 0;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..6ebf487
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,98 @@
+#include <private/dvr/clock_ns.h>
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+// We will not poll the display service for buffers more frequently than this.
+constexpr size_t kDisplayServiceTriesPerSecond = 2;
+}  // namespace
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+    : buffer_key_(key), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+                                 CPUUsageMode mode)
+    : owned_buffer_(std::move(buffer)),
+      buffer_(owned_buffer_.get()),
+      usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+    : buffer_(buffer), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+  if (IsMapped()) {
+    buffer_->Unlock();
+  }
+}
+
+void CPUMappedBuffer::TryMapping() {
+  // Do we have an IonBuffer for this shared memory object?
+  if (buffer_ == nullptr) {
+    // Has it been too long since we last connected to the display service?
+    const auto current_time_ns = GetSystemClockNs();
+    if ((current_time_ns - last_display_service_connection_ns_) <
+        (1e9 / kDisplayServiceTriesPerSecond)) {
+      // Early exit.
+      return;
+    }
+    last_display_service_connection_ns_ = current_time_ns;
+
+    // Create a display client and get the buffer.
+    auto display_client = display::DisplayClient::Create();
+    if (display_client) {
+      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+      if (get_result.ok()) {
+        owned_buffer_ = get_result.take();
+        buffer_ = owned_buffer_.get();
+      } else {
+        // The buffer has not been created yet. This is OK, we will keep
+        // retrying.
+      }
+    } else {
+      ALOGE("Unable to create display client for shared buffer access");
+    }
+  }
+
+  if (buffer_) {
+    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+                 ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+    // Figure out the usage bits.
+    switch (usage_mode_) {
+      case CPUUsageMode::READ_OFTEN:
+        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+        break;
+      case CPUUsageMode::READ_RARELY:
+        usage |= GRALLOC_USAGE_SW_READ_RARELY;
+        break;
+      case CPUUsageMode::WRITE_OFTEN:
+        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+        break;
+      case CPUUsageMode::WRITE_RARELY:
+        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+        break;
+    }
+
+    int width = static_cast<int>(buffer_->width());
+    int height = 1;
+    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+    if (ret < 0 || !address_) {
+      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+      buffer_->Unlock();
+    } else {
+      size_ = width;
+    }
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index fa78b1c..9fe161d 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -21,27 +21,33 @@
 
 cflags = [
     "-DLOG_TAG=\"libdvr\"",
+    "-DTRACE=0",
 ]
 
 srcs = [
     "dvr_api.cpp",
     "dvr_buffer.cpp",
     "dvr_buffer_queue.cpp",
+    "dvr_configuration_data.cpp",
     "dvr_display_manager.cpp",
     "dvr_hardware_composer_client.cpp",
+    "dvr_performance.cpp",
+    "dvr_pose.cpp",
     "dvr_surface.cpp",
     "dvr_vsync.cpp",
 ]
 
 static_libs = [
+    "libbroadcastring",
     "libbufferhub",
     "libbufferhubqueue",
-    "libdisplay",
     "libvrsensor",
+    "libdisplay",
     "libvirtualtouchpadclient",
     "libvr_hwc-impl",
     "libvr_hwc-binder",
     "libgrallocusage",
+    "libperformance",
     "libpdx_default_transport",
 ]
 
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 2c95583..7d4e2d1 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -3,10 +3,14 @@
 #include <errno.h>
 #include <utils/Log.h>
 
+#include <algorithm>
+
 // Headers from libdvr
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_configuration_data.h>
 #include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_performance.h>
 #include <dvr/dvr_surface.h>
 #include <dvr/dvr_vsync.h>
 
@@ -22,15 +26,20 @@
   ALOGI("dvrGetApi: api=%p struct_size=%zu version=%d", api, struct_size,
         version);
   if (version == 1) {
-    if (struct_size != sizeof(DvrApi_v1)) {
-      ALOGE("dvrGetApi: Size mismatch: expected %zu; actual %zu",
-            sizeof(DvrApi_v1), struct_size);
-      return -EINVAL;
-    }
+    // New entry points are added at the end. If the caller's struct and
+    // this library have different sizes, we define the entry points in common.
+    // The caller is expected to handle unset entry points if necessary.
+    size_t clamped_struct_size = std::min(struct_size, sizeof(DvrApi_v1));
     DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
 
 // Defines an API entry for V1 (no version suffix).
-#define DVR_V1_API_ENTRY(name) dvr_api->name = dvr##name
+#define DVR_V1_API_ENTRY(name)                                 \
+  do {                                                         \
+    if ((offsetof(DvrApi_v1, name) + sizeof(dvr_api->name)) <= \
+        clamped_struct_size) {                                 \
+      dvr_api->name = dvr##name;                               \
+    }                                                          \
+  } while (0)
 
 #include "include/dvr/dvr_api_entries.h"
 
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 82469b8..1a99234 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -1,6 +1,7 @@
 #include "include/dvr/dvr_buffer.h"
 
 #include <android/hardware_buffer.h>
+#include <dvr/dvr_shared_buffers.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <ui/GraphicBuffer.h>
 
@@ -43,7 +44,13 @@
 }
 
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
-  delete write_buffer;
+  if (write_buffer != nullptr) {
+    ALOGW_IF(
+        write_buffer->slot != -1,
+        "dvrWriteBufferDestroy: Destroying a buffer associated with a valid "
+        "buffer queue slot. This may indicate possible leaks.");
+    delete write_buffer;
+  }
 }
 
 int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
@@ -106,7 +113,15 @@
     *read_buffer = new DvrReadBuffer;
 }
 
-void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) {
+  if (read_buffer != nullptr) {
+    ALOGW_IF(
+        read_buffer->slot != -1,
+        "dvrReadBufferDestroy: Destroying a buffer associated with a valid "
+        "buffer queue slot. This may indicate possible leaks.");
+    delete read_buffer;
+  }
+}
 
 int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
   return read_buffer && read_buffer->read_buffer;
@@ -176,6 +191,11 @@
                                   hardware_buffer);
 }
 
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet() {
+  return android::dvr::kSharedBufferLayoutVersion;
+}
+
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer) {
   if (!write_buffer || !write_buffer->write_buffer)
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index f668510..09a49dd 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -2,192 +2,375 @@
 #include "include/dvr/dvr_buffer_queue.h"
 
 #include <android/native_window.h>
-#include <gui/Surface.h>
-#include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/buffer_hub_queue_producer.h>
 
 #include "dvr_internal.h"
-
-#define CHECK_PARAM(param)                                               \
-  LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
-                      __FUNCTION__)
+#include "dvr_buffer_queue_internal.h"
 
 using namespace android;
-
-namespace android {
-namespace dvr {
-
-DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
-    const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
-  return new DvrWriteBufferQueue{std::move(producer_queue)};
-}
-
-DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
-    const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
-  return new DvrReadBufferQueue{std::move(consumer_queue)};
-}
-
-dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
-    DvrWriteBufferQueue* write_queue) {
-  return write_queue->producer_queue.get();
-}
-
-}  // namespace dvr
-}  // namespace android
+using android::dvr::BufferConsumer;
+using android::dvr::BufferHubBuffer;
+using android::dvr::BufferHubQueueProducer;
+using android::dvr::BufferProducer;
+using android::dvr::ConsumerQueue;
+using android::dvr::ProducerQueue;
+using android::dvr::ProducerQueueConfigBuilder;
+using android::dvr::UsagePolicy;
 
 extern "C" {
 
-void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
-  if (write_queue != nullptr && write_queue->native_window != nullptr)
-    ANativeWindow_release(write_queue->native_window);
+DvrWriteBufferQueue::DvrWriteBufferQueue(
+    const std::shared_ptr<ProducerQueue>& producer_queue)
+    : producer_queue_(producer_queue),
+      width_(producer_queue->default_width()),
+      height_(producer_queue->default_height()),
+      format_(producer_queue->default_format()) {}
 
+int DvrWriteBufferQueue::GetNativeWindow(ANativeWindow** out_window) {
+  if (native_window_ == nullptr) {
+    // Lazy creation of |native_window|, as not everyone is using
+    // DvrWriteBufferQueue as an external surface.
+    sp<IGraphicBufferProducer> gbp =
+        BufferHubQueueProducer::Create(producer_queue_);
+    native_window_ = new Surface(gbp, true);
+  }
+
+  *out_window = static_cast<ANativeWindow*>(native_window_.get());
+  return 0;
+}
+
+int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
+  std::unique_ptr<ConsumerQueue> consumer_queue =
+      producer_queue_->CreateConsumerQueue();
+  if (consumer_queue == nullptr) {
+    ALOGE(
+        "DvrWriteBufferQueue::CreateReadQueue: Failed to create consumer queue "
+        "from producer queue: queue_id=%d.", producer_queue_->id());
+    return -ENOMEM;
+  }
+
+  *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue));
+  return 0;
+}
+
+int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
+                                 int* out_fence_fd) {
+  DvrNativeBufferMetadata meta;
+  DvrWriteBuffer* buffer = nullptr;
+  int fence_fd = -1;
+  if (const int ret = GainBuffer(timeout, &buffer, &meta, &fence_fd))
+    return ret;
+  if (!buffer)
+    return -ENOMEM;
+
+  write_buffers_[buffer->slot].reset(buffer);
+  write_buffer->write_buffer = std::move(buffer->write_buffer);
+  *out_fence_fd = fence_fd;
+  return 0;
+}
+
+int DvrWriteBufferQueue::GainBuffer(int timeout,
+                                    DvrWriteBuffer** out_write_buffer,
+                                    DvrNativeBufferMetadata* out_meta,
+                                    int* out_fence_fd) {
+  size_t slot;
+  pdx::LocalHandle release_fence;
+
+  // Need to retry N+1 times, where N is total number of buffers in the queue.
+  // As in the worst case, we will dequeue all N buffers and reallocate them, on
+  // the {N+1}th dequeue, we are guaranteed to get a buffer with new dimension.
+  size_t max_retries = 1 + producer_queue_->capacity();
+  size_t retry = 0;
+
+  for (; retry < max_retries; retry++) {
+    auto buffer_status =
+        producer_queue_->Dequeue(timeout, &slot, out_meta, &release_fence);
+    if (!buffer_status) {
+      ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+               "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer: %s",
+               buffer_status.GetErrorMessage().c_str());
+      return -buffer_status.error();
+    }
+
+    if (write_buffers_[slot] == nullptr) {
+      // Lazy initialization of a write_buffers_ slot. Note that a slot will
+      // only be dynamically allocated once during the entire cycle life of a
+      // queue.
+      write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
+      write_buffers_[slot]->slot = slot;
+    }
+
+    LOG_ALWAYS_FATAL_IF(
+        write_buffers_[slot]->write_buffer,
+        "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
+    write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
+
+    const auto& buffer_producer = write_buffers_[slot]->write_buffer;
+    if (!buffer_producer)
+      return -ENOMEM;
+
+    if (width_ == buffer_producer->width() &&
+        height_ == buffer_producer->height() &&
+        format_ == buffer_producer->format()) {
+      // Producer queue returns a buffer matches the current request.
+      break;
+    }
+
+    // Needs reallocation. Note that if there are already multiple available
+    // buffers in the queue, the next one returned from |queue_->Dequeue| may
+    // still have the old buffer dimension or format. Retry up to N+1 times or
+    // until we dequeued a buffer with new configuration.
+    ALOGD_IF(TRACE,
+             "DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu "
+             "(w=%u, h=%u, fmt=%u) is different from the buffer returned "
+             "(w=%u, h=%u, fmt=%u). Need re-allocation.",
+             slot, width_, height_, format_, buffer_producer->width(),
+             buffer_producer->height(), buffer_producer->format());
+
+    // Currently, we are not storing |layer_count| and |usage| in queue
+    // configuration. Copy those setup from the last buffer dequeued before we
+    // remove it.
+    uint32_t old_layer_count = buffer_producer->layer_count();
+    uint64_t old_usage = buffer_producer->usage();
+
+    // Allocate a new producer buffer with new buffer configs. Note that if
+    // there are already multiple available buffers in the queue, the next one
+    // returned from |queue_->Dequeue| may still have the old buffer dimension
+    // or format. Retry up to BufferHubQueue::kMaxQueueCapacity times or until
+    // we dequeued a buffer with new configuration.
+    auto remove_status = producer_queue_->RemoveBuffer(slot);
+    if (!remove_status) {
+      ALOGE("DvrWriteBufferQueue::Dequeue: Failed to remove buffer: %s",
+            remove_status.GetErrorMessage().c_str());
+      return -remove_status.error();
+    }
+    // Make sure that the previously allocated buffer is dereferenced from
+    // write_buffers_ array.
+    write_buffers_[slot]->write_buffer = nullptr;
+
+    auto allocate_status = producer_queue_->AllocateBuffer(
+        width_, height_, old_layer_count, format_, old_usage);
+    if (!allocate_status) {
+      ALOGE("DvrWriteBufferQueue::Dequeue: Failed to allocate buffer: %s",
+            allocate_status.GetErrorMessage().c_str());
+      return -allocate_status.error();
+    }
+  }
+
+  if (retry >= max_retries) {
+    ALOGE(
+        "DvrWriteBufferQueue::Dequeue: Failed to re-allocate buffer after "
+        "resizing.");
+    return -ENOMEM;
+  }
+
+  *out_write_buffer = write_buffers_[slot].release();
+  *out_fence_fd = release_fence.Release();
+
+  return 0;
+}
+
+int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
+                                    const DvrNativeBufferMetadata* meta,
+                                    int ready_fence_fd) {
+  LOG_FATAL_IF(
+      (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
+      "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
+
+  // Some basic sanity checks before we put the buffer back into a slot.
+  size_t slot = static_cast<size_t>(write_buffer->slot);
+  if (write_buffers_[slot] != nullptr) {
+    ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
+    return -EINVAL;
+  }
+  if (write_buffer->write_buffer == nullptr) {
+    ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer.");
+    return -EINVAL;
+  }
+  if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) {
+    ALOGE(
+        "DvrWriteBufferQueue::PostBuffer: Buffer to be posted does not "
+        "belong to this buffer queue. Posting buffer: id=%d, buffer in "
+        "queue: id=%d",
+        write_buffer->write_buffer->id(), producer_queue_->GetBufferId(slot));
+    return -EINVAL;
+  }
+
+  write_buffer->write_buffer->SetQueueIndex(next_post_index_++);
+  pdx::LocalHandle fence(ready_fence_fd);
+  const int ret = write_buffer->write_buffer->PostAsync(meta, fence);
+  if (ret < 0) {
+    ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d",
+          ret);
+    return ret;
+  }
+
+  // Put the DvrWriteBuffer pointer back into its slot for reuse.
+  write_buffers_[slot].reset(write_buffer);
+  // It's import to reset the write buffer client now. It should stay invalid
+  // until next GainBuffer on the same slot.
+  write_buffers_[slot]->write_buffer = nullptr;
+  return 0;
+}
+
+int DvrWriteBufferQueue::ResizeBuffer(uint32_t width, uint32_t height) {
+  if (width == 0 || height == 0) {
+    ALOGE(
+        "DvrWriteBufferQueue::ResizeBuffer: invalid buffer dimension: w=%u, "
+        "h=%u.",
+        width, height);
+    return -EINVAL;
+  }
+
+  width_ = width;
+  height_ = height;
+  return 0;
+}
+
+int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format,
+                              uint32_t layer_count, uint64_t usage,
+                              size_t capacity, size_t metadata_size,
+                              DvrWriteBufferQueue** out_write_queue) {
+  if (!out_write_queue)
+    return -EINVAL;
+
+  auto config_builder = ProducerQueueConfigBuilder()
+                            .SetDefaultWidth(width)
+                            .SetDefaultHeight(height)
+                            .SetDefaultFormat(format)
+                            .SetMetadataSize(metadata_size);
+  std::unique_ptr<ProducerQueue> producer_queue =
+      ProducerQueue::Create(config_builder.Build(), UsagePolicy{});
+  if (!producer_queue) {
+    ALOGE("dvrWriteBufferQueueCreate: Failed to create producer queue.");
+    return -ENOMEM;
+  }
+
+  auto status = producer_queue->AllocateBuffers(width, height, layer_count,
+                                                format, usage, capacity);
+  if (!status.ok()) {
+    ALOGE("dvrWriteBufferQueueCreate: Failed to allocate buffers.");
+    return -ENOMEM;
+  }
+
+  *out_write_queue = new DvrWriteBufferQueue(std::move(producer_queue));
+  return 0;
+}
+
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
   delete write_queue;
 }
 
 ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
-  if (!write_queue || !write_queue->producer_queue)
+  if (!write_queue)
     return -EINVAL;
 
-  return write_queue->producer_queue->capacity();
+  return write_queue->capacity();
 }
 
 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
   if (!write_queue)
     return -EINVAL;
 
-  return write_queue->producer_queue->id();
+  return write_queue->id();
 }
 
 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
                                           ANativeWindow** out_window) {
+  ALOGW(
+      "dvrWriteBufferQueueGetExternalSurface: This API has been deprecated and "
+      "renamed to dvrWriteBufferQueueGetANativeWindow.");
+  return dvrWriteBufferQueueGetANativeWindow(write_queue, out_window);
+}
+
+int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue,
+                                        ANativeWindow** out_window) {
   if (!write_queue || !out_window)
     return -EINVAL;
 
-  if (write_queue->producer_queue->metadata_size() !=
-      sizeof(DvrNativeBufferMetadata)) {
-    ALOGE(
-        "The size of buffer metadata (%zu) of the write queue does not match "
-        "of size of DvrNativeBufferMetadata (%zu).",
-        write_queue->producer_queue->metadata_size(),
-        sizeof(DvrNativeBufferMetadata));
-    return -EINVAL;
-  }
-
-  // Lazy creation of |native_window|.
-  if (write_queue->native_window == nullptr) {
-    sp<IGraphicBufferProducer> gbp =
-        dvr::BufferHubQueueProducer::Create(write_queue->producer_queue);
-    sp<Surface> surface = new Surface(gbp, true);
-    write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
-    ANativeWindow_acquire(write_queue->native_window);
-  }
-
-  *out_window = write_queue->native_window;
-  return 0;
+  return write_queue->GetNativeWindow(out_window);
 }
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue) {
-  if (!write_queue || !write_queue->producer_queue || !out_read_queue)
+  if (!write_queue || !out_read_queue)
     return -EINVAL;
 
-  auto read_queue = std::make_unique<DvrReadBufferQueue>();
-  read_queue->consumer_queue =
-      write_queue->producer_queue->CreateConsumerQueue();
-  if (read_queue->consumer_queue == nullptr) {
-    ALOGE(
-        "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
-        "from DvrWriteBufferQueue[%p].",
-        write_queue);
-    return -ENOMEM;
-  }
-
-  *out_read_queue = read_queue.release();
-  return 0;
+  return write_queue->CreateReadQueue(out_read_queue);
 }
 
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
                                DvrWriteBuffer* write_buffer,
                                int* out_fence_fd) {
-  if (!write_queue || !write_queue->producer_queue || !write_buffer ||
-      !out_fence_fd) {
+  if (!write_queue || !write_buffer || !out_fence_fd)
     return -EINVAL;
-  }
 
-  size_t slot;
-  pdx::LocalHandle release_fence;
-  auto buffer_status =
-      write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence);
-  if (!buffer_status) {
-    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
-             "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s",
-             buffer_status.GetErrorMessage().c_str());
-    return -buffer_status.error();
-  }
+  return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
+}
 
-  write_buffer->write_buffer = buffer_status.take();
-  *out_fence_fd = release_fence.Release();
-  return 0;
+int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
+                                  DvrWriteBuffer** out_write_buffer,
+                                  DvrNativeBufferMetadata* out_meta,
+                                  int* out_fence_fd) {
+  if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd)
+    return -EINVAL;
+
+  return write_queue->GainBuffer(timeout, out_write_buffer, out_meta,
+                                 out_fence_fd);
+}
+
+int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
+                                  DvrWriteBuffer* write_buffer,
+                                  const DvrNativeBufferMetadata* meta,
+                                  int ready_fence_fd) {
+  if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta)
+    return -EINVAL;
+
+  return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd);
+}
+
+int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue,
+                                    uint32_t width, uint32_t height) {
+  if (!write_queue)
+    return -EINVAL;
+
+  return write_queue->ResizeBuffer(width, height);
 }
 
 // ReadBufferQueue
-void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
-  delete read_queue;
-}
 
-ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
-  if (!read_queue)
-    return -EINVAL;
+DvrReadBufferQueue::DvrReadBufferQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue)
+    : consumer_queue_(consumer_queue) {}
 
-  return read_queue->consumer_queue->capacity();
-}
-
-int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
-  if (!read_queue)
-    return -EINVAL;
-
-  return read_queue->consumer_queue->id();
-}
-
-int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
-                                      DvrReadBufferQueue** out_read_queue) {
-  if (!read_queue || !read_queue->consumer_queue || !out_read_queue)
-    return -EINVAL;
-
-  auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
-  new_read_queue->consumer_queue =
-      read_queue->consumer_queue->CreateConsumerQueue();
-  if (new_read_queue->consumer_queue == nullptr) {
+int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
+  std::unique_ptr<ConsumerQueue> consumer_queue =
+      consumer_queue_->CreateConsumerQueue();
+  if (consumer_queue == nullptr) {
     ALOGE(
-        "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
-        "from DvrReadBufferQueue[%p].",
-        read_queue);
+        "DvrReadBufferQueue::CreateReadQueue: Failed to create consumer queue "
+        "from producer queue: queue_id=%d.", consumer_queue_->id());
     return -ENOMEM;
   }
 
-  *out_read_queue = new_read_queue.release();
+  *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue));
   return 0;
 }
 
-int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer* read_buffer, int* out_fence_fd,
-                              void* out_meta, size_t meta_size_bytes) {
-  if (!read_queue || !read_queue->consumer_queue || !read_buffer ||
-      !out_fence_fd || !out_meta) {
-    return -EINVAL;
-  }
-
-  if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) {
+int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
+                                int* out_fence_fd, void* out_meta,
+                                size_t meta_size_bytes) {
+  if (meta_size_bytes != consumer_queue_->metadata_size()) {
     ALOGE(
-        "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
+        "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
         "but actual (%zu).",
-        read_queue->consumer_queue->metadata_size(), meta_size_bytes);
+        consumer_queue_->metadata_size(), meta_size_bytes);
     return -EINVAL;
   }
 
   size_t slot;
   pdx::LocalHandle acquire_fence;
-  auto buffer_status = read_queue->consumer_queue->Dequeue(
+  auto buffer_status = consumer_queue_->Dequeue(
       timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
   if (!buffer_status) {
     ALOGE_IF(buffer_status.error() != ETIMEDOUT,
@@ -198,7 +381,209 @@
 
   read_buffer->read_buffer = buffer_status.take();
   *out_fence_fd = acquire_fence.Release();
+
   return 0;
 }
 
+int DvrReadBufferQueue::AcquireBuffer(int timeout,
+                                      DvrReadBuffer** out_read_buffer,
+                                      DvrNativeBufferMetadata* out_meta,
+                                      int* out_fence_fd) {
+  size_t slot;
+  pdx::LocalHandle acquire_fence;
+  auto buffer_status =
+      consumer_queue_->Dequeue(timeout, &slot, out_meta, &acquire_fence);
+  if (!buffer_status) {
+    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+             "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer: %s",
+             buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  if (read_buffers_[slot] == nullptr) {
+    // Lazy initialization of a read_buffers_ slot. Note that a slot will only
+    // be dynamically allocated once during the entire cycle life of a queue.
+    read_buffers_[slot] = std::make_unique<DvrReadBuffer>();
+    read_buffers_[slot]->slot = slot;
+  }
+
+  LOG_FATAL_IF(
+      read_buffers_[slot]->read_buffer,
+      "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot);
+  read_buffers_[slot]->read_buffer = std::move(buffer_status.take());
+
+  *out_read_buffer = read_buffers_[slot].release();
+  *out_fence_fd = acquire_fence.Release();
+
+  return 0;
+}
+
+int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
+                                      const DvrNativeBufferMetadata* meta,
+                                      int release_fence_fd) {
+  LOG_FATAL_IF(
+      (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
+      "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
+
+  // Some basic sanity checks before we put the buffer back into a slot.
+  size_t slot = static_cast<size_t>(read_buffer->slot);
+  if (read_buffers_[slot] != nullptr) {
+    ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
+    return -EINVAL;
+  }
+  if (read_buffer->read_buffer == nullptr) {
+    ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer.");
+    return -EINVAL;
+  }
+  if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
+    ALOGE(
+        "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
+        "belong to this buffer queue. Releasing buffer: id=%d, buffer in "
+        "queue: id=%d",
+        read_buffer->read_buffer->id(), consumer_queue_->GetBufferId(slot));
+    return -EINVAL;
+  }
+
+  pdx::LocalHandle fence(release_fence_fd);
+  int ret = read_buffer->read_buffer->ReleaseAsync(meta, fence);
+  if (ret < 0) {
+    ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d",
+          ret);
+    return ret;
+  }
+
+  // Put the DvrReadBuffer pointer back into its slot for reuse.
+  read_buffers_[slot].reset(read_buffer);
+  // It's import to reset the read buffer client now. It should stay invalid
+  // until next AcquireBuffer on the same slot.
+  read_buffers_[slot]->read_buffer = nullptr;
+  return 0;
+}
+
+void DvrReadBufferQueue::SetBufferAvailableCallback(
+    DvrReadBufferQueueBufferAvailableCallback callback, void* context) {
+  if (callback == nullptr) {
+    consumer_queue_->SetBufferAvailableCallback(nullptr);
+  } else {
+    consumer_queue_->SetBufferAvailableCallback(
+        [callback, context]() { callback(context); });
+  }
+}
+
+void DvrReadBufferQueue::SetBufferRemovedCallback(
+    DvrReadBufferQueueBufferRemovedCallback callback, void* context) {
+  if (callback == nullptr) {
+    consumer_queue_->SetBufferRemovedCallback(nullptr);
+  } else {
+    consumer_queue_->SetBufferRemovedCallback(
+        [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
+          // When buffer is removed from the queue, the slot is already invalid.
+          auto read_buffer = std::make_unique<DvrReadBuffer>();
+          read_buffer->read_buffer =
+              std::static_pointer_cast<BufferConsumer>(buffer);
+          callback(read_buffer.release(), context);
+        });
+  }
+}
+
+int DvrReadBufferQueue::HandleEvents() {
+  // TODO(jwcai) Probably should change HandleQueueEvents to return Status.
+  consumer_queue_->HandleQueueEvents();
+  return 0;
+}
+
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
+  delete read_queue;
+}
+
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->capacity();
+}
+
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->id();
+}
+
+int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->event_fd();
+}
+
+int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
+                                      DvrReadBufferQueue** out_read_queue) {
+  if (!read_queue || !out_read_queue)
+    return -EINVAL;
+
+  return read_queue->CreateReadQueue(out_read_queue);
+}
+
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+                              DvrReadBuffer* read_buffer, int* out_fence_fd,
+                              void* out_meta, size_t meta_size_bytes) {
+  if (!read_queue || !read_buffer || !out_fence_fd)
+    return -EINVAL;
+
+  if (meta_size_bytes != 0 && !out_meta)
+    return -EINVAL;
+
+  return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta,
+                             meta_size_bytes);
+}
+
+int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
+                                    DvrReadBuffer** out_read_buffer,
+                                    DvrNativeBufferMetadata* out_meta,
+                                    int* out_fence_fd) {
+  if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd)
+    return -EINVAL;
+
+  return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta,
+                                   out_fence_fd);
+}
+
+int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
+                                    DvrReadBuffer* read_buffer,
+                                    const DvrNativeBufferMetadata* meta,
+                                    int release_fence_fd) {
+  if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta)
+    return -EINVAL;
+
+  return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd);
+}
+
+int dvrReadBufferQueueSetBufferAvailableCallback(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferAvailableCallback callback, void* context) {
+  if (!read_queue)
+    return -EINVAL;
+
+  read_queue->SetBufferAvailableCallback(callback, context);
+  return 0;
+}
+
+int dvrReadBufferQueueSetBufferRemovedCallback(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferRemovedCallback callback, void* context) {
+  if (!read_queue)
+    return -EINVAL;
+
+  read_queue->SetBufferRemovedCallback(callback, context);
+  return 0;
+}
+
+int dvrReadBufferQueueHandleEvents(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->HandleEvents();
+}
+
 }  // extern "C"
diff --git a/libs/vr/libdvr/dvr_buffer_queue_internal.h b/libs/vr/libdvr/dvr_buffer_queue_internal.h
new file mode 100644
index 0000000..e53a686
--- /dev/null
+++ b/libs/vr/libdvr/dvr_buffer_queue_internal.h
@@ -0,0 +1,95 @@
+#ifndef ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_
+#define ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_
+
+#include <gui/Surface.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <sys/cdefs.h>
+
+#include <array>
+#include <memory>
+
+#include "dvr_internal.h"
+
+struct ANativeWindow;
+
+typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context);
+typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer,
+                                                        void* context);
+
+struct DvrWriteBufferQueue {
+  using BufferHubQueue = android::dvr::BufferHubQueue;
+  using ProducerQueue = android::dvr::ProducerQueue;
+
+  // Create a concrete object for DvrWriteBufferQueue.
+  //
+  // @param producer_queue The BufferHub's ProducerQueue that is used to back
+  //     this DvrWriteBufferQueue, must not be NULL.
+  explicit DvrWriteBufferQueue(
+      const std::shared_ptr<ProducerQueue>& producer_queue);
+
+  int id() const { return producer_queue_->id(); }
+  uint32_t width() const { return width_; };
+  uint32_t height() const { return height_; };
+  uint32_t format() const { return format_; };
+  size_t capacity() const { return producer_queue_->capacity(); }
+  const std::shared_ptr<ProducerQueue>& producer_queue() const {
+    return producer_queue_;
+  }
+
+  int GetNativeWindow(ANativeWindow** out_window);
+  int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
+  int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd);
+  int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer,
+                 DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
+  int PostBuffer(DvrWriteBuffer* write_buffer,
+                 const DvrNativeBufferMetadata* meta, int ready_fence_fd);
+  int ResizeBuffer(uint32_t width, uint32_t height);
+
+ private:
+  std::shared_ptr<ProducerQueue> producer_queue_;
+  std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity>
+      write_buffers_;
+
+  int64_t next_post_index_ = 0;
+  uint32_t width_;
+  uint32_t height_;
+  uint32_t format_;
+
+  android::sp<android::Surface> native_window_;
+};
+
+struct DvrReadBufferQueue {
+  using BufferHubQueue = android::dvr::BufferHubQueue;
+  using ConsumerQueue = android::dvr::ConsumerQueue;
+
+  explicit DvrReadBufferQueue(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue);
+
+  int id() const { return consumer_queue_->id(); }
+  int event_fd() const { return consumer_queue_->queue_fd(); }
+  size_t capacity() const { return consumer_queue_->capacity(); }
+
+  int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
+  int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd,
+              void* out_meta, size_t user_metadata_size);
+  int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer,
+                    DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
+  int ReleaseBuffer(DvrReadBuffer* read_buffer,
+                    const DvrNativeBufferMetadata* meta, int release_fence_fd);
+  void SetBufferAvailableCallback(
+      DvrReadBufferQueueBufferAvailableCallback callback, void* context);
+  void SetBufferRemovedCallback(
+      DvrReadBufferQueueBufferRemovedCallback callback, void* context);
+  int HandleEvents();
+
+ private:
+  std::shared_ptr<ConsumerQueue> consumer_queue_;
+  std::array<std::unique_ptr<DvrReadBuffer>, BufferHubQueue::kMaxQueueCapacity>
+      read_buffers_;
+};
+
+#endif  // ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_configuration_data.cpp b/libs/vr/libdvr/dvr_configuration_data.cpp
new file mode 100644
index 0000000..df0d54e
--- /dev/null
+++ b/libs/vr/libdvr/dvr_configuration_data.cpp
@@ -0,0 +1,40 @@
+#include "include/dvr/dvr_configuration_data.h"
+
+#include <private/dvr/display_client.h>
+
+using android::dvr::display::ConfigFileType;
+using android::dvr::display::DisplayClient;
+
+extern "C" {
+
+int dvrConfigurationDataGet(int config_type, uint8_t** data,
+                            size_t* data_size) {
+  if (!data || !data_size) {
+    return -EINVAL;
+  }
+
+  auto client = DisplayClient::Create();
+  if (!client) {
+    ALOGE("dvrGetGlobalBuffer: Failed to create display client!");
+    return -ECOMM;
+  }
+
+  ConfigFileType config_file_type = static_cast<ConfigFileType>(config_type);
+  auto config_data_status =
+      client->GetConfigurationData(config_file_type);
+
+  if (!config_data_status) {
+    return -config_data_status.error();
+  }
+
+  *data_size = config_data_status.get().size();
+  *data = new uint8_t[*data_size];
+  std::copy_n(config_data_status.get().begin(), *data_size, *data);
+  return 0;
+}
+
+void dvrConfigurationDataDestroy(uint8_t* data) {
+  delete[] data;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index 87636ec..852f9a4 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -2,20 +2,19 @@
 
 #include <dvr/dvr_buffer.h>
 #include <pdx/rpc/variant.h>
-#include <private/android/AHardwareBufferHelpers.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_client.h>
 #include <private/dvr/display_manager_client.h>
 
 #include "dvr_internal.h"
+#include "dvr_buffer_queue_internal.h"
 
-using android::AHardwareBuffer_convertToGrallocUsageBits;
 using android::dvr::BufferConsumer;
 using android::dvr::display::DisplayManagerClient;
 using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttribute;
 using android::dvr::display::SurfaceState;
-using android::dvr::CreateDvrReadBufferQueueFromConsumerQueue;
 using android::pdx::rpc::EmptyVariant;
 
 namespace {
@@ -111,26 +110,6 @@
 
 void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
 
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
-                                      const char* name, size_t size,
-                                      uint64_t usage, DvrBuffer** buffer_out) {
-  if (!client || !name || !buffer_out)
-    return -EINVAL;
-
-  uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
-
-  auto buffer_status =
-      client->client->SetupNamedBuffer(name, size, gralloc_usage);
-  if (!buffer_status) {
-    ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
-          buffer_status.GetErrorMessage().c_str());
-    return -buffer_status.error();
-  }
-
-  *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
-  return 0;
-}
-
 int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
   if (!client)
     return -EINVAL;
@@ -177,7 +156,7 @@
     return -status.error();
   }
 
-  *queue_out = CreateDvrReadBufferQueueFromConsumerQueue(status.take());
+  *queue_out = new DvrReadBufferQueue(status.take());
   return 0;
 }
 
diff --git a/libs/vr/libdvr/dvr_hardware_composer_client.cpp b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
index d3ae299..4e87cf6 100644
--- a/libs/vr/libdvr/dvr_hardware_composer_client.cpp
+++ b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
@@ -6,7 +6,9 @@
 #include <binder/IServiceManager.h>
 #include <private/android/AHardwareBufferHelpers.h>
 
+#include <functional>
 #include <memory>
+#include <mutex>
 
 struct DvrHwcFrame {
   android::dvr::ComposerView::Frame frame;
@@ -16,10 +18,15 @@
 
 class HwcCallback : public android::dvr::BnVrComposerCallback {
  public:
-  explicit HwcCallback(DvrHwcOnFrameCallback callback,
-                       void* client_state);
+  using CallbackFunction = std::function<int(DvrHwcFrame*)>;
+
+  explicit HwcCallback(const CallbackFunction& callback);
   ~HwcCallback() override;
 
+  // Reset the callback. This needs to be done early to avoid use after free
+  // accesses from binder thread callbacks.
+  void Shutdown();
+
   std::unique_ptr<DvrHwcFrame> DequeueFrame();
 
  private:
@@ -28,26 +35,41 @@
       const android::dvr::ParcelableComposerFrame& frame,
       android::dvr::ParcelableUniqueFd* fence) override;
 
-  DvrHwcOnFrameCallback callback_;
-  void* client_state_;
+  // Protects the |callback_| from uses from multiple threads. During shutdown
+  // there may be in-flight frame update events. In those cases the callback
+  // access needs to be protected otherwise binder threads may access an invalid
+  // callback.
+  std::mutex mutex_;
+  CallbackFunction callback_;
 
   HwcCallback(const HwcCallback&) = delete;
   void operator=(const HwcCallback&) = delete;
 };
 
-HwcCallback::HwcCallback(DvrHwcOnFrameCallback callback, void* client_state)
-    : callback_(callback), client_state_(client_state) {}
+HwcCallback::HwcCallback(const CallbackFunction& callback)
+    : callback_(callback) {}
 
 HwcCallback::~HwcCallback() {}
 
+void HwcCallback::Shutdown() {
+  std::lock_guard<std::mutex> guard(mutex_);
+  callback_ = nullptr;
+}
+
 android::binder::Status HwcCallback::onNewFrame(
     const android::dvr::ParcelableComposerFrame& frame,
     android::dvr::ParcelableUniqueFd* fence) {
+  std::lock_guard<std::mutex> guard(mutex_);
+
+  if (!callback_) {
+    fence->set_fence(android::base::unique_fd());
+    return android::binder::Status::ok();
+  }
+
   std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame());
   dvr_frame->frame = frame.frame();
 
-  fence->set_fence(android::base::unique_fd(callback_(client_state_,
-                                                      dvr_frame.release())));
+  fence->set_fence(android::base::unique_fd(callback_(dvr_frame.release())));
   return android::binder::Status::ok();
 }
 
@@ -67,7 +89,8 @@
   if (!client->composer.get())
     return nullptr;
 
-  client->callback = new HwcCallback(callback, data);
+  client->callback = new HwcCallback(std::bind(callback, data,
+                                               std::placeholders::_1));
   android::binder::Status status = client->composer->registerObserver(
       client->callback);
   if (!status.isOk())
@@ -77,6 +100,13 @@
 }
 
 void dvrHwcClientDestroy(DvrHwcClient* client) {
+  client->composer->clearObserver();
+
+  // NOTE: Deleting DvrHwcClient* isn't enough since DvrHwcClient::callback is a
+  // shared pointer that could be referenced from a binder thread. But the
+  // client callback isn't valid past this calls so that needs to be reset.
+  client->callback->Shutdown();
+
   delete client;
 }
 
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index 89bef09..de8bb96 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -10,8 +10,6 @@
 typedef struct DvrBuffer DvrBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
 typedef struct DvrWriteBuffer DvrWriteBuffer;
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
-typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
 }  // extern "C"
 
@@ -20,9 +18,7 @@
 
 class BufferProducer;
 class BufferConsumer;
-class ConsumerQueue;
 class IonBuffer;
-class ProducerQueue;
 
 DvrBuffer* CreateDvrBufferFromIonBuffer(
     const std::shared_ptr<IonBuffer>& ion_buffer);
@@ -32,23 +28,26 @@
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<BufferProducer>& buffer_producer);
 
-DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
-    const std::shared_ptr<ConsumerQueue>& consumer_queue);
-DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
-    const std::shared_ptr<ProducerQueue>& producer_queue);
-ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
-    DvrWriteBufferQueue* write_queue);
-
 }  // namespace dvr
 }  // namespace android
 
 extern "C" {
 
 struct DvrWriteBuffer {
+  // The slot nubmer of the buffer, a valid slot number must be in the range of
+  // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
+  // DvrWriteBuffer acquired from a DvrWriteBufferQueue.
+  int32_t slot = -1;
+
   std::shared_ptr<android::dvr::BufferProducer> write_buffer;
 };
 
 struct DvrReadBuffer {
+  // The slot nubmer of the buffer, a valid slot number must be in the range of
+  // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
+  // DvrReadBuffer acquired from a DvrReadBufferQueue.
+  int32_t slot = -1;
+
   std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
 };
 
@@ -56,15 +55,6 @@
   std::shared_ptr<android::dvr::IonBuffer> buffer;
 };
 
-struct DvrWriteBufferQueue {
-  std::shared_ptr<android::dvr::ProducerQueue> producer_queue;
-  ANativeWindow* native_window{nullptr};
-};
-
-struct DvrReadBufferQueue {
-  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue;
-};
-
 }  // extern "C"
 
 #endif  // ANDROID_DVR_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_performance.cpp b/libs/vr/libdvr/dvr_performance.cpp
new file mode 100644
index 0000000..599101f
--- /dev/null
+++ b/libs/vr/libdvr/dvr_performance.cpp
@@ -0,0 +1,18 @@
+#include "include/dvr/dvr_performance.h"
+
+#include <private/dvr/performance_client.h>
+
+using android::dvr::PerformanceClient;
+
+extern "C" {
+
+int dvrPerformanceSetSchedulerPolicy(pid_t task_id,
+                                     const char* scheduler_policy) {
+  int error;
+  if (auto client = PerformanceClient::Create(&error))
+    return client->SetSchedulerPolicy(task_id, scheduler_policy);
+  else
+    return error;
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_pose.cpp b/libs/vr/libdvr/dvr_pose.cpp
new file mode 100644
index 0000000..c379ef5
--- /dev/null
+++ b/libs/vr/libdvr/dvr_pose.cpp
@@ -0,0 +1,29 @@
+#include "include/dvr/dvr_pose.h"
+
+#include <memory>
+
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/pose_client_internal.h>
+
+#include "dvr_buffer_queue_internal.h"
+
+using android::dvr::ConsumerQueue;
+
+int dvrPoseClientGetDataReader(DvrPoseClient* client, uint64_t data_type,
+                               DvrReadBufferQueue** queue_out) {
+  if (!client || !queue_out)
+    return -EINVAL;
+
+  ConsumerQueue* consumer_queue;
+  int status = android::dvr::dvrPoseClientGetDataReaderHandle(client,
+                                                              data_type,
+                                                              &consumer_queue);
+  if (status != 0) {
+    ALOGE("dvrPoseClientGetDataReader: Failed to get queue: %d", status);
+    return status;
+  }
+
+  std::shared_ptr<ConsumerQueue> consumer_queue_ptr{consumer_queue};
+  *queue_out = new DvrReadBufferQueue(consumer_queue_ptr);
+  return 0;
+}
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 67e2ae8..a3a47f1 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -2,19 +2,33 @@
 
 #include <inttypes.h>
 
+#include <pdx/rpc/variant.h>
+#include <private/android/AHardwareBufferHelpers.h>
 #include <private/dvr/display_client.h>
 
+#include "dvr_buffer_queue_internal.h"
 #include "dvr_internal.h"
 
+using android::AHardwareBuffer_convertToGrallocUsageBits;
 using android::dvr::display::DisplayClient;
 using android::dvr::display::Surface;
 using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttributeValue;
 using android::dvr::CreateDvrReadBufferFromBufferConsumer;
-using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue;
+using android::pdx::rpc::EmptyVariant;
 
 namespace {
 
+// Sets the Variant |destination| to the target std::array type and copies the C
+// array into it. Unsupported std::array configurations will fail to compile.
+template <typename T, std::size_t N>
+void ArrayCopy(SurfaceAttributeValue* destination, const T (&source)[N]) {
+  using ArrayType = std::array<T, N>;
+  *destination = ArrayType{};
+  std::copy(std::begin(source), std::end(source),
+            std::get<ArrayType>(*destination).begin());
+}
+
 bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
                               size_t attribute_count,
                               SurfaceAttributes* surface_attributes,
@@ -29,25 +43,31 @@
         value = attributes[i].value.int64_value;
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
-        value = attributes[i].value.bool_value;
+        // bool_value is defined in an extern "C" block, which makes it look
+        // like an int to C++. Use a cast to assign the correct type to the
+        // Variant type SurfaceAttributeValue.
+        value = static_cast<bool>(attributes[i].value.bool_value);
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
         value = attributes[i].value.float_value;
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
-        value = attributes[i].value.float2_value;
+        ArrayCopy(&value, attributes[i].value.float2_value);
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
-        value = attributes[i].value.float3_value;
+        ArrayCopy(&value, attributes[i].value.float3_value);
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
-        value = attributes[i].value.float4_value;
+        ArrayCopy(&value, attributes[i].value.float4_value);
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
-        value = attributes[i].value.float8_value;
+        ArrayCopy(&value, attributes[i].value.float8_value);
         break;
       case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
-        value = attributes[i].value.float16_value;
+        ArrayCopy(&value, attributes[i].value.float16_value);
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_NONE:
+        value = EmptyVariant{};
         break;
       default:
         *error_index = i;
@@ -134,7 +154,7 @@
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
                                      uint32_t layer_count, uint64_t usage,
-                                     size_t capacity,
+                                     size_t capacity, size_t metadata_size,
                                      DvrWriteBufferQueue** out_writer) {
   if (surface == nullptr || out_writer == nullptr) {
     ALOGE(
@@ -144,39 +164,115 @@
     return -EINVAL;
   }
 
-  auto status = surface->surface->CreateQueue(width, height, layer_count,
-                                              format, usage, capacity);
+  auto status = surface->surface->CreateQueue(
+      width, height, layer_count, format, usage, capacity, metadata_size);
   if (!status) {
     ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
           status.GetErrorMessage().c_str());
     return -status.error();
   }
 
-  *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take());
+  *out_writer = new DvrWriteBufferQueue(status.take());
   return 0;
 }
 
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
-  auto client = DisplayClient::Create();
-  if (!client) {
-    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
-    return -ECOMM;
-  }
-
-  if (out_buffer == nullptr || name == nullptr) {
-    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
-          out_buffer);
+int dvrSetupGlobalBuffer(DvrGlobalBufferKey key, size_t size, uint64_t usage,
+                         DvrBuffer** buffer_out) {
+  if (!buffer_out)
     return -EINVAL;
+
+  int error;
+  auto client = DisplayClient::Create(&error);
+  if (!client) {
+    ALOGE("dvrSetupGlobalBuffer: Failed to create display client: %s",
+          strerror(-error));
+    return error;
   }
 
-  auto status = client->GetNamedBuffer(name);
+  uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
+
+  auto buffer_status = client->SetupGlobalBuffer(key, size, gralloc_usage);
+  if (!buffer_status) {
+    ALOGE("dvrSetupGlobalBuffer: Failed to setup global buffer: %s",
+          buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
+  return 0;
+}
+
+int dvrDeleteGlobalBuffer(DvrGlobalBufferKey key) {
+  int error;
+  auto client = DisplayClient::Create(&error);
+  if (!client) {
+    ALOGE("dvrDeleteGlobalBuffer: Failed to create display client: %s",
+          strerror(-error));
+    return error;
+  }
+
+  auto buffer_status = client->DeleteGlobalBuffer(key);
+  if (!buffer_status) {
+    ALOGE("dvrDeleteGlobalBuffer: Failed to delete named buffer: %s",
+          buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  return 0;
+}
+
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer) {
+  if (!out_buffer)
+    return -EINVAL;
+
+  int error;
+  auto client = DisplayClient::Create(&error);
+  if (!client) {
+    ALOGE("dvrGetGlobalBuffer: Failed to create display client: %s",
+          strerror(-error));
+    return error;
+  }
+
+  auto status = client->GetGlobalBuffer(key);
   if (!status) {
-    ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
-          status.GetErrorMessage().c_str());
     return -status.error();
   }
   *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
   return 0;
 }
 
+int dvrGetNativeDisplayMetrics(size_t sizeof_metrics,
+                               DvrNativeDisplayMetrics* metrics) {
+  ALOGE_IF(sizeof_metrics != sizeof(DvrNativeDisplayMetrics),
+           "dvrGetNativeDisplayMetrics: metrics struct mismatch, your dvr api "
+           "header is out of date.");
+
+  auto client = DisplayClient::Create();
+  if (!client) {
+    ALOGE("dvrGetNativeDisplayMetrics: Failed to create display client!");
+    return -ECOMM;
+  }
+
+  if (metrics == nullptr) {
+    ALOGE("dvrGetNativeDisplayMetrics: output metrics buffer must be non-null");
+    return -EINVAL;
+  }
+
+  auto status = client->GetDisplayMetrics();
+
+  if (!status) {
+    return -status.error();
+  }
+
+  if (sizeof_metrics >= 20) {
+    metrics->display_width = status.get().display_width;
+    metrics->display_height = status.get().display_height;
+    metrics->display_x_dpi = status.get().display_x_dpi;
+    metrics->display_y_dpi = status.get().display_y_dpi;
+    metrics->vsync_period_ns = status.get().vsync_period_ns;
+  }
+
+  return 0;
+}
+
 }  // extern "C"
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 8a203e0..499b7c1 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -4,12 +4,22 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <unistd.h>
+#include <cstdio>
 
-#include <dvr/dvr_hardware_composer_defs.h>
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_hardware_composer_types.h>
+#include <dvr/dvr_pose.h>
 
-__BEGIN_DECLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __GNUC__
+#define ALIGNED_DVR_STRUCT(x) __attribute__((packed, aligned(x)))
+#else
+#define ALIGNED_DVR_STRUCT(x)
+#endif
 
 typedef struct ANativeWindow ANativeWindow;
 
@@ -18,7 +28,8 @@
 typedef uint64_t DvrSurfaceUpdateFlags;
 typedef struct DvrDisplayManager DvrDisplayManager;
 typedef struct DvrSurfaceState DvrSurfaceState;
-typedef struct DvrPose DvrPose;
+typedef struct DvrPoseClient DvrPoseClient;
+typedef struct DvrPoseDataCaptureRequest DvrPoseDataCaptureRequest;
 typedef struct DvrVSyncClient DvrVSyncClient;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
@@ -29,23 +40,49 @@
 
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata;
 
 typedef struct DvrSurface DvrSurface;
 typedef uint64_t DvrSurfaceAttributeType;
 typedef int32_t DvrSurfaceAttributeKey;
+typedef int32_t DvrGlobalBufferKey;
 
 typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
 typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
 
+// Note: To avoid breaking others during active development, only modify this
+// struct by appending elements to the end.
+// If you do feel we should to re-arrange or remove elements, please make a
+// note of it, and wait until we're about to finalize for an API release to do
+// so.
+typedef struct DvrNativeDisplayMetrics {
+  uint32_t display_width;
+  uint32_t display_height;
+  uint32_t display_x_dpi;
+  uint32_t display_y_dpi;
+  uint32_t vsync_period_ns;
+} DvrNativeDisplayMetrics;
+
+// native_handle contains the fds for the underlying ION allocations inside
+// the gralloc buffer. This is needed temporarily while GPU vendors work on
+// better support for AHardwareBuffer via glBindSharedBuffer APIs. See
+// b/37207909. For now we can declare the native_handle struct where it is
+// used for GPU late latching. See cutils/native_handle.h for the struct layout.
 struct native_handle;
 
+// Device metrics data type enums.
+enum {
+  // Request the device lens metrics protobuf. This matches cardboard protos.
+  DVR_CONFIGURATION_DATA_LENS_METRICS = 0,
+  // Request the device metrics protobuf.
+  DVR_CONFIGURATION_DATA_DEVICE_METRICS = 1,
+  // Request the per device configuration data file.
+  DVR_CONFIGURATION_DATA_DEVICE_CONFIG = 2,
+};
+
 // dvr_display_manager.h
 typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
 typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
-typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
-                                                    const char* name,
-                                                    size_t size, uint64_t usage,
-                                                    DvrBuffer** buffer_out);
 typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
 typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
     DvrDisplayManager* client, int in_events, int* out_events);
@@ -54,6 +91,9 @@
 typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
     DvrDisplayManager* client, int surface_id, int queue_id,
     DvrReadBufferQueue** queue_out);
+typedef int (*DvrConfigurationDataGetPtr)(int config_type, uint8_t** data,
+                                          size_t* data_size);
+typedef void (*DvrConfigurationDataDestroyPtr)(uint8_t* data);
 typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
 typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
 typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
@@ -122,26 +162,45 @@
 typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
 typedef int (*DvrBufferGetAHardwareBufferPtr)(
     DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrBufferGlobalLayoutVersionGetPtr)();
 typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
     DvrBuffer* buffer);
 
 // dvr_buffer_queue.h
+typedef int (*DvrWriteBufferQueueCreatePtr)(uint32_t width, uint32_t height,
+                                            uint32_t format,
+                                            uint32_t layer_count,
+                                            uint64_t usage, size_t capacity,
+                                            size_t metadata_size,
+                                            DvrWriteBufferQueue** queue_out);
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
 typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
 typedef int (*DvrWriteBufferQueueGetIdPtr)(DvrWriteBufferQueue* write_queue);
 typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
     DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
+typedef int (*DvrWriteBufferQueueGetANativeWindowPtr)(
+    DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
                                              int timeout,
                                              DvrWriteBuffer* out_buffer,
                                              int* out_fence_fd);
+typedef int (*DvrWriteBufferQueueGainBufferPtr)(
+    DvrWriteBufferQueue* write_queue, int timeout,
+    DvrWriteBuffer** out_write_buffer, DvrNativeBufferMetadata* out_meta,
+    int* out_fence_fd);
+typedef int (*DvrWriteBufferQueuePostBufferPtr)(
+    DvrWriteBufferQueue* write_queue, DvrWriteBuffer* write_buffer,
+    const DvrNativeBufferMetadata* meta, int ready_fence_fd);
+typedef int (*DvrWriteBufferQueueResizeBufferPtr)(
+    DvrWriteBufferQueue* write_queue, uint32_t width, uint32_t height);
 typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
 typedef ssize_t (*DvrReadBufferQueueGetCapacityPtr)(
     DvrReadBufferQueue* read_queue);
 typedef int (*DvrReadBufferQueueGetIdPtr)(DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueGetEventFdPtr)(DvrReadBufferQueue* read_queue);
 typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
     DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
@@ -149,9 +208,31 @@
                                             DvrReadBuffer* out_buffer,
                                             int* out_fence_fd, void* out_meta,
                                             size_t meta_size_bytes);
+typedef int (*DvrReadBufferQueueAcquireBufferPtr)(
+    DvrReadBufferQueue* read_queue, int timeout,
+    DvrReadBuffer** out_read_buffer, DvrNativeBufferMetadata* out_meta,
+    int* out_fence_fd);
+typedef int (*DvrReadBufferQueueReleaseBufferPtr)(
+    DvrReadBufferQueue* read_queue, DvrReadBuffer* read_buffer,
+    const DvrNativeBufferMetadata* meta, int release_fence_fd);
+typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context);
+typedef int (*DvrReadBufferQueueSetBufferAvailableCallbackPtr)(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferAvailableCallback callback, void* context);
+typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer,
+                                                        void* context);
+typedef int (*DvrReadBufferQueueSetBufferRemovedCallbackPtr)(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferRemovedCallback callback, void* context);
+typedef int (*DvrReadBufferQueueHandleEventsPtr)(
+    DvrReadBufferQueue* read_queue);
 
 // dvr_surface.h
-typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
+typedef int (*DvrSetupGlobalBufferPtr)(DvrGlobalBufferKey key, size_t size,
+                                       uint64_t usage, DvrBuffer** buffer_out);
+typedef int (*DvrDeleteGlobalBufferPtr)(DvrGlobalBufferKey key);
+typedef int (*DvrGetGlobalBufferPtr)(DvrGlobalBufferKey key,
+                                     DvrBuffer** out_buffer);
 typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
                                    size_t attribute_count,
                                    DvrSurface** surface_out);
@@ -162,10 +243,12 @@
                                           size_t attribute_count);
 typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
     DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
-    uint32_t layer_count, uint64_t usage, size_t capacity,
+    uint32_t layer_count, uint64_t usage, size_t capacity, size_t metadata_size,
     DvrWriteBufferQueue** queue_out);
+typedef int (*DvrGetNativeDisplayMetricsPtr)(size_t sizeof_metrics,
+                                             DvrNativeDisplayMetrics* metrics);
 
-// vsync_client_api.h
+// dvr_vsync.h
 typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
 typedef void (*DvrVSyncClientDestroyPtr)(DvrVSyncClient* client);
 typedef int (*DvrVSyncClientGetSchedInfoPtr)(DvrVSyncClient* client,
@@ -173,18 +256,36 @@
                                              int64_t* next_timestamp_ns,
                                              uint32_t* next_vsync_count);
 
-// pose_client.h
-typedef DvrPose* (*DvrPoseCreatePtr)(void);
-typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
-typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
-                             DvrPoseAsync* out_pose);
-typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
-typedef int (*DvrPoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
-                                       uint32_t vsync_count,
-                                       DvrPoseAsync* out_pose);
+// libs/vr/libvrsensor/include/dvr/pose_client.h
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)();
+typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
+                                   DvrPoseAsync* out_pose);
+typedef uint32_t (*DvrPoseClientGetVsyncCountPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetControllerPtr)(DvrPoseClient* client,
+                                             int32_t controller_id,
+                                             uint32_t vsync_count,
+                                             DvrPoseAsync* out_pose);
+typedef int (*DvrPoseClientSensorsEnablePtr)(DvrPoseClient* client,
+                                             bool enabled);
+typedef int (*DvrPoseClientDataCapturePtr)(DvrPoseClient* client,
+    const DvrPoseDataCaptureRequest* request);
+typedef int (*DvrPoseClientDataReaderDestroyPtr)(DvrPoseClient* client,
+                                                 uint64_t data_type);
 
-// virtual_touchpad_client.h
-typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
+// dvr_pose.h
+typedef int (*DvrPoseClientGetDataReaderPtr)(DvrPoseClient* client,
+                                             uint64_t data_type,
+                                             DvrReadBufferQueue** read_queue);
+
+// services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
+
+// Touchpad IDs for *Touch*() and *ButtonState*() calls.
+enum {
+  DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
+  DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
+};
+typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)();
 typedef void (*DvrVirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
 typedef int (*DvrVirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
 typedef int (*DvrVirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
@@ -193,6 +294,8 @@
                                           float pressure);
 typedef int (*DvrVirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client,
                                                 int touchpad, int buttons);
+typedef int (*DvrVirtualTouchpadScrollPtr)(DvrVirtualTouchpad* client,
+                                           int touchpad, float x, float y);
 
 // dvr_hardware_composer_client.h
 typedef struct DvrHwcClient DvrHwcClient;
@@ -260,13 +363,34 @@
                                                            size_t layer_index,
                                                            size_t index);
 
+// dvr_performance.h
+typedef int (*DvrPerformanceSetSchedulerPolicyPtr)(
+    pid_t task_id, const char* scheduler_policy);
+
 // The buffer metadata that an Android Surface (a.k.a. ANativeWindow)
 // will populate. A DvrWriteBufferQueue must be created with this metadata iff
 // ANativeWindow access is needed. Please do not remove, modify, or reorder
 // existing data members. If new fields need to be added, please take extra care
 // to make sure that new data field is padded properly the size of the struct
 // stays same.
-struct DvrNativeBufferMetadata {
+struct ALIGNED_DVR_STRUCT(8) DvrNativeBufferMetadata {
+#ifdef __cplusplus
+  DvrNativeBufferMetadata()
+      : timestamp(0),
+        is_auto_timestamp(0),
+        dataspace(0),
+        crop_left(0),
+        crop_top(0),
+        crop_right(0),
+        crop_bottom(0),
+        scaling_mode(0),
+        transform(0),
+        index(0),
+        user_metadata_size(0),
+        user_metadata_ptr(0),
+        release_fence_mask(0),
+        reserved{0} {}
+#endif
   // Timestamp of the frame.
   int64_t timestamp;
 
@@ -290,15 +414,36 @@
   // android/native_window.h
   int32_t transform;
 
-  // Reserved bytes for so that the struct is forward compatible.
-  int32_t reserved[16];
+  // The index of the frame.
+  int64_t index;
+
+  // Size of additional metadata requested by user.
+  uint64_t user_metadata_size;
+
+  // Raw memory address of the additional user defined metadata. Only valid when
+  // user_metadata_size is non-zero.
+  uint64_t user_metadata_ptr;
+
+  // Only applicable for metadata retrieved from GainAsync. This indicates which
+  // consumer has pending fence that producer should epoll on.
+  uint64_t release_fence_mask;
+
+  // Reserved bytes for so that the struct is forward compatible and padding to
+  // 104 bytes so the size is a multiple of 8.
+  int32_t reserved[8];
 };
 
+#ifdef __cplusplus
+// Warning: DvrNativeBufferMetadata is part of the DVR API and changing its size
+// will cause compatiblity issues between different DVR API releases.
+static_assert(sizeof(DvrNativeBufferMetadata) == 104,
+              "Unexpected size for DvrNativeBufferMetadata");
+#endif
+
 struct DvrApi_v1 {
 // Defines an API entry for V1 (no version suffix).
 #define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
 
-// Include file with API entries.
 #include "dvr_api_entries.h"
 
 // Undefine macro definitions to play nice with Google3 style rules.
@@ -307,6 +452,8 @@
 
 int dvrGetApi(void* api, size_t struct_size, int version);
 
-__END_DECLS
+#ifdef __cplusplus
+}  // extern "C"
+#endif
 
 #endif  // ANDROID_DVR_API_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 09568fd..cce8c7e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -8,14 +8,16 @@
 #error Do not include this header directly.
 #endif
 
+// Do not delete this line: BEGIN CODEGEN OUTPUT
 // Display manager client
 DVR_V1_API_ENTRY(DisplayManagerCreate);
 DVR_V1_API_ENTRY(DisplayManagerDestroy);
-DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
 DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
 DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
 DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
 DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(ConfigurationDataGet);
+DVR_V1_API_ENTRY(ConfigurationDataDestroy);
 DVR_V1_API_ENTRY(SurfaceStateCreate);
 DVR_V1_API_ENTRY(SurfaceStateDestroy);
 DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
@@ -57,14 +59,16 @@
 DVR_V1_API_ENTRY(BufferDestroy);
 DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
 DVR_V1_API_ENTRY(BufferGetNativeHandle);
+DVR_V1_API_ENTRY(BufferGlobalLayoutVersionGet);
 
 // Write buffer queue
 DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
 DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity);
 DVR_V1_API_ENTRY(WriteBufferQueueGetId);
-DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);
+DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);  // deprecated
 DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue);
 DVR_V1_API_ENTRY(WriteBufferQueueDequeue);
+DVR_V1_API_ENTRY(WriteBufferQueueResizeBuffer);
 
 // Read buffer queue
 DVR_V1_API_ENTRY(ReadBufferQueueDestroy);
@@ -72,6 +76,9 @@
 DVR_V1_API_ENTRY(ReadBufferQueueGetId);
 DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue);
 DVR_V1_API_ENTRY(ReadBufferQueueDequeue);
+DVR_V1_API_ENTRY(ReadBufferQueueSetBufferAvailableCallback);
+DVR_V1_API_ENTRY(ReadBufferQueueSetBufferRemovedCallback);
+DVR_V1_API_ENTRY(ReadBufferQueueHandleEvents);
 
 // V-Sync client
 DVR_V1_API_ENTRY(VSyncClientCreate);
@@ -84,14 +91,16 @@
 DVR_V1_API_ENTRY(SurfaceGetId);
 DVR_V1_API_ENTRY(SurfaceSetAttributes);
 DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
-DVR_V1_API_ENTRY(GetNamedBuffer);
+DVR_V1_API_ENTRY(SetupGlobalBuffer);
+DVR_V1_API_ENTRY(DeleteGlobalBuffer);
+DVR_V1_API_ENTRY(GetGlobalBuffer);
 
 // Pose client
-DVR_V1_API_ENTRY(PoseCreate);
-DVR_V1_API_ENTRY(PoseDestroy);
-DVR_V1_API_ENTRY(PoseGet);
-DVR_V1_API_ENTRY(PoseGetVsyncCount);
-DVR_V1_API_ENTRY(PoseGetController);
+DVR_V1_API_ENTRY(PoseClientCreate);
+DVR_V1_API_ENTRY(PoseClientDestroy);
+DVR_V1_API_ENTRY(PoseClientGet);
+DVR_V1_API_ENTRY(PoseClientGetVsyncCount);
+DVR_V1_API_ENTRY(PoseClientGetController);
 
 // Virtual touchpad client
 DVR_V1_API_ENTRY(VirtualTouchpadCreate);
@@ -133,3 +142,38 @@
 DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion);
 DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions);
 DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion);
+
+// New entries added at the end to allow the DVR platform library API
+// to be updated before updating VrCore.
+
+// Virtual touchpad client
+DVR_V1_API_ENTRY(VirtualTouchpadScroll);
+
+// Read the native display metrics from the hardware composer
+DVR_V1_API_ENTRY(GetNativeDisplayMetrics);
+
+// Performance
+DVR_V1_API_ENTRY(PerformanceSetSchedulerPolicy);
+
+// Pose client
+DVR_V1_API_ENTRY(PoseClientSensorsEnable);
+
+// Read buffer queue
+DVR_V1_API_ENTRY(ReadBufferQueueGetEventFd);
+
+// Create write buffer queue locally
+DVR_V1_API_ENTRY(WriteBufferQueueCreate);
+
+// Gets an ANativeWindow from DvrWriteBufferQueue.
+DVR_V1_API_ENTRY(WriteBufferQueueGetANativeWindow);
+
+// Dvr{Read,Write}BufferQueue API for asynchronous IPC.
+DVR_V1_API_ENTRY(WriteBufferQueueGainBuffer);
+DVR_V1_API_ENTRY(WriteBufferQueuePostBuffer);
+DVR_V1_API_ENTRY(ReadBufferQueueAcquireBuffer);
+DVR_V1_API_ENTRY(ReadBufferQueueReleaseBuffer);
+
+// Pose client
+DVR_V1_API_ENTRY(PoseClientGetDataReader);
+DVR_V1_API_ENTRY(PoseClientDataCapture);
+DVR_V1_API_ENTRY(PoseClientDataReaderDestroy);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index af55698..935a7b2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -95,6 +95,9 @@
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer);
 
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet();
+
 // TODO(eieio): Switch to return int and take an out parameter for the native
 // handle.
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index dd669dc..bf695c7 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -12,33 +12,265 @@
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
-// WriteBufferQueue
+// Creates a write buffer queue to be used locally.
+//
+// Note that this API is mostly for testing purpose. For now there is no
+// mechanism to send a DvrWriteBufferQueue cross process. Use
+// dvrSurfaceCreateWriteBufferQueue if cross-process buffer transport is
+// intended.
+//
+// @param width The width of the buffers that this queue will produce.
+// @param height The height of buffers that this queue will produce.
+// @param format The format of the buffers that this queue will produce. This
+//     must be one of the AHARDWAREBUFFER_FORMAT_XXX enums.
+// @param layer_count The number of layers of the buffers that this queue will
+//     produce.
+// @param usage The usage of the buffers that this queue will produce. This
+//     must a combination of the AHARDWAREBUFFER_USAGE_XXX flags.
+// @param capacity The number of buffer that this queue will allocate. Note that
+//     all buffers will be allocated on create. Currently, the number of buffers
+//     is the queue cannot be changed after creation though DVR API. However,
+//     ANativeWindow can choose to reallocate, attach, or detach buffers from
+//     a DvrWriteBufferQueue through Android platform logic.
+// @param metadata_size The size of metadata in bytes.
+// @param out_write_queue The pointer of a DvrWriteBufferQueue will be filled
+//      here if the method call succeeds. The metadata size must match
+//      the metadata size in dvrWriteBufferPost/dvrReadBufferAcquire.
+// @return Zero on success, or negative error code.
+int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format,
+                              uint32_t layer_count, uint64_t usage,
+                              size_t capacity, size_t metadata_size,
+                              DvrWriteBufferQueue** out_write_queue);
+
+// Destroy a write buffer queue.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+
+// Get the total number of buffers in a write buffer queue.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
+// @return The capacity on success; or negative error code.
 ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+
+// Get the system unique queue id of a write buffer queue.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
+// @return Queue id on success; or negative error code.
 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue);
 
-// Returns ANativeWindow. Can be casted to a Java Surface using
-// ANativeWindow_toSurface NDK API. Note that this method does not acquire an
-// additional reference to the ANativeWindow returned, don't call
-// ANativeWindow_release on it.
+// Gets an ANativeWindow backed by the DvrWriteBufferQueue
+//
+// Can be casted to a Java Surface using ANativeWindow_toSurface NDK API. Note
+// that the native window is lazily created at the first time |GetNativeWindow|
+// is called, and the created ANativeWindow will be cached so that multiple
+// calls to this method will return the same object. Also note that this method
+// does not acquire an additional reference to the ANativeWindow returned, don't
+// call ANativeWindow_release on it.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
+// @param out_window The pointer of an ANativeWindow will be filled here if
+//     the method call succeeds.
+// @return Zero on success; or -EINVAL if this DvrWriteBufferQueue does not
+//     support being used as an android Surface.
+int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue,
+                                        ANativeWindow** out_window);
+
+// @deprecated Please use dvrWriteBufferQueueGetANativeWindow instead.
 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
                                           ANativeWindow** out_window);
 
+// Create a read buffer queue from an existing write buffer queue.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
+// @param out_read_queue The pointer of a DvrReadBufferQueue will be filled here
+//     if the method call succeeds.
+// @return Zero on success, or negative error code.
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
+
+// @deprecated Please use dvrWriteBufferQueueGainBuffer instead.
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
                                DvrWriteBuffer* out_buffer, int* out_fence_fd);
 
-// ReadeBufferQueue
+// Gains a buffer to write into.
+//
+// @param write_queue The DvrWriteBufferQueue to gain buffer from.
+// @param timeout Specifies the number of milliseconds that the method will
+//     block. Specifying a timeout of -1 causes it to block indefinitely,
+//     while specifying a timeout equal to zero cause it to return immediately,
+//     even if no buffers are available.
+// @param out_buffer A targeting DvrWriteBuffer object to hold the output of the
+//     dequeue operation.
+// @param out_meta A DvrNativeBufferMetadata object populated by the
+//     corresponding dvrReadBufferQueueReleaseBuffer API.
+// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which
+//     signals the release of underlying buffer. The producer should wait until
+//     this fence clears before writing data into it.
+// @return Zero on success, or negative error code.
+int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
+                                  DvrWriteBuffer** out_write_buffer,
+                                  DvrNativeBufferMetadata* out_meta,
+                                  int* out_fence_fd);
+
+// Posts a buffer and signals its readiness to be read from.
+//
+// @param write_queue The DvrWriteBufferQueue to post buffer into.
+// @param write_buffer The buffer to be posted.
+// @param meta The buffer metadata describing the buffer.
+// @param ready_fence_fd  A sync fence fd defined in NDK's sync.h API, which
+//     signals the readdiness of underlying buffer. When a valid fence gets
+//     passed in, the consumer will wait the fence to be ready before it starts
+//     to ready from the buffer.
+// @return Zero on success, or negative error code.
+int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
+                                  DvrWriteBuffer* write_buffer,
+                                  const DvrNativeBufferMetadata* meta,
+                                  int ready_fence_fd);
+
+// Overrides buffer dimension with new width and height.
+//
+// After the call successfully returns, each |dvrWriteBufferQueueDequeue| call
+// will return buffer with newly assigned |width| and |height|. When necessary,
+// old buffer will be removed from the buffer queue and replaced with new buffer
+// matching the new buffer size.
+//
+// @param write_queue The DvrWriteBufferQueue of interest.
+// @param width Desired width, cannot be Zero.
+// @param height Desired height, cannot be Zero.
+// @return Zero on success, or negative error code.
+int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue,
+                                    uint32_t width, uint32_t height);
+
+// Destroy a read buffer queue.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+
+// Get the total number of buffers in a read buffer queue.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @return The capacity on success; or negative error code.
 ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+
+// Get the system unique queue id of a read buffer queue.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @return Queue id on success; or negative error code.
 int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue);
+
+// Get the event fd that signals when queue updates occur.
+//
+// Use ReadBufferQueueHandleEvents to trigger registered event callbacks.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @return Fd on success; or negative error code.
+int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue);
+
+// Create a read buffer queue from an existing read buffer queue.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @param out_read_queue The pointer of a DvrReadBufferQueue will be filled here
+//     if the method call succeeds.
+// @return Zero on success, or negative error code.
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue);
+
+// @deprecated Please use dvrReadBufferQueueAcquireBuffer instead.
 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
                               DvrReadBuffer* out_buffer, int* out_fence_fd,
                               void* out_meta, size_t meta_size_bytes);
 
+// Dequeues a buffer to read from.
+//
+// @param read_queue The DvrReadBufferQueue to acquire buffer from.
+// @param timeout Specifies the number of milliseconds that the method will
+//     block. Specifying a timeout of -1 causes it to block indefinitely,
+//     while specifying a timeout equal to zero cause it to return immediately,
+//     even if no buffers are available.
+// @param out_buffer A targeting DvrReadBuffer object to hold the output of the
+//     dequeue operation. Must be created by |dvrReadBufferCreateEmpty|.
+// @param out_meta A DvrNativeBufferMetadata object populated by the
+//     corresponding dvrWriteBufferQueuePostBuffer API.
+// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which
+//     signals the release of underlying buffer. The consumer should wait until
+//     this fence clears before reading data from it.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
+                                    DvrReadBuffer** out_read_buffer,
+                                    DvrNativeBufferMetadata* out_meta,
+                                    int* out_fence_fd);
+
+// Releases a buffer and signals its readiness to be written into.
+//
+// @param read_queue The DvrReadBufferQueue to release buffer into.
+// @param read_buffer The buffer to be released.
+// @param meta The buffer metadata describing the buffer.
+// @param release_fence_fd A sync fence fd defined in NDK's sync.h API, which
+//     signals the readdiness of underlying buffer. When a valid fence gets
+//     passed in, the producer will wait the fence to be ready before it starts
+//     to write into the buffer again.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
+                                    DvrReadBuffer* read_buffer,
+                                    const DvrNativeBufferMetadata* meta,
+                                    int release_fence_fd);
+
+// Callback function which will be called when a buffer is avaiable.
+//
+// Note that there is no guarantee of thread safety and on which thread the
+// callback will be fired.
+//
+// @param context User provided opaque pointer.
+typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context);
+
+// Set buffer avaiable callback.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @param callback The callback function. Set this to NULL if caller no longer
+//     needs to listen to new buffer available events.
+// @param context User provided opaque pointer, will be passed back during
+//     callback. The caller is responsible for ensuring the validity of the
+//     context through the life cycle of the DvrReadBufferQueue.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueSetBufferAvailableCallback(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferAvailableCallback callback, void* context);
+
+// Callback function which will be called when a buffer is about to be removed.
+//
+// Note that there is no guarantee of thread safety and on which thread the
+// callback will be fired.
+//
+// @param buffer The buffer being removed. Once the callbacks returns, this
+//     buffer will be dereferenced from the buffer queue. If user has ever
+//     cached other DvrReadBuffer/AHardwareBuffer/EglImageKHR objects derived
+//     from this buffer, it's the user's responsibility to clean them up.
+//     Note that the ownership of the read buffer is not passed to this
+//     callback, so it should call dvrReadBufferDestroy on the buffer.
+// @param context User provided opaque pointer.
+typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer,
+                                                        void* context);
+
+// Set buffer removed callback.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @param callback The callback function. Set this to NULL if caller no longer
+//     needs to listen to buffer removed events.
+// @param context User provided opaque pointer, will be passed back during
+//     callback. The caller is responsible for ensuring the validity of the
+//     context through the life cycle of the DvrReadBufferQueue.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueSetBufferRemovedCallback(
+    DvrReadBufferQueue* read_queue,
+    DvrReadBufferQueueBufferRemovedCallback callback, void* context);
+
+// Handle all pending events on the read queue.
+//
+// @param read_queue The DvrReadBufferQueue of interest.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueHandleEvents(DvrReadBufferQueue* read_queue);
+
 __END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_config.h b/libs/vr/libdvr/include/dvr/dvr_config.h
new file mode 100644
index 0000000..3d2c066
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_config.h
@@ -0,0 +1,34 @@
+#ifndef ANDROID_DVR_CONFIG_H
+#define ANDROID_DVR_CONFIG_H
+
+// This header is shared by VrCore and Android and must be kept in sync.
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// This is a shared memory buffer for passing config data from VrCore to
+// libvrflinger in SurfaceFlinger.
+struct __attribute__((packed, aligned(16))) DvrConfig {
+  // Offset before vsync to submit frames to hardware composer.
+  int32_t frame_post_offset_ns{4000000};
+
+  // If the number of pending fences goes over this count at the point when we
+  // are about to submit a new frame to HWC, we will drop the frame. This
+  // should be a signal that the display driver has begun queuing frames. Note
+  // that with smart displays (with RAM), the fence is signaled earlier than
+  // the next vsync, at the point when the DMA to the display completes.
+  // Currently we use a smart display and the EDS timing coincides with zero
+  // pending fences, so this is 0.
+  int32_t allowed_pending_fence_count{0};
+
+  // New fields should always be added to the end for backwards compat.
+
+  // Reserved padding to 16 bytes.
+  uint8_t pad[8];
+};
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_configuration_data.h b/libs/vr/libdvr/include/dvr/dvr_configuration_data.h
new file mode 100644
index 0000000..22a509f
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_configuration_data.h
@@ -0,0 +1,24 @@
+#ifndef DVR_CONFIGURATION_DATA_H_
+#define DVR_CONFIGURATION_DATA_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_surface.h>
+
+__BEGIN_DECLS
+
+// Loads device configuration data of DVR_CONFIGURATION_DATA_*.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrConfigurationDataGet(int config_type,
+                            uint8_t** data, size_t* data_size);
+
+// Destroy the configuration data returned from dvrGetConfigurationData.
+void dvrConfigurationDataDestroy(uint8_t* data);
+
+__END_DECLS
+
+#endif  // DVR_CONFIGURATION_DATA_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
index d5aef8b..f910d61 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -1,5 +1,5 @@
-#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
-#define DVR_DISPLAY_MANAGER_CLIENT_H_
+#ifndef ANDROID_DVR_DISPLAY_MANAGER_H_
+#define ANDROID_DVR_DISPLAY_MANAGER_H_
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -25,13 +25,6 @@
 // Destroys the display manager client object.
 void dvrDisplayManagerDestroy(DvrDisplayManager* client);
 
-// Sets up a named buffer for shared memory data transfer between display
-// clients and the display manager.
-// @return 0 on success. Otherwise returns a negative error value.
-int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
-                                      const char* name, size_t size,
-                                      uint64_t usage, DvrBuffer** buffer_out);
-
 // Returns an fd used to signal when surface updates occur. Note that depending
 // on the underlying transport, only a subset of the real event bits may be
 // supported. Use dvrDisplayManagerClientTranslateEpollEventMask to get the real
@@ -76,7 +69,7 @@
                                    size_t* count_out);
 
 // Returns the update flags for the surface at |surface_index| in the state
-// object. The flags may be used to determine what changes, if any, occured to
+// object. The flags may be used to determine what changes, if any, occurred to
 // the surface since the last state update.
 // @return 0 on success. Otherwise returns a negative error value.
 int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
@@ -137,4 +130,4 @@
 
 __END_DECLS
 
-#endif  // DVR_DISPLAY_MANAGER_CLIENT_H_
+#endif  // ANDROID_DVR_DISPLAY_MANAGER_H_
diff --git a/libs/vr/libdisplay/include/dvr/dvr_display_types.h b/libs/vr/libdvr/include/dvr/dvr_display_types.h
similarity index 100%
rename from libs/vr/libdisplay/include/dvr/dvr_display_types.h
rename to libs/vr/libdvr/include/dvr/dvr_display_types.h
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 7ee7f9e..0ba76e2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -1,7 +1,7 @@
 #ifndef ANDROID_DVR_HARDWARE_COMPOSER_CLIENT_H
 #define ANDROID_DVR_HARDWARE_COMPOSER_CLIENT_H
 
-#include <dvr/dvr_hardware_composer_defs.h>
+#include <dvr/dvr_hardware_composer_types.h>
 #include <stdbool.h>
 
 #ifdef __cplusplus
@@ -24,37 +24,73 @@
 DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback,
                                  void* client_state);
 
+// Called to free the DvrHwcClient pointer.
 void dvrHwcClientDestroy(DvrHwcClient* client);
 
 // Called to free the frame information.
+// @param frame Pointer for the valid frame used for the query.
 void dvrHwcFrameDestroy(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return Identifier for the display associated by the frame.
 DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return width of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
 int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return height of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
 int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
 // @return True if the display has been removed. In this case the current frame
 // does not contain any valid layers to display. It is a signal to clean up any
 // display related state.
 bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
 // @return Number of layers in the frame.
 size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the currently active display configuration.
 uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the current color mode. See HAL_COLOR_MODE_* for valid
+// values.
 uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param out_matrix Output parameter for a float[16] array which will be filled
+// with the color transform matrix.
+// @param out_hint Output parameter which will contain the color transform hint.
+// See HAL_COLOR_TRANSFORM_* for valid values.
 void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
                                   int32_t* out_hint);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current power mode for the display. See HWC2_POWER_MODE_* for
+// valid values.
 uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current state of vsync. See HWC2_VSYNC_* for valid values.
 uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return A unique ID for the layer.
 DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
 
 // Return the graphic buffer associated with the layer at |layer_index| in
 // |frame|.
 //
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
 // @return Graphic buffer. Caller owns the buffer and is responsible for freeing
 // it. (see AHardwareBuffer_release())
 AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame,
@@ -62,42 +98,98 @@
 
 // Returns the fence FD for the layer at index |layer_index| in |frame|.
 //
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
 // @return Fence FD. Caller owns the FD and is responsible for closing it.
 int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the display covered by the layer. Will
+// not exceed the display dimensions.
 DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
                                             size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the layer that will fill the display
+// frame. Will not exceed the layer dimensions.
 DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The blend mode of the layer.
 DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
                                              size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The alpha value to be applied to the whole layer. Will be in the
+// [0.0, 1.0] range.
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The type of the layer assigned by the window manager.
 uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The application id the layer belongs to.
 uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
                                           size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The z-order for the layer.
 uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param out_x Output parameter for the x coordinate of the cursor location.
+// @param out_y Output parameter for the y coordinate of the cursor location.
 void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
                                int32_t* out_x, int32_t* out_y);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The transformation that needs to be applied to the layer before
+// presenting it. See DVR_HWC_TRANSFORM_* for valid values.
 uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The dataspace which represents how the pixel values should be
+// interpreted. See HAL_DATASPACE_* for valid values.
 uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The color of the layer if layer composition is SOLID_COLOR.
 uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of visible regions.
 uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
                                               size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the visible region for the layer.
+// @return The rectangle describing the visible region.
 DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
                                              size_t layer_index, size_t index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of damanged regions.
 uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
                                               size_t layer_index);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the damanged region for the layer.
+// @return The rectangle describing the damaged region.
 DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
                                              size_t layer_index, size_t index);
 #ifdef __cplusplus
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
similarity index 82%
rename from libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
rename to libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
index 36c30f9..1d5eda6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
@@ -26,6 +26,15 @@
   DVR_HWC_COMPOSITION_SIDEBAND = 5,
 };
 
+enum DvrHwcTransform {
+  DVR_HWC_TRANSFORM_NONE = 0,
+  DVR_HWC_TRANSFORM_FLIP_H = 1,
+  DVR_HWC_TRANSFORM_FLIP_V = 2,
+  DVR_HWC_TRANSFORM_ROT_90 = 4,
+  DVR_HWC_TRANSFORM_ROT_180 = 3,
+  DVR_HWC_TRANSFORM_ROT_270 = 7,
+};
+
 typedef uint64_t DvrHwcDisplay;
 typedef uint64_t DvrHwcLayer;
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_performance.h b/libs/vr/libdvr/include/dvr/dvr_performance.h
new file mode 100644
index 0000000..5df35ad
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_performance.h
@@ -0,0 +1,26 @@
+#ifndef ANDROID_DVR_PERFORMANCE_H_
+#define ANDROID_DVR_PERFORMANCE_H_
+
+#include <stddef.h>
+#include <unistd.h>
+
+__BEGIN_DECLS
+
+/// Sets the scheduler policy for a task.
+///
+/// Sets the scheduler policy for a task to the class described by a semantic
+/// string.
+///
+/// Supported policies are device-specific.
+///
+/// @param task_id The task id of task to set the policy for. When task_id is 0
+/// the current task id is substituted.
+/// @param scheduler_policy NULL-terminated ASCII string containing the desired
+/// scheduler policy.
+/// @returns Returns 0 on success or a negative errno error code on error.
+int dvrPerformanceSetSchedulerPolicy(pid_t task_id, const char* scheduler_policy);
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_PERFORMANCE_H_
+
diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h
new file mode 100644
index 0000000..8752751
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_pose.h
@@ -0,0 +1,154 @@
+#ifndef ANDROID_DVR_PUBLIC_POSE_H_
+#define ANDROID_DVR_PUBLIC_POSE_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#ifdef __ARM_NEON
+#include <arm_neon.h>
+#else
+#ifndef __FLOAT32X4T_86
+#define __FLOAT32X4T_86
+typedef float float32x4_t __attribute__((__vector_size__(16)));
+#endif
+#endif
+
+typedef struct DvrPoseClient DvrPoseClient;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+// Represents an estimated pose, accessed asynchronously through a shared ring
+// buffer. No assumptions should be made about the data in padding space.
+// The size of this struct is 128 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
+  // Left eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+  // Left eye head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+  // Right eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t right_orientation;
+  // Right eye head-from-start position x,y,z,pad in meters.
+  float32x4_t right_position;
+  // Start-space angular velocity x,y,z,pad in radians per second.
+  float32x4_t angular_velocity;
+  // Start-space positional velocity x,y,z,pad in meters per second.
+  float32x4_t velocity;
+  // Timestamp of when this pose is predicted for, typically halfway through
+  // scanout.
+  int64_t timestamp_ns;
+  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
+  //
+  // If DVR_POSE_FLAG_INVALID is set, the pose is indeterminate.
+  uint64_t flags;
+  // Reserved padding to 128 bytes.
+  uint8_t pad[16];
+} DvrPoseAsync;
+
+enum {
+  DVR_POSE_FLAG_INVALID = (1ULL << 0),       // This pose is invalid.
+  DVR_POSE_FLAG_INITIALIZING = (1ULL << 1),  // The pose delivered during
+                                             // initialization and it may not be
+                                             // correct.
+  DVR_POSE_FLAG_3DOF =
+      (1ULL << 2),  // This pose is derived from 3Dof sensors. If
+                    // this is not set, pose is derived using
+                    // 3Dof and 6Dof sensors.
+  DVR_POSE_FLAG_FLOOR_HEIGHT_INVALID =
+      (1ULL << 3),  // If set the floor height is invalid.
+
+  // Bits that indicate the tracking system state.
+  DVR_POSE_FLAG_SERVICE_EXCEPTION = (1ULL << 32),
+  DVR_POSE_FLAG_FISHEYE_OVER_EXPOSED = (1ULL << 33),
+  DVR_POSE_FLAG_FISHEYE_UNDER_EXPOSED = (1ULL << 34),
+  DVR_POSE_FLAG_COLOR_OVER_EXPOSED = (1ULL << 35),
+  DVR_POSE_FLAG_COLOR_UNDER_EXPOSED = (1ULL << 36),
+  DVR_POSE_FLAG_TOO_FEW_FEATURES_TRACKED = (1ULL << 37)
+};
+
+// Represents a sensor pose sample.
+typedef struct __attribute__((packed, aligned(16))) DvrPose {
+  // Head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+
+  // The angular velocity where the x,y,z is the rotation axis and the
+  // magnitude is the radians / second in the same coordinate frame as
+  // orientation.
+  float32x4_t angular_velocity;
+
+  // Head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+
+  // In meters / second in the same coordinate frame as position.
+  float32x4_t velocity;
+
+  // In meters / second ^ 2 in the same coordinate frame as position.
+  float32x4_t acceleration;
+
+  // Timestamp for the measurement in nanoseconds.
+  int64_t timestamp_ns;
+
+  // The combination of flags above.
+  uint64_t flags;
+
+  // The current floor height. May be updated at a lower cadence than pose.
+  float floor_height;
+
+  // Padding to 112 bytes so the size is a multiple of 16.
+  uint8_t padding[12];
+} DvrPose;
+
+// Represents a data type that can be streamed from pose service.
+enum {
+  DVR_POSE_RAW_DATA_STEREO_IMAGE = (1ULL << 0),
+  DVR_POSE_RAW_DATA_POINT_CLOUD = (1ULL << 1),
+  DVR_POSE_RAW_DATA_FEATURES = (1ULL << 2),
+
+  // Always last.
+  DVR_POSE_RAW_DATA_COUNT = (1ULL << 3),
+};
+
+// A request to retrieve data from the pose service. Expects that a buffer
+// queue has been initialized through dvrPoseClientGetDataReader().
+typedef struct DvrPoseDataCaptureRequest {
+  // The type of data to capture. Refer to enum DVR_POSE_RAW_DATA_* for types.
+  uint64_t data_type;
+  // The sample interval. This can be used to skip samples. For example, a
+  // value of 5 will capture every fifth frame and discard the 4 frames in
+  // between. Set to 1 to capture all frames.
+  uint32_t sample_interval;
+  // The length of time to capture samples in milliseconds. Set to 0 to capture
+  // indefinitely.
+  uint32_t capture_time_ms;
+  // Reserved fields.
+  uint32_t reserved0;
+  uint32_t reserved1;
+  uint32_t reserved2;
+  uint32_t reserved3;
+  uint32_t reserved4;
+} DvrPoseDataCaptureRequest;
+
+// Gets a read buffer queue for the data type |data_type|. Each call returns a
+// different read buffer queue connected to the same write buffer queue. A
+// separate write buffer queue exists for each |data_type|.
+//
+// PoseService supports a single consumer per write buffer queue. The consumer
+// is expected to hold a single DvrReadBufferQueue at a time. Callers should
+// cache these instead of requesting new ones when possible. If the consumer
+// disconnects from the queue, it can regain a read buffer queue for the same
+// producer by calling this function.
+//
+// For data_type DVR_POSE_RAW_DATA_STEREO_IMAGE, each buffer consists of two
+// images formatted as a AHARDWAREBUFFER_FORMAT_BLOB, where height is 1 and
+// width is the total size of both images. The size of an individual image can
+// be found in the metadata struct DvrNativeBufferMetadata, where width is
+// |crop_right| and height is |crop_bottom|/2. Each image is contiguous in
+// memory with stride equal to width.
+int dvrPoseClientGetDataReader(DvrPoseClient* client, uint64_t data_type,
+                               DvrReadBufferQueue** queue_out);
+
+// TODO(b/65067592): Move pose api's from pose_client.h to here.
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_PUBLIC_POSE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
new file mode 100644
index 0000000..63c7385
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -0,0 +1,102 @@
+#ifndef ANDROID_DVR_SHARED_BUFFERS_H_
+#define ANDROID_DVR_SHARED_BUFFERS_H_
+
+#include <dvr/dvr_config.h>
+#include <dvr/dvr_pose.h>
+#include <dvr/dvr_vsync.h>
+#include <libbroadcastring/broadcast_ring.h>
+
+// This header is shared by VrCore and Android and must be kept in sync.
+namespace android {
+namespace dvr {
+
+// Increment when the layout for the buffers change.
+enum : uint32_t { kSharedBufferLayoutVersion = 2 };
+
+// Note: These buffers will be mapped from various system processes as well
+// as VrCore and the application processes in a r/w manner.
+//
+// Therefore it is possible for the application to mess with the contents of
+// these buffers.
+//
+// While using them, assume garbage memory: Your logic must not crash or lead
+// to execution of unsafe code as a function of the contents of these buffers.
+
+// Sanity check for basic type sizes.
+static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
+static_assert(sizeof(DvrPose) == 112, "Unexpected size for DvrPose");
+static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+static_assert(sizeof(DvrConfig) == 16, "Unexpected size for DvrConfig");
+
+// A helper class that provides compile time sized traits for the BroadcastRing.
+template <class DvrType, size_t StaticCount>
+class DvrRingBufferTraits {
+ public:
+  using Record = DvrType;
+  static constexpr bool kUseStaticRecordSize = false;
+  static constexpr uint32_t kStaticRecordCount = StaticCount;
+  static constexpr int kMaxReservedRecords = 1;
+  static constexpr int kMinAvailableRecords = 1;
+};
+
+// Traits classes.
+using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
+using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
+using DvrConfigTraits = DvrRingBufferTraits<DvrConfig, 2>;
+
+// The broadcast ring classes that will expose the data.
+using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
+using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
+using DvrConfigRing = BroadcastRing<DvrConfig, DvrConfigTraits>;
+
+// This is a shared memory buffer for passing pose data estimated at vsyncs.
+//
+// This will be primarily used for late latching and EDS where we bind this
+// buffer in a shader and extract the right vsync-predicted pose.
+struct __attribute__((packed, aligned(16))) DvrVsyncPoseBuffer {
+  enum : int {
+    // The number vsync predicted poses to keep in the ring buffer.
+    // Must be a power of 2.
+    kSize = 8,
+    kIndexMask = kSize - 1,
+
+    // The number of vsyncs (from the current vsync) we predict in vsync buffer.
+    // The other poses are left alone.
+    kMinFutureCount = 4
+  };
+
+  // The vsync predicted poses.
+  // The pose for the vsync n is:
+  // vsync_poses[n % kSize]
+  //
+  // This buffer is unsynchronized: It is possible to get torn reads as the
+  // sensor service updates the predictions as new sensor measurements come
+  // in. In particular, it is possible to get the position and an updated
+  // orientation while reading.
+  DvrPoseAsync vsync_poses[kSize];
+
+  // The latest sensor pose for GPU usage.
+  DvrPose current_pose;
+
+  // Current vsync_count (where sensord is writing poses from).
+  uint32_t vsync_count;
+
+  // For 16 byte alignment.
+  uint8_t padding[12];
+};
+
+static_assert(sizeof(DvrVsyncPoseBuffer) == 1152,
+              "Unexpected size for DvrVsyncPoseBuffer");
+
+// The keys for the dvr global buffers.
+enum DvrGlobalBuffers : int32_t {
+  kVsyncPoseBuffer = 1,
+  kVsyncBuffer = 2,
+  kSensorPoseBuffer = 3,
+  kVrFlingerConfigBufferKey = 4
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFERS_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 361488e..74a68a1 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -6,16 +6,13 @@
 #include <stdint.h>
 #include <sys/cdefs.h>
 
+#include <dvr/dvr_api.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
 #include <dvr/dvr_display_types.h>
 
 __BEGIN_DECLS
 
-typedef struct DvrBuffer DvrBuffer;
-typedef struct DvrSurface DvrSurface;
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
-
 // Attribute types. The values are one-hot encoded to support singluar types or
 // masks of supported types.
 enum {
@@ -79,12 +76,37 @@
 int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
                                      uint32_t height, uint32_t format,
                                      uint32_t layer_count, uint64_t usage,
-                                     size_t capacity,
+                                     size_t capacity, size_t metadata_size,
                                      DvrWriteBufferQueue** queue_out);
 
-// Get a named buffer from the display service.
+// Sets up a named buffer for shared memory data transfer between display
+// clients and the system. Protected API that may only be called with sufficient
+// privilege.
 // @return 0 on success. Otherwise returns a negative error value.
-int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
+int dvrSetupGlobalBuffer(DvrGlobalBufferKey key, size_t size, uint64_t usage,
+                         DvrBuffer** buffer_out);
+
+// Deletes a named buffer. WARNING: This is dangerous because any existing
+// clients of this buffer will not be notified and will remain attached to
+// the old buffer. This is useful for tests, but probably not for production
+// code.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDeleteGlobalBuffer(DvrGlobalBufferKey key);
+
+// Get a global buffer from the display service.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrGetGlobalBuffer(DvrGlobalBufferKey key, DvrBuffer** out_buffer);
+
+// Read the native device display metrics as reported by the hardware composer.
+// This is useful as otherwise the device metrics are only reported as
+// relative to the current device orientation.
+// @param sizeof_metrics the size of the passed in metrics struct. This is used
+//   to ensure we don't break each other during active development.
+// @param metrics on success holds the retrieved device metrics.
+// @return 0 on success. Otherwise returns a negative error value (typically
+//   this means the display service is not available).
+int dvrGetNativeDisplayMetrics(size_t metrics_struct_size,
+                               DvrNativeDisplayMetrics* metrics);
 
 __END_DECLS
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
index 1eea3d9..87fdf31 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vsync.h
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -8,6 +8,27 @@
 
 typedef struct DvrVSyncClient DvrVSyncClient;
 
+// Represents a vsync sample. The size of this struct is 32 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrVsync {
+  // The timestamp for the last vsync in nanoseconds.
+  uint64_t vsync_timestamp_ns;
+
+  // The index of the last vsync.
+  uint32_t vsync_count;
+
+  // Scan out for the left eye = vsync_timestamp_ns + vsync_left_eye_offset_ns.
+  int32_t vsync_left_eye_offset_ns;
+
+  // Scan out for the right eye = vsync_timestamp_ns + vsync_right_eye_offset_ns
+  int32_t vsync_right_eye_offset_ns;
+
+  // The period of a vsync in nanoseconds.
+  uint32_t vsync_period_ns;
+
+  // Padding to 32 bytes so the size is a multiple of 16.
+  uint8_t padding[8];
+} DvrVsync;
+
 // Creates a new client to the system vsync service.
 int dvrVSyncClientCreate(DvrVSyncClient** client_out);
 
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index ef746e2..887766a 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -32,6 +32,7 @@
     "libdvrcommon",
     "libdisplay",
     "libpdx_default_transport",
+    "libbroadcastring",
 ]
 
 cc_test {
@@ -41,11 +42,13 @@
         "dvr_named_buffer-test.cpp",
     ],
 
+    header_libs: ["libdvr_headers"],
     static_libs: static_libraries,
     shared_libs: shared_libraries,
     cflags: [
         "-DLOG_TAG=\"dvr_api-test\"",
         "-DTRACE=0",
+        "-Wno-missing-field-initializers",
         "-O0",
         "-g",
     ],
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 474e968..62cd8d4 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -1,35 +1,45 @@
+#include <android/log.h>
+#include <android/native_window.h>
+#include <android-base/unique_fd.h>
 #include <dvr/dvr_api.h>
 #include <dvr/dvr_buffer_queue.h>
-#include <gui/Surface.h>
-#include <private/dvr/buffer_hub_queue_client.h>
 
-#include <base/logging.h>
 #include <gtest/gtest.h>
 
-#include "../dvr_internal.h"
+#include <array>
+#include <unordered_map>
 
-namespace android {
-namespace dvr {
+#ifndef ALOGD
+#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#endif
+
+#ifndef ALOGD_IF
+#define ALOGD_IF(cond, ...) \
+  ((__predict_false(cond)) ? ((void)ALOGD(__VA_ARGS__)) : (void)0)
+#endif
 
 namespace {
 
-static constexpr int kBufferWidth = 100;
-static constexpr int kBufferHeight = 1;
-static constexpr int kLayerCount = 1;
-static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
-static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+static constexpr uint32_t kBufferWidth = 100;
+static constexpr uint32_t kBufferHeight = 1;
+static constexpr uint32_t kLayerCount = 1;
+static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB;
+static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
 static constexpr size_t kQueueCapacity = 3;
 
-typedef uint64_t TestMeta;
-
 class DvrBufferQueueTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
-        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
-    ASSERT_NE(nullptr, write_queue_);
+ public:
+  static void BufferAvailableCallback(void* context) {
+    DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
+    thiz->HandleBufferAvailable();
   }
 
+  static void BufferRemovedCallback(DvrReadBuffer* buffer, void* context) {
+    DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context);
+    thiz->HandleBufferRemoved(buffer);
+  }
+
+ protected:
   void TearDown() override {
     if (write_queue_ != nullptr) {
       dvrWriteBufferQueueDestroy(write_queue_);
@@ -37,35 +47,52 @@
     }
   }
 
-  void AllocateBuffers(size_t buffer_count) {
-    size_t out_slot;
-    for (size_t i = 0; i < buffer_count; i++) {
-      int ret = GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
-                    ->AllocateBuffer(kBufferWidth, kBufferHeight, kLayerCount,
-                                     kBufferFormat, kBufferUsage, &out_slot);
-      ASSERT_EQ(0, ret);
-    }
+  void HandleBufferAvailable() {
+    buffer_available_count_ += 1;
+    ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_);
+  }
+
+  void HandleBufferRemoved(DvrReadBuffer* buffer) {
+    buffer_removed_count_ += 1;
+    ALOGD_IF(TRACE, "Buffer removed, buffer=%p, count=%d", buffer,
+             buffer_removed_count_);
   }
 
   DvrWriteBufferQueue* write_queue_{nullptr};
+  int buffer_available_count_{0};
+  int buffer_removed_count_{0};
 };
 
-TEST_F(DvrBufferQueueTest, TestWrite_QueueDestroy) {
+TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
   dvrWriteBufferQueueDestroy(write_queue_);
   write_queue_ = nullptr;
 }
 
-TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
-  AllocateBuffers(kQueueCapacity);
+TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
   size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
 
   ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
   ASSERT_EQ(kQueueCapacity, capacity);
 }
 
-TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
+TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
   DvrReadBufferQueue* read_queue = nullptr;
-  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
 
   ASSERT_EQ(0, ret);
   ASSERT_NE(nullptr, read_queue);
@@ -73,10 +100,15 @@
   dvrReadBufferQueueDestroy(read_queue);
 }
 
-TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
+TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
   DvrReadBufferQueue* read_queue1 = nullptr;
   DvrReadBufferQueue* read_queue2 = nullptr;
-  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
+  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
 
   ASSERT_EQ(0, ret);
   ASSERT_NE(nullptr, read_queue1);
@@ -90,90 +122,86 @@
   dvrReadBufferQueueDestroy(read_queue2);
 }
 
-TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
-  AllocateBuffers(3);
+TEST_F(DvrBufferQueueTest, GainBuffer) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(ret, 0);
 
-  DvrReadBuffer* read_buffer = nullptr;
-  DvrWriteBuffer* write_buffer = nullptr;
+  DvrWriteBuffer* wb = nullptr;
+  EXPECT_FALSE(dvrWriteBufferIsValid(wb));
 
-  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
-  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
-
-  dvrReadBufferCreateEmpty(&read_buffer);
-  ASSERT_NE(nullptr, read_buffer);
-
-  dvrWriteBufferCreateEmpty(&write_buffer);
-  ASSERT_NE(nullptr, write_buffer);
-
-  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
-  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
-
-  DvrReadBufferQueue* read_queue = nullptr;
-
-  ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
-
-  const int kTimeoutMs = 0;
+  DvrNativeBufferMetadata meta;
   int fence_fd = -1;
-  ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
-                                          write_buffer, &fence_fd));
-  EXPECT_EQ(-1, fence_fd);
-  EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
-
-  ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
-  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+  ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta,
+                                      &fence_fd);
+  ASSERT_EQ(ret, 0);
+  EXPECT_EQ(fence_fd, -1);
+  EXPECT_NE(wb, nullptr);
+  EXPECT_TRUE(dvrWriteBufferIsValid(wb));
 }
 
-TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
-  static constexpr int kTimeout = 0;
+TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(ret, 0);
+
   DvrReadBufferQueue* read_queue = nullptr;
   DvrReadBuffer* rb = nullptr;
   DvrWriteBuffer* wb = nullptr;
+  DvrNativeBufferMetadata meta1;
+  DvrNativeBufferMetadata meta2;
   int fence_fd = -1;
 
-  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
 
-  ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, read_queue);
+  ASSERT_EQ(ret, 0);
+  ASSERT_NE(read_queue, nullptr);
 
-  dvrWriteBufferCreateEmpty(&wb);
-  ASSERT_NE(nullptr, wb);
-
-  dvrReadBufferCreateEmpty(&rb);
-  ASSERT_NE(nullptr, rb);
-
-  AllocateBuffers(kQueueCapacity);
+  dvrReadBufferQueueSetBufferAvailableCallback(read_queue,
+                                               &BufferAvailableCallback, this);
 
   // Gain buffer for writing.
-  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
-  ASSERT_EQ(0, ret);
+  ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta1,
+                                      &fence_fd);
+  ASSERT_EQ(ret, 0);
+  ASSERT_NE(wb, nullptr);
   ASSERT_TRUE(dvrWriteBufferIsValid(wb));
   ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
            wb, fence_fd);
-  pdx::LocalHandle release_fence(fence_fd);
+  android::base::unique_fd release_fence(fence_fd);
 
   // Post buffer to the read_queue.
-  TestMeta seq = 42U;
-  ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq));
-  ASSERT_EQ(0, ret);
-  dvrWriteBufferDestroy(wb);
+  meta1.timestamp = 42;
+  ret = dvrWriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
+  ASSERT_EQ(ret, 0);
+  ASSERT_FALSE(dvrWriteBufferIsValid(wb));
   wb = nullptr;
 
   // Acquire buffer for reading.
-  TestMeta acquired_seq = 0U;
-  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
-                                  &acquired_seq, sizeof(acquired_seq));
-  ASSERT_EQ(0, ret);
+  ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb, &meta2,
+                                        &fence_fd);
+  ASSERT_EQ(ret, 0);
+  ASSERT_NE(rb, nullptr);
+
+  // Dequeue is successfully, BufferAvailableCallback should be fired once.
+  ASSERT_EQ(buffer_available_count_, 1);
   ASSERT_TRUE(dvrReadBufferIsValid(rb));
-  ASSERT_EQ(seq, acquired_seq);
+
+  // Metadata should be passed along from producer to consumer properly.
+  ASSERT_EQ(meta1.timestamp, meta2.timestamp);
+
   ALOGD_IF(TRACE,
            "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
            fence_fd);
-  pdx::LocalHandle acquire_fence(fence_fd);
+  android::base::unique_fd acquire_fence(fence_fd);
 
   // Release buffer to the write_queue.
-  ret = dvrReadBufferRelease(rb, -1);
-  ASSERT_EQ(0, ret);
-  dvrReadBufferDestroy(rb);
+  ret = dvrReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
+                                        /*release_fence_fd=*/-1);
+  ASSERT_EQ(ret, 0);
+  ASSERT_FALSE(dvrReadBufferIsValid(rb));
   rb = nullptr;
 
   // TODO(b/34387835) Currently buffer allocation has to happen after all queues
@@ -186,32 +214,311 @@
   dvrReadBufferQueueDestroy(read_queue);
 }
 
-TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
+TEST_F(DvrBufferQueueTest, GetANativeWindow) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, write_queue_);
+
   ANativeWindow* window = nullptr;
-
-  // The |write_queue_| doesn't have proper metadata (must be
-  // DvrNativeBufferMetadata) configured during creation.
-  int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
-  ASSERT_EQ(-EINVAL, ret);
-  ASSERT_EQ(nullptr, window);
-
-  // A write queue with DvrNativeBufferMetadata should work fine.
-  std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
-      write_queue(
-          CreateDvrWriteBufferQueueFromProducerQueue(
-              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
-          dvrWriteBufferQueueDestroy);
-  ASSERT_NE(nullptr, write_queue.get());
-
-  ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
+  ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window);
   ASSERT_EQ(0, ret);
   ASSERT_NE(nullptr, window);
 
-  sp<Surface> surface = static_cast<Surface*>(window);
-  ASSERT_TRUE(Surface::isValid(surface));
+  uint32_t width = ANativeWindow_getWidth(window);
+  uint32_t height = ANativeWindow_getHeight(window);
+  uint32_t format = ANativeWindow_getFormat(window);
+  ASSERT_EQ(kBufferWidth, width);
+  ASSERT_EQ(kBufferHeight, height);
+  ASSERT_EQ(kBufferFormat, format);
+}
+
+// Create buffer queue of three buffers and dequeue three buffers out of it.
+// Before each dequeue operation, we resize the buffer queue and expect the
+// queue always return buffer with desired dimension.
+TEST_F(DvrBufferQueueTest, ResizeBuffer) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
+  int fence_fd = -1;
+
+  DvrNativeBufferMetadata meta;
+  DvrReadBufferQueue* read_queue = nullptr;
+  DvrWriteBuffer* wb1 = nullptr;
+  DvrWriteBuffer* wb2 = nullptr;
+  DvrWriteBuffer* wb3 = nullptr;
+  AHardwareBuffer* ahb1 = nullptr;
+  AHardwareBuffer* ahb2 = nullptr;
+  AHardwareBuffer* ahb3 = nullptr;
+  AHardwareBuffer_Desc buffer_desc;
+
+  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue);
+
+  dvrReadBufferQueueSetBufferRemovedCallback(read_queue, &BufferRemovedCallback,
+                                             this);
+
+  // Handle all pending events on the read queue.
+  ret = dvrReadBufferQueueHandleEvents(read_queue);
+  ASSERT_EQ(0, ret);
+
+  size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
+  ALOGD_IF(TRACE, "TestResizeBuffer, capacity=%zu", capacity);
+  ASSERT_EQ(kQueueCapacity, capacity);
+
+  // Resize before dequeuing.
+  constexpr uint32_t w1 = 10;
+  ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w1, kBufferHeight);
+  ASSERT_EQ(0, ret);
+
+  // Gain first buffer for writing. All buffers will be resized.
+  ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1, &meta,
+                                      &fence_fd);
+  ASSERT_EQ(0, ret);
+  ASSERT_TRUE(dvrWriteBufferIsValid(wb1));
+  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1);
+  android::base::unique_fd release_fence1(fence_fd);
+
+  // Check the buffer dimension.
+  ret = dvrWriteBufferGetAHardwareBuffer(wb1, &ahb1);
+  ASSERT_EQ(0, ret);
+  AHardwareBuffer_describe(ahb1, &buffer_desc);
+  ASSERT_EQ(w1, buffer_desc.width);
+  ASSERT_EQ(kBufferHeight, buffer_desc.height);
+  AHardwareBuffer_release(ahb1);
+
+  // For the first resize, all buffers are reallocated.
+  int expected_buffer_removed_count = kQueueCapacity;
+  ret = dvrReadBufferQueueHandleEvents(read_queue);
+  ASSERT_EQ(0, ret);
+  ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
+
+  // Resize the queue. We are testing with blob format, keep height to be 1.
+  constexpr uint32_t w2 = 20;
+  ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w2, kBufferHeight);
+  ASSERT_EQ(0, ret);
+
+  // The next buffer we dequeued should have new width.
+  ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2, &meta,
+                                      &fence_fd);
+  ASSERT_EQ(0, ret);
+  ASSERT_TRUE(dvrWriteBufferIsValid(wb2));
+  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2,
+           fence_fd);
+  android::base::unique_fd release_fence2(fence_fd);
+
+  // Check the buffer dimension, should be new width
+  ret = dvrWriteBufferGetAHardwareBuffer(wb2, &ahb2);
+  ASSERT_EQ(0, ret);
+  AHardwareBuffer_describe(ahb2, &buffer_desc);
+  ASSERT_EQ(w2, buffer_desc.width);
+  AHardwareBuffer_release(ahb2);
+
+  // For the second resize, all but one buffers are reallocated.
+  expected_buffer_removed_count += (kQueueCapacity - 1);
+  ret = dvrReadBufferQueueHandleEvents(read_queue);
+  ASSERT_EQ(0, ret);
+  ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
+
+  // Resize the queue for the third time.
+  constexpr uint32_t w3 = 30;
+  ret = dvrWriteBufferQueueResizeBuffer(write_queue_, w3, kBufferHeight);
+  ASSERT_EQ(0, ret);
+
+  // The next buffer we dequeued should have new width.
+  ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3, &meta,
+                                      &fence_fd);
+  ASSERT_EQ(0, ret);
+  ASSERT_TRUE(dvrWriteBufferIsValid(wb3));
+  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3,
+           fence_fd);
+  android::base::unique_fd release_fence3(fence_fd);
+
+  // Check the buffer dimension, should be new width
+  ret = dvrWriteBufferGetAHardwareBuffer(wb3, &ahb3);
+  ASSERT_EQ(0, ret);
+  AHardwareBuffer_describe(ahb3, &buffer_desc);
+  ASSERT_EQ(w3, buffer_desc.width);
+  AHardwareBuffer_release(ahb3);
+
+  // For the third resize, all but two buffers are reallocated.
+  expected_buffer_removed_count += (kQueueCapacity - 2);
+  ret = dvrReadBufferQueueHandleEvents(read_queue);
+  ASSERT_EQ(0, ret);
+  ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_);
+
+  dvrReadBufferQueueDestroy(read_queue);
+}
+
+TEST_F(DvrBufferQueueTest, ReadQueueEventFd) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
+  DvrReadBufferQueue* read_queue = nullptr;
+  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, read_queue);
+
+  int event_fd = dvrReadBufferQueueGetEventFd(read_queue);
+  ASSERT_GT(event_fd, 0);
+}
+
+// Verifies a Dvr{Read,Write}BufferQueue contains the same set of
+// Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
+// the corresponding AHardwareBuffer handle stays the same.
+TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
+  int ret = dvrWriteBufferQueueCreate(
+      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
+      kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+  ASSERT_EQ(0, ret);
+
+  int fence_fd = -1;
+  DvrReadBufferQueue* read_queue = nullptr;
+  EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
+
+  // Read buffers.
+  std::array<DvrReadBuffer*, kQueueCapacity> rbs;
+  // Write buffers.
+  std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
+  // Buffer metadata.
+  std::array<DvrNativeBufferMetadata, kQueueCapacity> metas;
+  // Hardware buffers for Read buffers.
+  std::unordered_map<int, AHardwareBuffer*> rhbs;
+  // Hardware buffers for Write buffers.
+  std::unordered_map<int, AHardwareBuffer*> whbs;
+
+  constexpr int kNumTests = 100;
+
+  // This test runs the following operations many many times. Thus we prefer to
+  // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
+  std::function<void(size_t i)> Gain = [&](size_t i) {
+    int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/10,
+                                            &wbs[i], &metas[i], &fence_fd);
+    ASSERT_EQ(ret, 0);
+    ASSERT_LT(fence_fd, 0);  // expect invalid fence.
+    ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
+    int buffer_id = dvrWriteBufferGetId(wbs[i]);
+    ASSERT_GT(buffer_id, 0);
+
+    AHardwareBuffer* hb = nullptr;
+    ASSERT_EQ(0, dvrWriteBufferGetAHardwareBuffer(wbs[i], &hb));
+
+    auto whb_it = whbs.find(buffer_id);
+    if (whb_it == whbs.end()) {
+      // If this is a new buffer id, check that total number of unique
+      // hardware buffers won't exceed queue capacity.
+      ASSERT_LT(whbs.size(), kQueueCapacity);
+      whbs.emplace(buffer_id, hb);
+    } else {
+      // If this is a buffer id we have seen before, check that the
+      // buffer_id maps to the same AHardwareBuffer handle.
+      ASSERT_EQ(hb, whb_it->second);
+    }
+  };
+
+  std::function<void(size_t i)> Post = [&](size_t i) {
+    ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
+
+    metas[i].timestamp++;
+    int ret = dvrWriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i],
+                                            /*fence=*/-1);
+    ASSERT_EQ(ret, 0);
+  };
+
+  std::function<void(size_t i)> Acquire = [&](size_t i) {
+    int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10,
+                                              &rbs[i], &metas[i], &fence_fd);
+    ASSERT_EQ(ret, 0);
+    ASSERT_LT(fence_fd, 0);  // expect invalid fence.
+    ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
+
+    int buffer_id = dvrReadBufferGetId(rbs[i]);
+    ASSERT_GT(buffer_id, 0);
+
+    AHardwareBuffer* hb = nullptr;
+    ASSERT_EQ(0, dvrReadBufferGetAHardwareBuffer(rbs[i], &hb));
+
+    auto rhb_it = rhbs.find(buffer_id);
+    if (rhb_it == rhbs.end()) {
+      // If this is a new buffer id, check that total number of unique hardware
+      // buffers won't exceed queue capacity.
+      ASSERT_LT(rhbs.size(), kQueueCapacity);
+      rhbs.emplace(buffer_id, hb);
+    } else {
+      // If this is a buffer id we have seen before, check that the buffer_id
+      // maps to the same AHardwareBuffer handle.
+      ASSERT_EQ(hb, rhb_it->second);
+    }
+  };
+
+  std::function<void(size_t i)> Release = [&](size_t i) {
+    ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
+
+    int ret = dvrReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i],
+                                              /*release_fence_fd=*/-1);
+    ASSERT_EQ(ret, 0);
+  };
+
+  // Scenario one:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+    }
+    // Post all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Post(i));
+    }
+    // Acquire all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+    }
+    // Release all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Release(i));
+    }
+  }
+
+  // Scenario two:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain and post all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+      ASSERT_NO_FATAL_FAILURE(Post(i));
+    }
+    // Acquire and release all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+      ASSERT_NO_FATAL_FAILURE(Release(i));
+    }
+  }
+
+  // Scenario three:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain all write buffers then post them in reversed order.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+    }
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Post(kQueueCapacity - 1 - i));
+    }
+
+    // Acquire all write buffers then release them in reversed order.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+    }
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i));
+    }
+  }
 }
 
 }  // namespace
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
index a2414d6..f83b26e 100644
--- a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -1,14 +1,18 @@
+#include <android-base/properties.h>
 #include <base/logging.h>
 #include <gtest/gtest.h>
+#include <log/log.h>
 #include <poll.h>
 
 #include <android/hardware_buffer.h>
 
 #include <algorithm>
+#include <array>
 #include <set>
 #include <thread>
 #include <vector>
 
+#include <dvr/dvr_configuration_data.h>
 #include <dvr/dvr_deleter.h>
 #include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
@@ -23,7 +27,30 @@
 
 namespace {
 
-DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, bool value) {
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, nullptr_t) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, int32_t value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+  attribute.value.int32_value = value;
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, int64_t value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
+  attribute.value.int64_value = value;
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, bool value) {
   DvrSurfaceAttribute attribute;
   attribute.key = key;
   attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
@@ -31,11 +58,56 @@
   return attribute;
 }
 
-DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, int32_t value) {
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key, float value) {
   DvrSurfaceAttribute attribute;
   attribute.key = key;
-  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
-  attribute.value.bool_value = value;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
+  attribute.value.float_value = value;
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
+                                  const std::array<float, 2>& value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
+  std::copy(value.begin(), value.end(), attribute.value.float2_value);
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
+                                  const std::array<float, 3>& value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
+  std::copy(value.begin(), value.end(), attribute.value.float3_value);
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
+                                  const std::array<float, 4>& value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
+  std::copy(value.begin(), value.end(), attribute.value.float4_value);
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
+                                  const std::array<float, 8>& value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
+  std::copy(value.begin(), value.end(), attribute.value.float8_value);
+  return attribute;
+}
+
+DvrSurfaceAttribute MakeAttribute(DvrSurfaceAttributeKey key,
+                                  const std::array<float, 16>& value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
+  std::copy(value.begin(), value.end(), attribute.value.float16_value);
   return attribute;
 }
 
@@ -43,8 +115,8 @@
                                                   int32_t z_order = 0) {
   DvrSurface* surface = nullptr;
   DvrSurfaceAttribute attributes[] = {
-      GetAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
-      GetAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
+      MakeAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
+      MakeAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
 
   const int ret = dvrSurfaceCreate(
       attributes, std::extent<decltype(attributes)>::value, &surface);
@@ -56,11 +128,12 @@
 
 Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
     const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
-    uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity) {
+    uint32_t format, uint32_t layer_count, uint64_t usage, size_t capacity,
+    size_t metadata_size) {
   DvrWriteBufferQueue* queue;
-  const int ret =
-      dvrSurfaceCreateWriteBufferQueue(surface.get(), width, height, format,
-                                       layer_count, usage, capacity, &queue);
+  const int ret = dvrSurfaceCreateWriteBufferQueue(
+      surface.get(), width, height, format, layer_count, usage, capacity,
+      metadata_size, &queue);
   if (ret < 0)
     return ErrorStatus(-ret);
   else
@@ -98,13 +171,14 @@
       return {};
   }
 
-  Status<void> WaitForUpdate() {
+  enum : int { kTimeoutMs = 10000 };  // 10s
+
+  Status<void> WaitForUpdate(int timeout_ms = kTimeoutMs) {
     if (display_manager_event_fd_ < 0)
       return ErrorStatus(-display_manager_event_fd_);
 
-    const int kTimeoutMs = 10000;  // 10s
     pollfd pfd = {display_manager_event_fd_, POLLIN, 0};
-    const int count = poll(&pfd, 1, kTimeoutMs);
+    const int count = poll(&pfd, 1, timeout_ms);
     if (count < 0)
       return ErrorStatus(errno);
     else if (count == 0)
@@ -200,6 +274,23 @@
     return {std::move(queue_ids)};
   }
 
+  Status<std::vector<uint8_t>> GetConfigData(int config_type) {
+    uint8_t* data = nullptr;
+    size_t data_size = 0;
+    int error = dvrConfigurationDataGet(config_type, &data, &data_size);
+    if (error < 0) {
+      return ErrorStatus(-error);
+    }
+
+    if (!data || data_size == 0) {
+      return ErrorStatus(EINVAL);
+    }
+    std::vector<uint8_t> data_result(data, data + data_size);
+    dvrConfigurationDataDestroy(data);
+    std::string s(data, data + data_size);
+    return {std::move(data_result)};
+  }
+
  private:
   UniqueDvrDisplayManager display_manager_;
   UniqueDvrSurfaceState surface_state_;
@@ -451,20 +542,218 @@
   auto attributes = attribute_status.take();
   EXPECT_GE(attributes.size(), 2u);
 
-  const std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
-                                           DVR_SURFACE_ATTRIBUTE_VISIBLE};
+  std::set<int32_t> actual_keys;
+  std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+                                     DVR_SURFACE_ATTRIBUTE_VISIBLE};
 
   // Collect all the keys in attributes that match the expected keys.
-  std::set<int32_t> actual_keys;
-  std::for_each(attributes.begin(), attributes.end(),
-                [&expected_keys, &actual_keys](const auto& attribute) {
-                  if (expected_keys.find(attribute.key) != expected_keys.end())
-                    actual_keys.emplace(attribute.key);
-                });
+  auto compare_keys = [](const auto& attributes, const auto& expected_keys) {
+    std::set<int32_t> keys;
+    for (const auto& attribute : attributes) {
+      if (expected_keys.find(attribute.key) != expected_keys.end())
+        keys.emplace(attribute.key);
+    }
+    return keys;
+  };
 
   // If the sets match then attributes contained at least the expected keys,
   // even if other keys were also present.
+  actual_keys = compare_keys(attributes, expected_keys);
   EXPECT_EQ(expected_keys, actual_keys);
+
+  std::vector<DvrSurfaceAttribute> attributes_to_set = {
+      MakeAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, 0)};
+
+  // Test invalid args.
+  EXPECT_EQ(-EINVAL, dvrSurfaceSetAttributes(nullptr, attributes_to_set.data(),
+                                             attributes_to_set.size()));
+  EXPECT_EQ(-EINVAL, dvrSurfaceSetAttributes(surface.get(), nullptr,
+                                             attributes_to_set.size()));
+
+  // Test attribute change events.
+  ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
+                                       attributes_to_set.size()));
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+
+  // Verify the attributes changed flag is set.
+  auto check_flags = [](const auto& value) {
+    return value & DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED;
+  };
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+                   DVR_SURFACE_ATTRIBUTE_VISIBLE};
+
+  actual_keys.clear();
+  actual_keys = compare_keys(attributes, expected_keys);
+  EXPECT_EQ(expected_keys, actual_keys);
+
+  // Test setting and then deleting an attribute.
+  const DvrSurfaceAttributeKey kUserKey = 1;
+  attributes_to_set = {MakeAttribute(kUserKey, 1024)};
+
+  ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
+                                       attributes_to_set.size()));
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER, DVR_SURFACE_ATTRIBUTE_VISIBLE,
+                   kUserKey};
+
+  actual_keys.clear();
+  actual_keys = compare_keys(attributes, expected_keys);
+  EXPECT_EQ(expected_keys, actual_keys);
+
+  // Delete the attribute.
+  attributes_to_set = {MakeAttribute(kUserKey, nullptr)};
+
+  ASSERT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
+                                       attributes_to_set.size()));
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER, DVR_SURFACE_ATTRIBUTE_VISIBLE,
+                   kUserKey};
+
+  actual_keys.clear();
+  actual_keys = compare_keys(attributes, expected_keys);
+  EXPECT_NE(expected_keys, actual_keys);
+
+  // Test deleting a reserved attribute.
+  attributes_to_set = {MakeAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, nullptr)};
+
+  EXPECT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
+                                       attributes_to_set.size()));
+
+  // Failed attribute operations should not trigger update events.
+  const int kTimeoutMs = 100;  // 0.1s
+  EXPECT_STATUS_ERROR_VALUE(ETIMEDOUT, manager_->WaitForUpdate(kTimeoutMs));
+
+  attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+                   DVR_SURFACE_ATTRIBUTE_VISIBLE};
+
+  actual_keys.clear();
+  actual_keys = compare_keys(attributes, expected_keys);
+  EXPECT_EQ(expected_keys, actual_keys);
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceAttributeTypes) {
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  enum : std::int32_t {
+    kInt32Key = 1,
+    kInt64Key,
+    kBoolKey,
+    kFloatKey,
+    kFloat2Key,
+    kFloat3Key,
+    kFloat4Key,
+    kFloat8Key,
+    kFloat16Key,
+  };
+
+  const std::vector<DvrSurfaceAttribute> attributes_to_set = {
+      MakeAttribute(kInt32Key, int32_t{0}),
+      MakeAttribute(kInt64Key, int64_t{0}),
+      MakeAttribute(kBoolKey, false),
+      MakeAttribute(kFloatKey, 0.0f),
+      MakeAttribute(kFloat2Key, std::array<float, 2>{{1.0f, 2.0f}}),
+      MakeAttribute(kFloat3Key, std::array<float, 3>{{3.0f, 4.0f, 5.0f}}),
+      MakeAttribute(kFloat4Key, std::array<float, 4>{{6.0f, 7.0f, 8.0f, 9.0f}}),
+      MakeAttribute(kFloat8Key,
+                    std::array<float, 8>{{10.0f, 11.0f, 12.0f, 13.0f, 14.0f,
+                                          15.0f, 16.0f, 17.0f}}),
+      MakeAttribute(kFloat16Key, std::array<float, 16>{
+                                     {18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f,
+                                      24.0f, 25.0f, 26.0f, 27.0f, 28.0f, 29.0f,
+                                      30.0f, 31.0f, 32.0f, 33.0f}})};
+
+  EXPECT_EQ(0, dvrSurfaceSetAttributes(surface.get(), attributes_to_set.data(),
+                                       attributes_to_set.size()));
+
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  auto attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  auto attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), attributes_to_set.size());
+
+  auto HasAttribute = [](const auto& attributes,
+                         DvrSurfaceAttributeKey key) -> bool {
+    for (const auto& attribute : attributes) {
+      if (attribute.key == key)
+        return true;
+    }
+    return false;
+  };
+  auto AttributeType =
+      [](const auto& attributes,
+         DvrSurfaceAttributeKey key) -> DvrSurfaceAttributeType {
+    for (const auto& attribute : attributes) {
+      if (attribute.key == key)
+        return attribute.value.type;
+    }
+    return DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
+  };
+
+  ASSERT_TRUE(HasAttribute(attributes, kInt32Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+            AttributeType(attributes, kInt32Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kInt64Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_INT64,
+            AttributeType(attributes, kInt64Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kBoolKey));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+            AttributeType(attributes, kBoolKey));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloatKey));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT,
+            AttributeType(attributes, kFloatKey));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloat2Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2,
+            AttributeType(attributes, kFloat2Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloat3Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3,
+            AttributeType(attributes, kFloat3Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloat4Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4,
+            AttributeType(attributes, kFloat4Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloat8Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8,
+            AttributeType(attributes, kFloat8Key));
+
+  ASSERT_TRUE(HasAttribute(attributes, kFloat16Key));
+  EXPECT_EQ(DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16,
+            AttributeType(attributes, kFloat16Key));
 }
 
 TEST_F(DvrDisplayManagerTest, SurfaceQueueEvent) {
@@ -480,13 +769,14 @@
   ASSERT_STATUS_OK(manager_->WaitForUpdate());
   ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
 
-  // Verify there are no queues for the surface recorded in the state snapshot.
+  // Verify there are no queues for the surface recorded in the state
+  // snapshot.
   EXPECT_STATUS_EQ(std::vector<int>{}, manager_->GetQueueIds(0));
 
   // Create a new queue in the surface.
   auto write_queue_status = CreateSurfaceQueue(
       surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 1,
-      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1, 0);
   ASSERT_STATUS_OK(write_queue_status);
   UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
   ASSERT_NE(nullptr, write_queue.get());
@@ -549,7 +839,7 @@
   const uint32_t kLayerCount = 3;
   auto write_queue_status = CreateSurfaceQueue(
       surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kLayerCount,
-      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1, 0);
   ASSERT_STATUS_OK(write_queue_status);
   UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
   ASSERT_NE(nullptr, write_queue.get());
@@ -573,6 +863,24 @@
   dvrWriteBufferDestroy(buffer);
 }
 
+TEST_F(DvrDisplayManagerTest, ConfigurationData) {
+  // TODO(hendrikw): Move this out of the display manager tests.
+  auto data1 = manager_->GetConfigData(-1);
+  ASSERT_STATUS_ERROR(data1);
+
+  const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+
+  // This should be run on devices with and without built in metrics.
+  bool has_metric = !base::GetProperty(kDvrLensMetricsProperty, "").empty();
+  auto data2 = manager_->GetConfigData(DVR_CONFIGURATION_DATA_LENS_METRICS);
+  if (has_metric) {
+    ASSERT_STATUS_OK(data2);
+    ASSERT_NE(0u, data2.get().size());
+  } else {
+    ASSERT_STATUS_ERROR(data2);
+  }
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index e65f6d5..c21deb0 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,6 +1,7 @@
 #include <android/hardware_buffer.h>
 #include <dvr/dvr_buffer.h>
-#include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_config.h>
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/dvr_surface.h>
 #include <system/graphics.h>
 
@@ -12,33 +13,15 @@
 
 namespace {
 
-class DvrNamedBufferTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    const int ret = dvrDisplayManagerCreate(&client_);
-    ASSERT_EQ(0, ret);
-    ASSERT_NE(nullptr, client_);
-  }
-
-  void TearDown() override {
-    dvrDisplayManagerDestroy(client_);
-    client_ = nullptr;
-  }
-
-  DvrDisplayManager* client_ = nullptr;
-};
-
-TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
-  const char* buffer_name = "same_name";
+TEST(DvrGlobalBufferTest, TestGlobalBuffersSameName) {
+  const DvrGlobalBufferKey buffer_key = 101;
   DvrBuffer* buffer1 = nullptr;
-  int ret1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+  int ret1 = dvrSetupGlobalBuffer(buffer_key, 10, 0, &buffer1);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer1);
 
   DvrBuffer* buffer2 = nullptr;
-  int ret2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+  int ret2 = dvrSetupGlobalBuffer(buffer_key, 10, 0, &buffer2);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer2);
 
@@ -71,7 +54,7 @@
   dvrBufferDestroy(buffer2);
 
   DvrBuffer* buffer3 = nullptr;
-  int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+  int e3 = dvrGetGlobalBuffer(buffer_key, &buffer3);
   ASSERT_NE(nullptr, buffer3);
   ASSERT_EQ(0, e3);
 
@@ -95,38 +78,36 @@
   AHardwareBuffer_release(hardware_buffer3);
 }
 
-TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
-  const char* buffer_name1 = "test1";
-  const char* buffer_name2 = "test2";
+TEST(DvrGlobalBufferTest, TestMultipleGlobalBuffers) {
+  const DvrGlobalBufferKey buffer_key1 = 102;
+  const DvrGlobalBufferKey buffer_key2 = 103;
   DvrBuffer* setup_buffer1 = nullptr;
-  int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
-                                               &setup_buffer1);
+  int ret1 = dvrSetupGlobalBuffer(buffer_key1, 10, 0, &setup_buffer1);
   ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, setup_buffer1);
   dvrBufferDestroy(setup_buffer1);
 
   DvrBuffer* setup_buffer2 = nullptr;
-  int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
-                                               &setup_buffer2);
+  int ret2 = dvrSetupGlobalBuffer(buffer_key2, 10, 0, &setup_buffer2);
   ASSERT_EQ(0, ret2);
   ASSERT_NE(nullptr, setup_buffer2);
   dvrBufferDestroy(setup_buffer2);
 
   DvrBuffer* buffer1 = nullptr;
-  int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+  int e1 = dvrGetGlobalBuffer(buffer_key1, &buffer1);
   ASSERT_NE(nullptr, buffer1);
   ASSERT_EQ(0, e1);
   dvrBufferDestroy(buffer1);
 
   DvrBuffer* buffer2 = nullptr;
-  int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+  int e2 = dvrGetGlobalBuffer(buffer_key2, &buffer2);
   ASSERT_NE(nullptr, buffer2);
   ASSERT_EQ(0, e2);
   dvrBufferDestroy(buffer2);
 }
 
-TEST_F(DvrNamedBufferTest, TestNamedBufferUsage) {
-  const char* buffer_name = "buffer_usage";
+TEST(DvrGlobalBufferTest, TestGlobalBufferUsage) {
+  const DvrGlobalBufferKey buffer_key = 100;
 
   // Set usage to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE. We use this because
   // internally AHARDWAREBUFFER_USAGE_VIDEO_ENCODE is converted to
@@ -136,8 +117,7 @@
   const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
 
   DvrBuffer* setup_buffer = nullptr;
-  int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
-                                             &setup_buffer);
+  int e1 = dvrSetupGlobalBuffer(buffer_key, 10, usage, &setup_buffer);
   ASSERT_NE(nullptr, setup_buffer);
   ASSERT_EQ(0, e1);
 
@@ -154,6 +134,151 @@
   AHardwareBuffer_release(hardware_buffer);
 }
 
+TEST(DvrGlobalBufferTest, TestGlobalBufferCarriesData) {
+  const DvrGlobalBufferKey buffer_name = 110;
+
+  uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                   AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+  constexpr size_t size = 1024 * sizeof(uint64_t);
+  constexpr uint64_t value = 0x123456787654321;
+
+  {
+    // Allocate some data and set it to something.
+    DvrBuffer* setup_buffer = nullptr;
+    int e1 = dvrSetupGlobalBuffer(buffer_name, size, usage, &setup_buffer);
+    ASSERT_NE(nullptr, setup_buffer);
+    ASSERT_EQ(0, e1);
+
+    AHardwareBuffer* hardware_buffer = nullptr;
+    int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+    ASSERT_EQ(0, e2);
+    ASSERT_NE(nullptr, hardware_buffer);
+
+    void* buffer;
+    int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+    ASSERT_EQ(0, e3);
+    ASSERT_NE(nullptr, buffer);
+    // Verify that the buffer pointer is at least 16 byte aligned.
+    ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+    uint64_t* data = static_cast<uint64_t*>(buffer);
+    constexpr size_t num_values = size / sizeof(uint64_t);
+    for (size_t i = 0; i < num_values; ++i) {
+      data[i] = value;
+    }
+
+    int32_t fence = -1;
+    int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+    ASSERT_EQ(0, e4);
+
+    dvrBufferDestroy(setup_buffer);
+    AHardwareBuffer_release(hardware_buffer);
+  }
+
+  {
+    // Get the buffer and check that all the data is still present.
+    DvrBuffer* setup_buffer = nullptr;
+    int e1 = dvrGetGlobalBuffer(buffer_name, &setup_buffer);
+    ASSERT_NE(nullptr, setup_buffer);
+    ASSERT_EQ(0, e1);
+
+    AHardwareBuffer* hardware_buffer = nullptr;
+    int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+    ASSERT_EQ(0, e2);
+    ASSERT_NE(nullptr, hardware_buffer);
+
+    void* buffer;
+    int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+    ASSERT_EQ(0, e3);
+    ASSERT_NE(nullptr, buffer);
+    // Verify that the buffer pointer is at least 16 byte aligned.
+    ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+    uint64_t* data = static_cast<uint64_t*>(buffer);
+    constexpr size_t num_values = size / sizeof(uint64_t);
+    bool is_equal = true;
+    for (size_t i = 0; i < num_values; ++i) {
+      is_equal &= (data[i] == value);
+    }
+    ASSERT_TRUE(is_equal);
+
+    int32_t fence = -1;
+    int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+    ASSERT_EQ(0, e4);
+
+    dvrBufferDestroy(setup_buffer);
+    AHardwareBuffer_release(hardware_buffer);
+  }
+}
+
+TEST(DvrGlobalBufferTest, TestGlobalBufferZeroed) {
+  const DvrGlobalBufferKey buffer_name = 120;
+
+  // Allocate 1MB and check that it is all zeros.
+  uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                   AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+  constexpr size_t size = 1024 * 1024;
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrSetupGlobalBuffer(buffer_name, size, usage, &setup_buffer);
+  ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e1);
+
+  AHardwareBuffer* hardware_buffer = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer);
+
+  void* buffer;
+  int e3 = AHardwareBuffer_lock(hardware_buffer, usage, -1, nullptr, &buffer);
+  ASSERT_EQ(0, e3);
+  ASSERT_NE(nullptr, buffer);
+  // Verify that the buffer pointer is at least 16 byte aligned.
+  ASSERT_EQ(0, reinterpret_cast<uintptr_t>(buffer) & (16 - 1));
+
+  uint64_t* data = static_cast<uint64_t*>(buffer);
+  constexpr size_t num_values = size / sizeof(uint64_t);
+  uint64_t zero = 0;
+  for (size_t i = 0; i < num_values; ++i) {
+    zero |= data[i];
+  }
+  ASSERT_EQ(0, zero);
+
+  int32_t fence = -1;
+  int e4 = AHardwareBuffer_unlock(hardware_buffer, &fence);
+  ASSERT_EQ(0, e4);
+
+  dvrBufferDestroy(setup_buffer);
+  AHardwareBuffer_release(hardware_buffer);
+}
+
+TEST(DvrGlobalBufferTest, TestVrflingerConfigBuffer) {
+  const DvrGlobalBufferKey buffer_name =
+      DvrGlobalBuffers::kVrFlingerConfigBufferKey;
+
+  // First delete any existing buffer so we can test the failure case.
+  dvrDeleteGlobalBuffer(buffer_name);
+
+  const uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
+                         AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
+
+  size_t correct_size = DvrConfigRing::MemorySize();
+  size_t wrong_size = DvrConfigRing::MemorySize(0);
+
+  // Setup an invalid config buffer (too small) and assert that it fails.
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrSetupGlobalBuffer(buffer_name, wrong_size, usage, &setup_buffer);
+  ASSERT_EQ(nullptr, setup_buffer);
+  ASSERT_GT(0, e1);
+
+  // Setup a correct config buffer.
+  int e2 =
+      dvrSetupGlobalBuffer(buffer_name, correct_size, usage, &setup_buffer);
+  ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e2);
+
+  dvrBufferDestroy(setup_buffer);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index 527cdbd..62aeb79 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -28,7 +28,7 @@
     "libhardware",
 ]
 
-staticLibraries = ["libpdx_default_transport"]
+staticLibraries = ["libpdx_default_transport", "libbroadcastring"]
 
 headerLibraries = [
     "libeigen",
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index f55e994..10c0b31 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -5,12 +5,15 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-DLOG_TAG=\"libpdx\"",
+        "-DTRACE=0",
     ],
     export_include_dirs: ["private"],
     local_include_dirs: ["private"],
     srcs: [
         "client.cpp",
         "service.cpp",
+        "service_dispatcher.cpp",
         "status.cpp",
     ],
 }
@@ -33,6 +36,7 @@
         "variant_tests.cpp",
     ],
     static_libs: [
+        "libcutils",
         "libgmock",
         "libpdx",
         "liblog",
diff --git a/libs/vr/libpdx/client.cpp b/libs/vr/libpdx/client.cpp
index bfa2d87..a01c4d6 100644
--- a/libs/vr/libpdx/client.cpp
+++ b/libs/vr/libpdx/client.cpp
@@ -1,6 +1,5 @@
 #include "pdx/client.h"
 
-#define LOG_TAG "ServiceFramework"
 #include <log/log.h>
 
 #include <pdx/trace.h>
diff --git a/libs/vr/libpdx/mock_tests.cpp b/libs/vr/libpdx/mock_tests.cpp
index 76fd154..4143837 100644
--- a/libs/vr/libpdx/mock_tests.cpp
+++ b/libs/vr/libpdx/mock_tests.cpp
@@ -3,7 +3,6 @@
 #include <pdx/mock_client_channel_factory.h>
 #include <pdx/mock_message_reader.h>
 #include <pdx/mock_message_writer.h>
-#include <pdx/mock_service_dispatcher.h>
 #include <pdx/mock_service_endpoint.h>
 
 TEST(MockTypes, Instantiation) {
@@ -15,6 +14,5 @@
   android::pdx::MockMessageReader message_reader;
   android::pdx::MockOutputResourceMapper output_resource_mapper;
   android::pdx::MockMessageWriter message_writer;
-  android::pdx::MockServiceDispatcher service_dispatcher;
   android::pdx::MockEndpoint endpoint;
 }
diff --git a/libs/vr/libpdx/private/pdx/client_channel.h b/libs/vr/libpdx/private/pdx/client_channel.h
index dbfd626..10a49bb 100644
--- a/libs/vr/libpdx/private/pdx/client_channel.h
+++ b/libs/vr/libpdx/private/pdx/client_channel.h
@@ -1,6 +1,8 @@
 #ifndef ANDROID_PDX_CLIENT_CHANNEL_H_
 #define ANDROID_PDX_CLIENT_CHANNEL_H_
 
+#include <vector>
+
 #include <pdx/channel_handle.h>
 #include <pdx/file_handle.h>
 #include <pdx/status.h>
@@ -20,6 +22,15 @@
   virtual int event_fd() const = 0;
   virtual Status<int> GetEventMask(int events) = 0;
 
+  struct EventSource {
+    int event_fd;
+    int event_mask;
+  };
+
+  // Returns a set of event-generating fds with and event mask for each. These
+  // fds are owned by the ClientChannel and must never be closed by the caller.
+  virtual std::vector<EventSource> GetEventSources() const = 0;
+
   virtual LocalChannelHandle& GetChannelHandle() = 0;
   virtual void* AllocateTransactionState() = 0;
   virtual void FreeTransactionState(void* state) = 0;
diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel.h b/libs/vr/libpdx/private/pdx/mock_client_channel.h
index 561c939..49e0682 100644
--- a/libs/vr/libpdx/private/pdx/mock_client_channel.h
+++ b/libs/vr/libpdx/private/pdx/mock_client_channel.h
@@ -11,6 +11,7 @@
  public:
   MOCK_CONST_METHOD0(GetIpcTag, uint32_t());
   MOCK_CONST_METHOD0(event_fd, int());
+  MOCK_CONST_METHOD0(GetEventSources, std::vector<EventSource>());
   MOCK_METHOD1(GetEventMask, Status<int>(int));
   MOCK_METHOD0(GetChannelHandle, LocalChannelHandle&());
   MOCK_METHOD0(AllocateTransactionState, void*());
diff --git a/libs/vr/libpdx/private/pdx/mock_service_dispatcher.h b/libs/vr/libpdx/private/pdx/mock_service_dispatcher.h
deleted file mode 100644
index 9b51d30..0000000
--- a/libs/vr/libpdx/private/pdx/mock_service_dispatcher.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef ANDROID_PDX_MOCK_SERVICE_DISPATCHER_H_
-#define ANDROID_PDX_MOCK_SERVICE_DISPATCHER_H_
-
-#include <gmock/gmock.h>
-#include <pdx/service_dispatcher.h>
-
-namespace android {
-namespace pdx {
-
-class MockServiceDispatcher : public ServiceDispatcher {
- public:
-  MOCK_METHOD1(AddService, int(const std::shared_ptr<Service>& service));
-  MOCK_METHOD1(RemoveService, int(const std::shared_ptr<Service>& service));
-  MOCK_METHOD0(ReceiveAndDispatch, int());
-  MOCK_METHOD1(ReceiveAndDispatch, int(int timeout));
-  MOCK_METHOD0(EnterDispatchLoop, int());
-  MOCK_METHOD1(SetCanceled, void(bool cancel));
-  MOCK_CONST_METHOD0(IsCanceled, bool());
-};
-
-}  // namespace pdx
-}  // namespace android
-
-#endif  // ANDROID_PDX_MOCK_SERVICE_DISPATCHER_H_
diff --git a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
index e741d4a..7f829e7 100644
--- a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
@@ -66,6 +66,7 @@
   MOCK_METHOD0(AllocateMessageState, void*());
   MOCK_METHOD1(FreeMessageState, void(void* state));
   MOCK_METHOD0(Cancel, Status<void>());
+  MOCK_CONST_METHOD0(epoll_fd, int());
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index cb44a51..80b1769 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -26,14 +26,35 @@
 template <std::size_t I, typename... Types>
 using TypeTagForIndex = TypeTag<TypeForIndex<I, Types...>>;
 
+// Similar to std::is_constructible except that it evaluates to false for bool
+// construction from pointer types: this helps prevent subtle to bugs caused by
+// assigning values that decay to pointers to Variants with bool elements.
+//
+// Here is an example of the problematic situation this trait avoids:
+//
+//  Variant<int, bool> v;
+//  const int array[3] = {1, 2, 3};
+//  v = array; // This is allowed by regular std::is_constructible.
+//
+template <typename...>
+struct IsConstructible;
+template <typename T, typename U>
+struct IsConstructible<T, U>
+    : std::integral_constant<bool,
+                             std::is_constructible<T, U>::value &&
+                                 !(std::is_same<std::decay_t<T>, bool>::value &&
+                                   std::is_pointer<std::decay_t<U>>::value)> {};
+template <typename T, typename... Args>
+struct IsConstructible<T, Args...> : std::is_constructible<T, Args...> {};
+
 // Enable if T(Args...) is well formed.
 template <typename R, typename T, typename... Args>
 using EnableIfConstructible =
-    typename std::enable_if<std::is_constructible<T, Args...>::value, R>::type;
+    typename std::enable_if<IsConstructible<T, Args...>::value, R>::type;
 // Enable if T(Args...) is not well formed.
 template <typename R, typename T, typename... Args>
 using EnableIfNotConstructible =
-    typename std::enable_if<!std::is_constructible<T, Args...>::value, R>::type;
+    typename std::enable_if<!IsConstructible<T, Args...>::value, R>::type;
 
 // Determines whether T is an element of Types...;
 template <typename... Types>
@@ -65,12 +86,11 @@
 struct ConstructibleCount;
 template <typename From, typename To>
 struct ConstructibleCount<From, To>
-    : std::integral_constant<std::size_t,
-                             std::is_constructible<To, From>::value> {};
+    : std::integral_constant<std::size_t, IsConstructible<To, From>::value> {};
 template <typename From, typename First, typename... Rest>
 struct ConstructibleCount<From, First, Rest...>
     : std::integral_constant<std::size_t,
-                             std::is_constructible<First, From>::value +
+                             IsConstructible<First, From>::value +
                                  ConstructibleCount<From, Rest...>::value> {};
 
 // Enable if T is an element of Types...
@@ -126,6 +146,18 @@
       : first_(std::forward<T>(value)) {
     *index_out = index;
   }
+  Union(const Union& other, std::int32_t index) {
+    if (index == 0)
+      new (&first_) Type(other.first_);
+  }
+  Union(Union&& other, std::int32_t index) {
+    if (index == 0)
+      new (&first_) Type(std::move(other.first_));
+  }
+  Union(const Union&) = delete;
+  Union(Union&&) = delete;
+  void operator=(const Union&) = delete;
+  void operator=(Union&&) = delete;
 
   Type& get(TypeTag<Type>) { return first_; }
   const Type& get(TypeTag<Type>) const { return first_; }
@@ -217,6 +249,22 @@
   template <typename T, typename U>
   Union(std::int32_t index, std::int32_t* index_out, TypeTag<T>, U&& value)
       : rest_(index + 1, index_out, TypeTag<T>{}, std::forward<U>(value)) {}
+  Union(const Union& other, std::int32_t index) {
+    if (index == 0)
+      new (&first_) First(other.first_);
+    else
+      new (&rest_) Union<Rest...>(other.rest_, index - 1);
+  }
+  Union(Union&& other, std::int32_t index) {
+    if (index == 0)
+      new (&first_) First(std::move(other.first_));
+    else
+      new (&rest_) Union<Rest...>(std::move(other.rest_), index - 1);
+  }
+  Union(const Union&) = delete;
+  Union(Union&&) = delete;
+  void operator=(const Union&) = delete;
+  void operator=(Union&&) = delete;
 
   struct FirstType {};
   struct RestType {};
@@ -351,6 +399,10 @@
 
 }  // namespace detail
 
+// Variant is a type safe union that can store values of any of its element
+// types. A Variant is different than std::tuple in that it only stores one type
+// at a time or a special empty type. Variants are always default constructible
+// to empty, even when none of the element types are default constructible.
 template <typename... Types>
 class Variant {
  private:
@@ -393,6 +445,11 @@
   explicit Variant(EmptyVariant) {}
   ~Variant() { Destruct(); }
 
+  Variant(const Variant& other)
+      : index_{other.index_}, value_{other.value_, other.index_} {}
+  Variant(Variant&& other)
+      : index_{other.index_}, value_{std::move(other.value_), other.index_} {}
+
   // Copy and move construction from Variant types. Each element of OtherTypes
   // must be convertible to an element of Types.
   template <typename... OtherTypes>
@@ -404,6 +461,15 @@
     other.Visit([this](auto&& value) { Construct(std::move(value)); });
   }
 
+  Variant& operator=(const Variant& other) {
+    other.Visit([this](const auto& value) { *this = value; });
+    return *this;
+  }
+  Variant& operator=(Variant&& other) {
+    other.Visit([this](auto&& value) { *this = std::move(value); });
+    return *this;
+  }
+
   // Construction from non-Variant types.
   template <typename T, typename = EnableIfAssignable<void, T>>
   explicit Variant(T&& value)
@@ -429,7 +495,7 @@
   // Handles assignment from the empty type. This overload supports assignment
   // in visitors using generic lambdas.
   Variant& operator=(EmptyVariant) {
-    Assign(EmptyVariant{});
+    Destruct();
     return *this;
   }
 
@@ -541,7 +607,10 @@
   void Construct(EmptyVariant) {}
 
   // Destroys the active element of the Variant.
-  void Destruct() { value_.Destruct(index_); }
+  void Destruct() {
+    value_.Destruct(index_);
+    index_ = kEmptyIndex;
+  }
 
   // Assigns the Variant when non-empty and the current type matches the target
   // type, otherwise destroys the current value and constructs a element of the
@@ -562,8 +631,6 @@
       Construct(std::forward<T>(value));
     }
   }
-  // Handles assignment from an empty Variant.
-  void Assign(EmptyVariant) { Destruct(); }
 };
 
 // Utility type to extract/convert values from a variant. This class simplifies
diff --git a/libs/vr/libpdx/private/pdx/service_dispatcher.h b/libs/vr/libpdx/private/pdx/service_dispatcher.h
index c5e342a..bd27000 100644
--- a/libs/vr/libpdx/private/pdx/service_dispatcher.h
+++ b/libs/vr/libpdx/private/pdx/service_dispatcher.h
@@ -2,6 +2,11 @@
 #define ANDROID_PDX_SERVICE_DISPATCHER_H_
 
 #include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <pdx/file_handle.h>
 
 namespace android {
 namespace pdx {
@@ -15,7 +20,10 @@
  */
 class ServiceDispatcher {
  public:
-  virtual ~ServiceDispatcher() = default;
+  // Get a new instance of ServiceDispatcher, or return nullptr if init failed.
+  static std::unique_ptr<ServiceDispatcher> Create();
+
+  ~ServiceDispatcher();
 
   /*
    * Adds a service to the list of services handled by this dispatcher. This
@@ -24,7 +32,7 @@
    *
    * Returns 0 on success; -EEXIST if the service was already added.
    */
-  virtual int AddService(const std::shared_ptr<Service>& service) = 0;
+  int AddService(const std::shared_ptr<Service>& service);
 
   /*
    * Removes a service from this dispatcher. This will fail if any threads are
@@ -33,7 +41,7 @@
    * Returns 0 on success; -ENOENT if the service was not previously added;
    * -EBUSY if there are threads in the dispatcher.
    */
-  virtual int RemoveService(const std::shared_ptr<Service>& service) = 0;
+  int RemoveService(const std::shared_ptr<Service>& service);
 
   /*
    * Receive and dispatch one set of messages. Multiple threads may enter this
@@ -42,14 +50,14 @@
    * cycle, requiring an external loop. This is useful when other work needs
    * to be done in the service dispatch loop.
    */
-  virtual int ReceiveAndDispatch() = 0;
+  int ReceiveAndDispatch();
 
   /*
    * Same as above with timeout in milliseconds. A negative value means
    * infinite timeout, while a value of 0 means return immediately if no
    * messages are available to receive.
    */
-  virtual int ReceiveAndDispatch(int timeout) = 0;
+  int ReceiveAndDispatch(int timeout);
 
   /*
    * Receive and dispatch messages until canceled. When more than one thread
@@ -58,19 +66,39 @@
    * hands Message instances (via move assignment) over to a queue of threads
    * (or perhaps one of several) to handle.
    */
-  virtual int EnterDispatchLoop() = 0;
+  int EnterDispatchLoop();
 
   /*
    * Sets the canceled state of the dispatcher. When canceled is true, any
    * threads blocked waiting for messages will return. This method waits until
    * all dispatch threads have exited the dispatcher.
    */
-  virtual void SetCanceled(bool cancel) = 0;
+  void SetCanceled(bool cancel);
 
   /*
    * Gets the canceled state of the dispatcher.
    */
-  virtual bool IsCanceled() const = 0;
+  bool IsCanceled() const;
+
+ private:
+  ServiceDispatcher();
+
+  // Internal thread accounting.
+  int ThreadEnter();
+  void ThreadExit();
+
+  std::mutex mutex_;
+  std::condition_variable condition_;
+  std::atomic<bool> canceled_{false};
+
+  std::vector<std::shared_ptr<Service>> services_;
+
+  int thread_count_ = 0;
+  LocalHandle event_fd_;
+  LocalHandle epoll_fd_;
+
+  ServiceDispatcher(const ServiceDispatcher&) = delete;
+  void operator=(const ServiceDispatcher&) = delete;
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/service_endpoint.h b/libs/vr/libpdx/private/pdx/service_endpoint.h
index 28bd6bc..d581894 100644
--- a/libs/vr/libpdx/private/pdx/service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/service_endpoint.h
@@ -136,6 +136,10 @@
   // Cancels the endpoint, unblocking any receiver threads waiting for a
   // message.
   virtual Status<void> Cancel() = 0;
+
+  // Returns an fd that can be used with epoll() to wait for incoming messages
+  // from this endpoint.
+  virtual int epoll_fd() const = 0;
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/trace.h b/libs/vr/libpdx/private/pdx/trace.h
index ebe8491..c687fd6 100644
--- a/libs/vr/libpdx/private/pdx/trace.h
+++ b/libs/vr/libpdx/private/pdx/trace.h
@@ -1,35 +1,82 @@
 #ifndef ANDROID_PDX_TRACE_H_
 #define ANDROID_PDX_TRACE_H_
 
-// Tracing utilities for libpdx. Tracing in the service framework is enabled
-// under these conditions:
-//    1. ATRACE_TAG is defined, AND
-//    2. ATRACE_TAG does not equal ATRACE_TAG_NEVER, AND
-//    3. PDX_TRACE_ENABLED is defined, AND
-//    4. PDX_TRACE_ENABLED is equal to logical true.
-//
-// If any of these conditions are not met tracing is completely removed from the
-// library and headers.
+#include <array>
 
-// If ATRACE_TAG is not defined, default to never.
-#ifndef ATRACE_TAG
-#define ATRACE_TAG ATRACE_TAG_NEVER
-#endif
-
-// Include tracing functions after the trace tag is defined.
 #include <utils/Trace.h>
 
-// If PDX_TRACE_ENABLED is not defined, default to off.
-#ifndef PDX_TRACE_ENABLED
-#define PDX_TRACE_ENABLED 0
+// Enables internal tracing in libpdx. This is disabled by default to avoid
+// spamming the trace buffers during normal trace activities. libpdx must be
+// built with this set to true to enable internal tracing.
+#ifndef PDX_LIB_TRACE_ENABLED
+#define PDX_LIB_TRACE_ENABLED false
 #endif
 
-#if (ATRACE_TAG) != (ATRACE_TAG_NEVER) && (PDX_TRACE_ENABLED)
-#define PDX_TRACE_NAME ATRACE_NAME
-#else
-#define PDX_TRACE_NAME(name) \
-  do {                       \
-  } while (0)
-#endif
+namespace android {
+namespace pdx {
+
+// Utility to generate scoped tracers with arguments.
+class ScopedTraceArgs {
+ public:
+  template <typename... Args>
+  ScopedTraceArgs(uint64_t tag, const char* format, Args&&... args)
+      : tag_{tag} {
+    if (atrace_is_tag_enabled(tag_)) {
+      std::array<char, 1024> buffer;
+      snprintf(buffer.data(), buffer.size(), format,
+               std::forward<Args>(args)...);
+      atrace_begin(tag_, buffer.data());
+    }
+  }
+
+  ~ScopedTraceArgs() { atrace_end(tag_); }
+
+ private:
+  uint64_t tag_;
+
+  ScopedTraceArgs(const ScopedTraceArgs&) = delete;
+  void operator=(const ScopedTraceArgs&) = delete;
+};
+
+// Utility to generate scoped tracers.
+class ScopedTrace {
+ public:
+  template <typename... Args>
+  ScopedTrace(uint64_t tag, bool enabled, const char* name)
+      : tag_{tag}, enabled_{enabled} {
+    if (enabled_)
+      atrace_begin(tag_, name);
+  }
+
+  ~ScopedTrace() {
+    if (enabled_)
+      atrace_end(tag_);
+  }
+
+ private:
+  uint64_t tag_;
+  bool enabled_;
+
+  ScopedTrace(const ScopedTrace&) = delete;
+  void operator=(const ScopedTrace&) = delete;
+};
+
+}  // namespace pdx
+}  // namespace android
+
+// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
+// defined in utils/Trace.h.
+#define PDX_TRACE_FORMAT(format, ...)                         \
+  ::android::pdx::ScopedTraceArgs PASTE(__tracer, __LINE__) { \
+    ATRACE_TAG, format, ##__VA_ARGS__                         \
+  }
+
+// TODO(eieio): Rename this to PDX_LIB_TRACE_NAME() for internal use by libpdx
+// and rename internal uses inside the library. This version is only enabled
+// when PDX_LIB_TRACE_ENABLED is true.
+#define PDX_TRACE_NAME(name)                              \
+  ::android::pdx::ScopedTrace PASTE(__tracer, __LINE__) { \
+    ATRACE_TAG, PDX_LIB_TRACE_ENABLED, name               \
+  }
 
 #endif  // ANDROID_PDX_TRACE_H_
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index 305c3b8..08fcaea 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -2,6 +2,7 @@
 #define ANDROID_PDX_UTILITY_H_
 
 #include <cstdint>
+#include <cstdlib>
 #include <iterator>
 
 #include <pdx/rpc/sequence.h>
@@ -23,6 +24,7 @@
     if (other.size())
       memcpy(data_, other.data(), other.size());
   }
+  ~ByteBuffer() { std::free(data_); }
 
   ByteBuffer& operator=(const ByteBuffer& other) {
     resize(other.size());
@@ -69,7 +71,7 @@
     size |= size >> 8;
     size |= size >> 16;
     size++;
-    void* new_data = data_ ? realloc(data_, size) : malloc(size);
+    void* new_data = data_ ? std::realloc(data_, size) : std::malloc(size);
     // TODO(avakulenko): Check for allocation failures.
     data_ = static_cast<uint8_t*>(new_data);
     capacity_ = size;
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index fab4770..1d3b62a 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -1,4 +1,3 @@
-#define LOG_TAG "ServiceFramework"
 #include "pdx/service.h"
 
 #include <fcntl.h>
@@ -10,8 +9,6 @@
 
 #include <pdx/trace.h>
 
-#define TRACE 0
-
 namespace android {
 namespace pdx {
 
diff --git a/libs/vr/libpdx_uds/service_dispatcher.cpp b/libs/vr/libpdx/service_dispatcher.cpp
similarity index 83%
rename from libs/vr/libpdx_uds/service_dispatcher.cpp
rename to libs/vr/libpdx/service_dispatcher.cpp
index 2c52578..b112fa3 100644
--- a/libs/vr/libpdx_uds/service_dispatcher.cpp
+++ b/libs/vr/libpdx/service_dispatcher.cpp
@@ -1,26 +1,25 @@
-#include "uds/service_dispatcher.h"
+#include <pdx/service_dispatcher.h>
 
 #include <errno.h>
 #include <log/log.h>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 
-#include "pdx/service.h"
-#include "uds/service_endpoint.h"
+#include <pdx/service.h>
+#include <pdx/service_endpoint.h>
 
 static const int kMaxEventsPerLoop = 128;
 
 namespace android {
 namespace pdx {
-namespace uds {
 
-std::unique_ptr<pdx::ServiceDispatcher> ServiceDispatcher::Create() {
+std::unique_ptr<ServiceDispatcher> ServiceDispatcher::Create() {
   std::unique_ptr<ServiceDispatcher> dispatcher{new ServiceDispatcher()};
   if (!dispatcher->epoll_fd_ || !dispatcher->event_fd_) {
     dispatcher.reset();
   }
 
-  return std::move(dispatcher);
+  return dispatcher;
 }
 
 ServiceDispatcher::ServiceDispatcher() {
@@ -70,18 +69,14 @@
 }
 
 int ServiceDispatcher::AddService(const std::shared_ptr<Service>& service) {
-  if (service->endpoint()->GetIpcTag() != Endpoint::kIpcTag)
-    return -EINVAL;
-
   std::lock_guard<std::mutex> autolock(mutex_);
 
-  auto* endpoint = static_cast<Endpoint*>(service->endpoint());
   epoll_event event;
   event.events = EPOLLIN;
   event.data.ptr = service.get();
 
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, endpoint->epoll_fd(), &event) <
-      0) {
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, service->endpoint()->epoll_fd(),
+                &event) < 0) {
     ALOGE("Failed to add service to dispatcher because: %s\n", strerror(errno));
     return -errno;
   }
@@ -91,9 +86,6 @@
 }
 
 int ServiceDispatcher::RemoveService(const std::shared_ptr<Service>& service) {
-  if (service->endpoint()->GetIpcTag() != Endpoint::kIpcTag)
-    return -EINVAL;
-
   std::lock_guard<std::mutex> autolock(mutex_);
 
   // It's dangerous to remove a service while other threads may be using it.
@@ -101,16 +93,15 @@
     return -EBUSY;
 
   epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
-
-  auto* endpoint = static_cast<Endpoint*>(service->endpoint());
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, endpoint->epoll_fd(), &dummy) <
-      0) {
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, service->endpoint()->epoll_fd(),
+                &dummy) < 0) {
     ALOGE("Failed to remove service from dispatcher because: %s\n",
           strerror(errno));
     return -errno;
   }
 
-  services_.remove(service);
+  services_.erase(std::remove(services_.begin(), services_.end(), service),
+                  services_.end());
   return 0;
 }
 
@@ -139,7 +130,7 @@
       Service* service = static_cast<Service*>(events[i].data.ptr);
 
       ALOGI_IF(TRACE, "Dispatching message: fd=%d\n",
-               static_cast<Endpoint*>(service->endpoint())->epoll_fd());
+               service->endpoint()->epoll_fd());
       service->ReceiveAndDispatch();
     }
   }
@@ -171,7 +162,7 @@
         Service* service = static_cast<Service*>(events[i].data.ptr);
 
         ALOGI_IF(TRACE, "Dispatching message: fd=%d\n",
-                 static_cast<Endpoint*>(service->endpoint())->epoll_fd());
+                 service->endpoint()->epoll_fd());
         service->ReceiveAndDispatch();
       }
     }
@@ -197,6 +188,5 @@
 
 bool ServiceDispatcher::IsCanceled() const { return canceled_; }
 
-}  // namespace uds
 }  // namespace pdx
 }  // namespace android
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index 325f33f..e3520f5 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -1,3 +1,4 @@
+#include <array>
 #include <cstdint>
 #include <functional>
 #include <memory>
@@ -584,6 +585,25 @@
     EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count());
     EXPECT_EQ(1u, InstrumentType<int>::copy_assignment_count());
   }
+
+  {
+    InstrumentType<int>::clear();
+
+    // Construct from temporary, temporary ctor/dtor.
+    Variant<int, InstrumentType<int>> v(InstrumentType<int>(25));
+
+    // Assign EmptyVariant.
+    v = EmptyVariant{};
+
+    EXPECT_EQ(2u, InstrumentType<int>::constructor_count());
+    EXPECT_EQ(2u, InstrumentType<int>::destructor_count());
+    EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count());
+    EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count());
+  }
+  EXPECT_EQ(2u, InstrumentType<int>::constructor_count());
+  EXPECT_EQ(2u, InstrumentType<int>::destructor_count());
+  EXPECT_EQ(0u, InstrumentType<int>::move_assignment_count());
+  EXPECT_EQ(0u, InstrumentType<int>::copy_assignment_count());
 }
 
 TEST(Variant, MoveConstructor) {
@@ -758,7 +778,7 @@
     Variant<std::string> b;
 
     std::swap(a, b);
-    EXPECT_TRUE(!a.empty());
+    EXPECT_TRUE(a.empty());
     EXPECT_TRUE(!b.empty());
     ASSERT_TRUE(b.is<std::string>());
     EXPECT_EQ("1", std::get<std::string>(b));
@@ -770,7 +790,7 @@
 
     std::swap(a, b);
     EXPECT_TRUE(!a.empty());
-    EXPECT_TRUE(!b.empty());
+    EXPECT_TRUE(b.empty());
     ASSERT_TRUE(a.is<std::string>());
     EXPECT_EQ("1", std::get<std::string>(a));
   }
@@ -1078,6 +1098,29 @@
   EXPECT_FALSE((detail::HasType<char&, int, float, bool>::value));
 }
 
+TEST(Variant, IsConstructible) {
+  using ArrayType = const float[3];
+  struct ImplicitBool {
+    operator bool() const { return true; }
+  };
+  struct ExplicitBool {
+    explicit operator bool() const { return true; }
+  };
+  struct NonBool {};
+  struct TwoArgs {
+    TwoArgs(int, bool) {}
+  };
+
+  EXPECT_FALSE((detail::IsConstructible<bool, ArrayType>::value));
+  EXPECT_TRUE((detail::IsConstructible<bool, int>::value));
+  EXPECT_TRUE((detail::IsConstructible<bool, ImplicitBool>::value));
+  EXPECT_TRUE((detail::IsConstructible<bool, ExplicitBool>::value));
+  EXPECT_FALSE((detail::IsConstructible<bool, NonBool>::value));
+  EXPECT_TRUE((detail::IsConstructible<TwoArgs, int, bool>::value));
+  EXPECT_FALSE((detail::IsConstructible<TwoArgs, int, std::string>::value));
+  EXPECT_FALSE((detail::IsConstructible<TwoArgs, int>::value));
+}
+
 TEST(Variant, Set) {
   EXPECT_TRUE((detail::Set<int, bool, float>::template IsSubset<int, bool,
                                                                 float>::value));
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 8cfa86f..f891c59 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -36,12 +36,13 @@
 }
 
 cc_binary {
-    name: "servicetool",
+    name: "pdx_tool",
     defaults: ["pdx_default_transport_compiler_defaults"],
     srcs: [
-        "servicetool.cpp",
+        "pdx_tool.cpp",
     ],
     shared_libs: [
+        "libcutils",
         "liblog",
     ],
     static_libs: [
diff --git a/libs/vr/libpdx_default_transport/servicetool.cpp b/libs/vr/libpdx_default_transport/pdx_tool.cpp
similarity index 100%
rename from libs/vr/libpdx_default_transport/servicetool.cpp
rename to libs/vr/libpdx_default_transport/pdx_tool.cpp
diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_dispatcher.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_dispatcher.h
deleted file mode 100644
index 158871c..0000000
--- a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/service_dispatcher.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_SERVICE_DISPATCHER_H_
-#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_SERVICE_DISPATCHER_H_
-
-#include <servicefs/service_dispatcher.h>
-
-namespace android {
-namespace pdx {
-namespace default_transport {
-
-using ServiceDispatcher = ::android::pdx::servicefs::ServiceDispatcher;
-
-}  // namespace default_transport
-}  // namespace pdx
-}  // namespace android
-
-
-#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_SERVICE_DISPATCHER_H_
diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_dispatcher.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_dispatcher.h
deleted file mode 100644
index 7cb7a80..0000000
--- a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/service_dispatcher.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_SERVICE_DISPATCHER_H_
-#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_SERVICE_DISPATCHER_H_
-
-#include <uds/service_dispatcher.h>
-
-namespace android {
-namespace pdx {
-namespace default_transport {
-
-using ServiceDispatcher = ::android::pdx::uds::ServiceDispatcher;
-
-}  // namespace default_transport
-}  // namespace pdx
-}  // namespace android
-
-
-#endif  // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_SERVICE_DISPATCHER_H_
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 82a5ea7..d0b7cab 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -16,7 +16,6 @@
         "client_channel_factory.cpp",
         "client_channel.cpp",
         "ipc_helper.cpp",
-        "service_dispatcher.cpp",
         "service_endpoint.cpp",
     ],
     static_libs: [
diff --git a/libs/vr/libpdx_uds/channel_event_set.cpp b/libs/vr/libpdx_uds/channel_event_set.cpp
index ac4dea9..c68968e 100644
--- a/libs/vr/libpdx_uds/channel_event_set.cpp
+++ b/libs/vr/libpdx_uds/channel_event_set.cpp
@@ -1,6 +1,10 @@
 #include "private/uds/channel_event_set.h"
 
+#include <errno.h>
 #include <log/log.h>
+#include <poll.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
 
 #include <uds/ipc_helper.h>
 
@@ -8,41 +12,34 @@
 namespace pdx {
 namespace uds {
 
-ChannelEventSet::ChannelEventSet() {
-  const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
-  LocalHandle epoll_fd, event_fd;
+namespace {
 
-  if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll") ||
-      !SetupHandle(eventfd(0, flags), &event_fd, "event")) {
-    return;
-  }
-
-  epoll_event event;
-  event.events = 0;
-  event.data.u32 = 0;
-  if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, event_fd.Get(), &event) < 0) {
-    const int error = errno;
-    ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
-          strerror(error));
-    return;
-  }
-
-  epoll_fd_ = std::move(epoll_fd);
-  event_fd_ = std::move(event_fd);
-}
-
-Status<void> ChannelEventSet::AddDataFd(const LocalHandle& data_fd) {
-  epoll_event event;
-  event.events = EPOLLHUP | EPOLLRDHUP;
-  event.data.u32 = event.events;
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
-    const int error = errno;
-    ALOGE("ChannelEventSet::ChannelEventSet: Failed to add event_fd: %s",
+template <typename FileHandleType>
+Status<void> SetupHandle(int fd, FileHandleType* handle,
+                         const char* error_name) {
+  const int error = errno;
+  handle->Reset(fd);
+  if (!*handle) {
+    ALOGE("SetupHandle: Failed to setup %s handle: %s", error_name,
           strerror(error));
     return ErrorStatus{error};
-  } else {
-    return {};
   }
+  return {};
+}
+
+}  // anonymous namespace
+
+ChannelEventSet::ChannelEventSet() {
+  const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
+  LocalHandle pollin_event_fd, pollhup_event_fd;
+
+  if (!SetupHandle(eventfd(0, flags), &pollin_event_fd, "pollin_event") ||
+      !SetupHandle(eventfd(0, flags), &pollhup_event_fd, "pollhup_event")) {
+    return;
+  }
+
+  pollin_event_fd_ = std::move(pollin_event_fd);
+  pollhup_event_fd_ = std::move(pollhup_event_fd);
 }
 
 int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
@@ -51,63 +48,101 @@
   const int old_bits = event_bits_;
   const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
   event_bits_ = new_bits;
+  eventfd_t value;
 
-  // If anything changed clear the event and update the event mask.
-  if (old_bits != new_bits) {
-    eventfd_t value;
-    eventfd_read(event_fd_.Get(), &value);
+  // Calculate which bits changed and how. Bits that haven't changed since last
+  // modification will not change the state of an eventfd.
+  const int set_bits = new_bits & ~old_bits;
+  const int clear_bits = ~new_bits & old_bits;
 
-    epoll_event event;
-    event.events = POLLIN;
-    event.data.u32 = event_bits_;
-    if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, event_fd_.Get(), &event) <
-        0) {
-      const int error = errno;
-      ALOGE("ChannelEventSet::AddEventHandle: Failed to update event: %s",
-            strerror(error));
-      return -error;
-    }
-  }
+  if (set_bits & EPOLLIN)
+    eventfd_write(pollin_event_fd_.Get(), 1);
+  else if (clear_bits & EPOLLIN)
+    eventfd_read(pollin_event_fd_.Get(), &value);
 
-  // If there are any bits set, re-trigger the eventfd.
-  if (new_bits)
-    eventfd_write(event_fd_.Get(), 1);
+  if (set_bits & EPOLLHUP)
+    eventfd_write(pollhup_event_fd_.Get(), 1);
+  else if (clear_bits & EPOLLHUP)
+    eventfd_read(pollhup_event_fd_.Get(), &value);
 
   return 0;
 }
 
-Status<void> ChannelEventSet::SetupHandle(int fd, LocalHandle* handle,
-                                          const char* error_name) {
-  const int error = errno;
-  handle->Reset(fd);
-  if (!*handle) {
-    ALOGE("ChannelEventSet::SetupHandle: Failed to setup %s handle: %s",
-          error_name, strerror(error));
+ChannelEventReceiver::ChannelEventReceiver(LocalHandle data_fd,
+                                           LocalHandle pollin_event_fd,
+                                           LocalHandle pollhup_event_fd) {
+  LocalHandle epoll_fd;
+  if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll")) {
+    return;
+  }
+
+  epoll_event event;
+  event.events = EPOLLHUP | EPOLLRDHUP;
+  event.data.u32 = 0;
+  if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
+    const int error = errno;
+    ALOGE("ChannelEventSet::ChannelEventSet: Failed to add data_fd: %s",
+          strerror(error));
+    return;
+  }
+
+  event.events = EPOLLIN;
+  event.data.u32 = 0;
+  if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollin_event_fd.Get(), &event) <
+      0) {
+    const int error = errno;
+    ALOGE("ChannelEventSet::ChannelEventSet: Failed to add pollin_event_fd: %s",
+          strerror(error));
+    return;
+  }
+
+  event.events = EPOLLIN;
+  event.data.u32 = 0;
+  if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollhup_event_fd.Get(), &event) <
+      0) {
+    const int error = errno;
+    ALOGE(
+        "ChannelEventSet::ChannelEventSet: Failed to add pollhup_event_fd: %s",
+        strerror(error));
+    return;
+  }
+
+  pollin_event_fd_ = std::move(pollin_event_fd);
+  pollhup_event_fd_ = std::move(pollhup_event_fd);
+  data_fd_ = std::move(data_fd);
+  epoll_fd_ = std::move(epoll_fd);
+}
+
+Status<int> ChannelEventReceiver::PollPendingEvents(int timeout_ms) const {
+  std::array<pollfd, 3> pfds = {{{pollin_event_fd_.Get(), POLLIN, 0},
+                                 {pollhup_event_fd_.Get(), POLLIN, 0},
+                                 {data_fd_.Get(), POLLHUP | POLLRDHUP, 0}}};
+  if (RETRY_EINTR(poll(pfds.data(), pfds.size(), timeout_ms)) < 0) {
+    const int error = errno;
+    ALOGE(
+        "ChannelEventReceiver::PollPendingEvents: Failed to poll for events: "
+        "%s",
+        strerror(error));
     return ErrorStatus{error};
   }
-  return {};
+
+  const int event_mask =
+      ((pfds[0].revents & POLLIN) ? EPOLLIN : 0) |
+      ((pfds[1].revents & POLLIN) ? EPOLLHUP : 0) |
+      ((pfds[2].revents & (POLLHUP | POLLRDHUP)) ? EPOLLHUP : 0);
+  return {event_mask};
 }
 
 Status<int> ChannelEventReceiver::GetPendingEvents() const {
   constexpr long kTimeoutMs = 0;
-  epoll_event event;
-  const int count =
-      RETRY_EINTR(epoll_wait(epoll_fd_.Get(), &event, 1, kTimeoutMs));
+  return PollPendingEvents(kTimeoutMs);
+}
 
-  Status<int> status;
-  if (count < 0) {
-    status.SetError(errno);
-    ALOGE("ChannelEventReceiver::GetPendingEvents: Failed to get events: %s",
-          status.GetErrorMessage().c_str());
-    return status;
-  }
-
-  const int mask_out = event.data.u32;
-  ALOGD_IF(TRACE, "ChannelEventReceiver::GetPendingEvents: mask_out=%x",
-           mask_out);
-
-  status.SetValue(mask_out);
-  return status;
+std::vector<ClientChannel::EventSource> ChannelEventReceiver::GetEventSources()
+    const {
+  return {{data_fd_.Get(), EPOLLHUP | EPOLLRDHUP},
+          {pollin_event_fd_.Get(), EPOLLIN},
+          {pollhup_event_fd_.Get(), POLLIN}};
 }
 
 }  // namespace uds
diff --git a/libs/vr/libpdx_uds/channel_manager.cpp b/libs/vr/libpdx_uds/channel_manager.cpp
index afc0a4f..43ebe05 100644
--- a/libs/vr/libpdx_uds/channel_manager.cpp
+++ b/libs/vr/libpdx_uds/channel_manager.cpp
@@ -22,18 +22,26 @@
 }
 
 LocalChannelHandle ChannelManager::CreateHandle(LocalHandle data_fd,
-                                                LocalHandle event_fd) {
-  if (data_fd && event_fd) {
+                                                LocalHandle pollin_event_fd,
+                                                LocalHandle pollhup_event_fd) {
+  if (data_fd && pollin_event_fd && pollhup_event_fd) {
     std::lock_guard<std::mutex> autolock(mutex_);
-    int32_t handle = data_fd.Get();
-    channels_.emplace(handle,
-                      ChannelData{std::move(data_fd), std::move(event_fd)});
+    const int32_t handle = data_fd.Get();
+    channels_.emplace(
+        handle,
+        ChannelEventReceiver{std::move(data_fd), std::move(pollin_event_fd),
+                             std::move(pollhup_event_fd)});
     return LocalChannelHandle(this, handle);
+  } else {
+    ALOGE(
+        "ChannelManager::CreateHandle: Invalid arguments: data_fd=%d "
+        "pollin_event_fd=%d pollhup_event_fd=%d",
+        data_fd.Get(), pollin_event_fd.Get(), pollhup_event_fd.Get());
+    return LocalChannelHandle(nullptr, -1);
   }
-  return LocalChannelHandle(nullptr, -1);
 }
 
-ChannelManager::ChannelData* ChannelManager::GetChannelData(int32_t handle) {
+ChannelEventReceiver* ChannelManager::GetChannelData(int32_t handle) {
   std::lock_guard<std::mutex> autolock(mutex_);
   auto channel = channels_.find(handle);
   return channel != channels_.end() ? &channel->second : nullptr;
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 9d91617..2e9c1de 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -33,7 +33,9 @@
     } else if (static_cast<size_t>(index) < response.channels.size()) {
       auto& channel_info = response.channels[index];
       *handle = ChannelManager::Get().CreateHandle(
-          std::move(channel_info.data_fd), std::move(channel_info.event_fd));
+          std::move(channel_info.data_fd),
+          std::move(channel_info.pollin_event_fd),
+          std::move(channel_info.pollhup_event_fd));
     } else {
       return false;
     }
@@ -53,9 +55,9 @@
 
     if (auto* channel_data =
             ChannelManager::Get().GetChannelData(handle.value())) {
-      ChannelInfo<BorrowedHandle> channel_info;
-      channel_info.data_fd.Reset(handle.value());
-      channel_info.event_fd = channel_data->event_receiver.event_fd();
+      ChannelInfo<BorrowedHandle> channel_info{
+          channel_data->data_fd(), channel_data->pollin_event_fd(),
+          channel_data->pollhup_event_fd()};
       request.channels.push_back(std::move(channel_info));
       return request.channels.size() - 1;
     } else {
@@ -90,10 +92,12 @@
   size_t send_len = CountVectorSize(send_vector, send_count);
   InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
               false);
-  auto status = SendData(socket_fd, transaction_state->request);
-  if (status && send_len > 0)
-    status = SendDataVector(socket_fd, send_vector, send_count);
-  return status;
+  if (send_len == 0) {
+    send_vector = nullptr;
+    send_count = 0;
+  }
+  return SendData(socket_fd, transaction_state->request, send_vector,
+                  send_count);
 }
 
 Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index 433f459..09dc7be 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -139,20 +139,33 @@
 
   RequestHeader<BorrowedHandle> request;
   InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
+
   status = SendData(socket_.Borrow(), request);
   if (!status)
     return status.error_status();
+
   ResponseHeader<LocalHandle> response;
   status = ReceiveData(socket_.Borrow(), &response);
   if (!status)
     return status.error_status();
-  int ref = response.ret_code;
-  if (ref < 0 || static_cast<size_t>(ref) > response.file_descriptors.size())
+  else if (response.ret_code < 0 || response.channels.size() != 1)
     return ErrorStatus(EIO);
 
-  LocalHandle event_fd = std::move(response.file_descriptors[ref]);
+  LocalHandle pollin_event_fd = std::move(response.channels[0].pollin_event_fd);
+  LocalHandle pollhup_event_fd =
+      std::move(response.channels[0].pollhup_event_fd);
+
+  if (!pollin_event_fd || !pollhup_event_fd) {
+    ALOGE(
+        "ClientChannelFactory::Connect: Required fd was not returned from the "
+        "service: pollin_event_fd=%d pollhup_event_fd=%d",
+        pollin_event_fd.Get(), pollhup_event_fd.Get());
+    return ErrorStatus(EIO);
+  }
+
   return ClientChannel::Create(ChannelManager::Get().CreateHandle(
-      std::move(socket_), std::move(event_fd)));
+      std::move(socket_), std::move(pollin_event_fd),
+      std::move(pollhup_event_fd)));
 }
 
 }  // namespace uds
diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp
index 7c3c68a..1560030 100644
--- a/libs/vr/libpdx_uds/client_channel_tests.cpp
+++ b/libs/vr/libpdx_uds/client_channel_tests.cpp
@@ -13,6 +13,7 @@
 #include <pdx/client.h>
 #include <pdx/rpc/remote_method.h>
 #include <pdx/service.h>
+#include <pdx/service_dispatcher.h>
 
 #include <uds/client_channel_factory.h>
 #include <uds/service_endpoint.h>
@@ -81,7 +82,7 @@
     auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{});
     endpoint->RegisterNewChannelForTests(std::move(channel_socket));
     service_ = TestService::Create(std::move(endpoint));
-    dispatcher_ = android::pdx::uds::ServiceDispatcher::Create();
+    dispatcher_ = ServiceDispatcher::Create();
     dispatcher_->AddService(service_);
     dispatch_thread_ = std::thread(
         std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get()));
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index d75ce86..f85b3bb 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -20,6 +20,9 @@
 
 namespace {
 
+constexpr size_t kMaxFdCount =
+    256;  // Total of 1KiB of data to transfer these FDs.
+
 // Default implementations of Send/Receive interfaces to use standard socket
 // send/sendmsg/recv/recvmsg functions.
 class SocketSender : public SendInterface {
@@ -175,20 +178,31 @@
 }
 
 Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
-                               const ucred* cred) {
+                               const ucred* cred, const iovec* data_vec,
+                               size_t vec_count) {
+  if (file_handles_.size() > kMaxFdCount) {
+    ALOGE(
+        "SendPayload::Send: Trying to send too many file descriptors (%zu), "
+        "max allowed = %zu",
+        file_handles_.size(), kMaxFdCount);
+    return ErrorStatus{EINVAL};
+  }
+
   SendInterface* sender = sender_ ? sender_ : &g_socket_sender;
   MessagePreamble preamble;
   preamble.magic = kMagicPreamble;
   preamble.data_size = buffer_.size();
   preamble.fd_count = file_handles_.size();
-  Status<void> ret = SendAll(sender, socket_fd, &preamble, sizeof(preamble));
-  if (!ret)
-    return ret;
 
   msghdr msg = {};
-  iovec recv_vect = {buffer_.data(), buffer_.size()};
-  msg.msg_iov = &recv_vect;
-  msg.msg_iovlen = 1;
+  msg.msg_iovlen = 2 + vec_count;
+  msg.msg_iov = static_cast<iovec*>(alloca(sizeof(iovec) * msg.msg_iovlen));
+  msg.msg_iov[0].iov_base = &preamble;
+  msg.msg_iov[0].iov_len = sizeof(preamble);
+  msg.msg_iov[1].iov_base = buffer_.data();
+  msg.msg_iov[1].iov_len = buffer_.size();
+  for (size_t i = 0; i < vec_count; i++)
+    msg.msg_iov[i + 2] = data_vec[i];
 
   if (cred || !file_handles_.empty()) {
     const size_t fd_bytes = file_handles_.size() * sizeof(int);
@@ -270,7 +284,15 @@
                                      ucred* cred) {
   RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver;
   MessagePreamble preamble;
-  Status<void> ret = RecvAll(receiver, socket_fd, &preamble, sizeof(preamble));
+  msghdr msg = {};
+  iovec recv_vect = {&preamble, sizeof(preamble)};
+  msg.msg_iov = &recv_vect;
+  msg.msg_iovlen = 1;
+  const size_t receive_fd_bytes = kMaxFdCount * sizeof(int);
+  msg.msg_controllen = CMSG_SPACE(sizeof(ucred)) + CMSG_SPACE(receive_fd_bytes);
+  msg.msg_control = alloca(msg.msg_controllen);
+
+  Status<void> ret = RecvMsgAll(receiver, socket_fd, &msg);
   if (!ret)
     return ret;
 
@@ -284,23 +306,6 @@
   file_handles_.clear();
   read_pos_ = 0;
 
-  msghdr msg = {};
-  iovec recv_vect = {buffer_.data(), buffer_.size()};
-  msg.msg_iov = &recv_vect;
-  msg.msg_iovlen = 1;
-
-  if (cred || preamble.fd_count) {
-    const size_t receive_fd_bytes = preamble.fd_count * sizeof(int);
-    msg.msg_controllen =
-        (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
-        (receive_fd_bytes == 0 ? 0 : CMSG_SPACE(receive_fd_bytes));
-    msg.msg_control = alloca(msg.msg_controllen);
-  }
-
-  ret = RecvMsgAll(receiver, socket_fd, &msg);
-  if (!ret)
-    return ret;
-
   bool cred_available = false;
   file_handles_.reserve(preamble.fd_count);
   cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -320,6 +325,10 @@
     cmsg = CMSG_NXTHDR(&msg, cmsg);
   }
 
+  ret = RecvAll(receiver, socket_fd, buffer_.data(), buffer_.size());
+  if (!ret)
+    return ret;
+
   if (cred && !cred_available) {
     ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
     ret.SetError(EIO);
diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
index 1f464d5..99e7502 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
@@ -1,11 +1,9 @@
 #ifndef ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_
 #define ANDROID_PDX_UDS_CHANNEL_EVENT_SET_H_
 
-#include <errno.h>
-#include <poll.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
+#include <vector>
 
+#include <pdx/client_channel.h>
 #include <pdx/file_handle.h>
 #include <pdx/status.h>
 
@@ -19,21 +17,20 @@
   ChannelEventSet(ChannelEventSet&&) = default;
   ChannelEventSet& operator=(ChannelEventSet&&) = default;
 
-  BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); }
+  BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); }
+  BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
 
-  explicit operator bool() const { return !!epoll_fd_ && !!event_fd_; }
+  explicit operator bool() const {
+    return !!pollin_event_fd_ && !!pollhup_event_fd_;
+  }
 
-  Status<void> AddDataFd(const LocalHandle& data_fd);
   int ModifyEvents(int clear_mask, int set_mask);
 
  private:
-  LocalHandle epoll_fd_;
-  LocalHandle event_fd_;
+  LocalHandle pollin_event_fd_;
+  LocalHandle pollhup_event_fd_;
   uint32_t event_bits_ = 0;
 
-  static Status<void> SetupHandle(int fd, LocalHandle* handle,
-                                  const char* error_name);
-
   ChannelEventSet(const ChannelEventSet&) = delete;
   void operator=(const ChannelEventSet&) = delete;
 };
@@ -41,14 +38,31 @@
 class ChannelEventReceiver {
  public:
   ChannelEventReceiver() = default;
-  ChannelEventReceiver(LocalHandle epoll_fd) : epoll_fd_{std::move(epoll_fd)} {}
+  ChannelEventReceiver(LocalHandle data_fd, LocalHandle pollin_event_fd,
+                       LocalHandle pollhup_event_fd);
   ChannelEventReceiver(ChannelEventReceiver&&) = default;
   ChannelEventReceiver& operator=(ChannelEventReceiver&&) = default;
 
+  explicit operator bool() const {
+    return !!pollin_event_fd_ && !!pollhup_event_fd_ && !!data_fd_ &&
+           !!epoll_fd_;
+  }
+
   BorrowedHandle event_fd() const { return epoll_fd_.Borrow(); }
+
+  BorrowedHandle pollin_event_fd() const { return pollin_event_fd_.Borrow(); }
+  BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
+  BorrowedHandle data_fd() const { return data_fd_.Borrow(); }
+
   Status<int> GetPendingEvents() const;
+  Status<int> PollPendingEvents(int timeout_ms) const;
+
+  std::vector<ClientChannel::EventSource> GetEventSources() const;
 
  private:
+  LocalHandle data_fd_;
+  LocalHandle pollin_event_fd_;
+  LocalHandle pollhup_event_fd_;
   LocalHandle epoll_fd_;
 
   ChannelEventReceiver(const ChannelEventReceiver&) = delete;
diff --git a/libs/vr/libpdx_uds/private/uds/channel_manager.h b/libs/vr/libpdx_uds/private/uds/channel_manager.h
index 2aca414..5f6a514 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_manager.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_manager.h
@@ -16,13 +16,11 @@
  public:
   static ChannelManager& Get();
 
-  LocalChannelHandle CreateHandle(LocalHandle data_fd, LocalHandle event_fd);
-  struct ChannelData {
-    LocalHandle data_fd;
-    ChannelEventReceiver event_receiver;
-  };
+  LocalChannelHandle CreateHandle(LocalHandle data_fd,
+                                  LocalHandle pollin_event_fd,
+                                  LocalHandle pollhup_event_fd);
 
-  ChannelData* GetChannelData(int32_t handle);
+  ChannelEventReceiver* GetChannelData(int32_t handle);
 
  private:
   ChannelManager() = default;
@@ -30,7 +28,7 @@
   void CloseHandle(int32_t handle) override;
 
   std::mutex mutex_;
-  std::unordered_map<int32_t, ChannelData> channels_;
+  std::unordered_map<int32_t, ChannelEventReceiver> channels_;
 };
 
 }  // namespace uds
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h
index 8f607f5..7a5ddf4 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel.h
@@ -23,11 +23,19 @@
   uint32_t GetIpcTag() const override { return Endpoint::kIpcTag; }
 
   int event_fd() const override {
-    return channel_data_ ? channel_data_->event_receiver.event_fd().Get() : -1;
+    return channel_data_ ? channel_data_->event_fd().Get() : -1;
   }
+
+  std::vector<EventSource> GetEventSources() const override {
+    if (channel_data_)
+      return channel_data_->GetEventSources();
+    else
+      return {};
+  }
+
   Status<int> GetEventMask(int /*events*/) override {
     if (channel_data_)
-      return channel_data_->event_receiver.GetPendingEvents();
+      return channel_data_->GetPendingEvents();
     else
       return ErrorStatus(EINVAL);
   }
@@ -74,7 +82,7 @@
                              const iovec* receive_vector, size_t receive_count);
 
   LocalChannelHandle channel_handle_;
-  ChannelManager::ChannelData* channel_data_;
+  ChannelEventReceiver* channel_data_;
   std::mutex socket_mutex_;
 };
 
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index bde16d3..63b5b10 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -59,7 +59,8 @@
  public:
   SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
   Status<void> Send(const BorrowedHandle& socket_fd);
-  Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
+  Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
+                    const iovec* data_vec = nullptr, size_t vec_count = 0);
 
   // MessageWriter
   void* GetNextWriteBufferSection(size_t size) override;
@@ -109,10 +110,12 @@
 class ChannelInfo {
  public:
   FileHandleType data_fd;
-  FileHandleType event_fd;
+  FileHandleType pollin_event_fd;
+  FileHandleType pollhup_event_fd;
 
  private:
-  PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, event_fd);
+  PDX_SERIALIZABLE_MEMBERS(ChannelInfo, data_fd, pollin_event_fd,
+                           pollhup_event_fd);
 };
 
 template <typename FileHandleType>
@@ -156,18 +159,22 @@
 };
 
 template <typename T>
-inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data,
+                             const iovec* data_vec = nullptr,
+                             size_t vec_count = 0) {
   SendPayload payload;
   rpc::Serialize(data, &payload);
-  return payload.Send(socket_fd);
+  return payload.Send(socket_fd, nullptr, data_vec, vec_count);
 }
 
 template <typename FileHandleType>
 inline Status<void> SendData(const BorrowedHandle& socket_fd,
-                             const RequestHeader<FileHandleType>& request) {
+                             const RequestHeader<FileHandleType>& request,
+                             const iovec* data_vec = nullptr,
+                             size_t vec_count = 0) {
   SendPayload payload;
   rpc::Serialize(request, &payload);
-  return payload.Send(socket_fd, &request.cred);
+  return payload.Send(socket_fd, &request.cred, data_vec, vec_count);
 }
 
 Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
diff --git a/libs/vr/libpdx_uds/private/uds/service_dispatcher.h b/libs/vr/libpdx_uds/private/uds/service_dispatcher.h
deleted file mode 100644
index 23af4f4..0000000
--- a/libs/vr/libpdx_uds/private/uds/service_dispatcher.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef ANDROID_PDX_UDS_SERVICE_DISPATCHER_H_
-#define ANDROID_PDX_UDS_SERVICE_DISPATCHER_H_
-
-#include <list>
-#include <memory>
-#include <mutex>
-#include <unordered_map>
-
-#include <pdx/file_handle.h>
-#include <pdx/service_dispatcher.h>
-
-namespace android {
-namespace pdx {
-namespace uds {
-
-class ServiceDispatcher : public pdx::ServiceDispatcher {
- public:
-  // Get a new instance of ServiceDispatcher, or return nullptr if init failed.
-  static std::unique_ptr<pdx::ServiceDispatcher> Create();
-
-  ~ServiceDispatcher() override;
-  int AddService(const std::shared_ptr<Service>& service) override;
-  int RemoveService(const std::shared_ptr<Service>& service) override;
-  int ReceiveAndDispatch() override;
-  int ReceiveAndDispatch(int timeout) override;
-  int EnterDispatchLoop() override;
-  void SetCanceled(bool cancel) override;
-  bool IsCanceled() const override;
-
- private:
-  ServiceDispatcher();
-
-  // Internal thread accounting.
-  int ThreadEnter();
-  void ThreadExit();
-
-  std::mutex mutex_;
-  std::condition_variable condition_;
-  std::atomic<bool> canceled_{false};
-
-  std::list<std::shared_ptr<Service>> services_;
-
-  int thread_count_ = 0;
-  LocalHandle event_fd_;
-  LocalHandle epoll_fd_;
-
-  ServiceDispatcher(const ServiceDispatcher&) = delete;
-  void operator=(const ServiceDispatcher&) = delete;
-};
-
-}  // namespace uds
-}  // namespace pdx
-}  // namespace android
-
-#endif  // ANDROID_PDX_UDS_SERVICE_DISPATCHER_H_
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 368891c..01ebf65 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -7,12 +7,12 @@
 #include <mutex>
 #include <string>
 #include <unordered_map>
+#include <utility>
 #include <vector>
 
 #include <pdx/service.h>
 #include <pdx/service_endpoint.h>
 #include <uds/channel_event_set.h>
-#include <uds/service_dispatcher.h>
 
 namespace android {
 namespace pdx {
@@ -105,7 +105,7 @@
   // socket file descriptor.
   Status<void> RegisterNewChannelForTests(LocalHandle channel_fd);
 
-  int epoll_fd() const { return epoll_fd_.Get(); }
+  int epoll_fd() const override { return epoll_fd_.Get(); }
 
  private:
   struct ChannelData {
@@ -140,7 +140,8 @@
   Status<void> ReenableEpollEvent(const BorrowedHandle& channel_fd);
   Channel* GetChannelState(int32_t channel_id);
   BorrowedHandle GetChannelSocketFd(int32_t channel_id);
-  BorrowedHandle GetChannelEventFd(int32_t channel_id);
+  Status<std::pair<BorrowedHandle, BorrowedHandle>> GetChannelEventFd(
+      int32_t channel_id);
   int32_t GetChannelId(const BorrowedHandle& channel_fd);
   Status<void> CreateChannelSocketPair(LocalHandle* local_socket,
                                        LocalHandle* remote_socket);
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 3109753..3f25776 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -15,9 +15,9 @@
 #include <pdx/rpc/remote_method.h>
 #include <pdx/rpc/serializable.h>
 #include <pdx/service.h>
+#include <pdx/service_dispatcher.h>
 #include <uds/client_channel.h>
 #include <uds/client_channel_factory.h>
-#include <uds/service_dispatcher.h>
 #include <uds/service_endpoint.h>
 
 using android::pdx::BorrowedHandle;
@@ -561,7 +561,7 @@
 
   void SetUp() override {
     // Create a dispatcher to handle messages to services.
-    dispatcher_ = android::pdx::uds::ServiceDispatcher::Create();
+    dispatcher_ = android::pdx::ServiceDispatcher::Create();
     ASSERT_NE(nullptr, dispatcher_);
 
     // Start the message dispatch loop in a separate thread.
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 27a56f9..0ee77f4 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -49,7 +49,9 @@
     } else if (static_cast<size_t>(index) < request.channels.size()) {
       auto& channel_info = request.channels[index];
       *handle = ChannelManager::Get().CreateHandle(
-          std::move(channel_info.data_fd), std::move(channel_info.event_fd));
+          std::move(channel_info.data_fd),
+          std::move(channel_info.pollin_event_fd),
+          std::move(channel_info.pollhup_event_fd));
     } else {
       return false;
     }
@@ -69,9 +71,9 @@
 
     if (auto* channel_data =
             ChannelManager::Get().GetChannelData(handle.value())) {
-      ChannelInfo<BorrowedHandle> channel_info;
-      channel_info.data_fd.Reset(handle.value());
-      channel_info.event_fd = channel_data->event_receiver.event_fd();
+      ChannelInfo<BorrowedHandle> channel_info{
+          channel_data->data_fd(), channel_data->pollin_event_fd(),
+          channel_data->pollhup_event_fd()};
       response.channels.push_back(std::move(channel_info));
       return response.channels.size() - 1;
     } else {
@@ -80,12 +82,13 @@
   }
 
   Status<ChannelReference> PushChannelHandle(BorrowedHandle data_fd,
-                                             BorrowedHandle event_fd) {
-    if (!data_fd || !event_fd)
+                                             BorrowedHandle pollin_event_fd,
+                                             BorrowedHandle pollhup_event_fd) {
+    if (!data_fd || !pollin_event_fd || !pollhup_event_fd)
       return ErrorStatus{EINVAL};
-    ChannelInfo<BorrowedHandle> channel_info;
-    channel_info.data_fd = std::move(data_fd);
-    channel_info.event_fd = std::move(event_fd);
+    ChannelInfo<BorrowedHandle> channel_info{std::move(data_fd),
+                                             std::move(pollin_event_fd),
+                                             std::move(pollhup_event_fd)};
     response.channels.push_back(std::move(channel_info));
     return response.channels.size() - 1;
   }
@@ -287,7 +290,6 @@
     return ErrorStatus(errno);
   }
   ChannelData channel_data;
-  channel_data.event_set.AddDataFd(channel_fd);
   channel_data.data_fd = std::move(channel_fd);
   channel_data.channel_state = channel_state;
   for (;;) {
@@ -431,18 +433,21 @@
     return status.error_status();
 
   std::lock_guard<std::mutex> autolock(channel_mutex_);
-  auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
-  if (!channel_data)
-    return channel_data.error_status();
-  *channel_id = channel_data.get().first;
+  auto channel_data_status =
+      OnNewChannelLocked(std::move(local_socket), channel);
+  if (!channel_data_status)
+    return channel_data_status.error_status();
+
+  ChannelData* channel_data;
+  std::tie(*channel_id, channel_data) = channel_data_status.take();
 
   // Flags are ignored for now.
   // TODO(xiaohuit): Implement those.
 
   auto* state = static_cast<MessageState*>(message->GetState());
   Status<ChannelReference> ref = state->PushChannelHandle(
-      remote_socket.Borrow(),
-      channel_data.get().second->event_set.event_fd().Borrow());
+      remote_socket.Borrow(), channel_data->event_set.pollin_event_fd(),
+      channel_data->event_set.pollhup_event_fd());
   if (!ref)
     return ref.error_status();
   state->sockets_to_close.push_back(std::move(remote_socket));
@@ -472,13 +477,15 @@
   return handle;
 }
 
-BorrowedHandle Endpoint::GetChannelEventFd(int32_t channel_id) {
+Status<std::pair<BorrowedHandle, BorrowedHandle>> Endpoint::GetChannelEventFd(
+    int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
-  BorrowedHandle handle;
   auto channel_data = channels_.find(channel_id);
-  if (channel_data != channels_.end())
-    handle = channel_data->second.event_set.event_fd().Borrow();
-  return handle;
+  if (channel_data != channels_.end()) {
+    return {{channel_data->second.event_set.pollin_event_fd(),
+             channel_data->second.event_set.pollhup_event_fd()}};
+  }
+  return ErrorStatus(ENOENT);
 }
 
 int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) {
@@ -593,11 +600,6 @@
   }
 
   BorrowedHandle channel_fd{event.data.fd};
-  if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
-    BuildCloseMessage(GetChannelId(channel_fd), message);
-    return {};
-  }
-
   return ReceiveMessageForChannel(channel_fd, message);
 }
 
@@ -616,12 +618,23 @@
       if (return_code < 0) {
         return CloseChannel(channel_id);
       } else {
-        // Reply with the event fd.
-        auto push_status = state->PushFileHandle(GetChannelEventFd(channel_id));
-        state->response_data.clear();  // Just in case...
-        if (!push_status)
-          return push_status.error_status();
-        return_code = push_status.get();
+        // Open messages do not have a payload and may not transfer any channels
+        // or file descriptors on behalf of the service.
+        state->response_data.clear();
+        state->response.file_descriptors.clear();
+        state->response.channels.clear();
+
+        // Return the channel event-related fds in a single ChannelInfo entry
+        // with an empty data_fd member.
+        auto status = GetChannelEventFd(channel_id);
+        if (!status)
+          return status.error_status();
+
+        auto handles = status.take();
+        state->response.channels.push_back({BorrowedHandle(),
+                                            std::move(handles.first),
+                                            std::move(handles.second)});
+        return_code = 0;
       }
       break;
   }
diff --git a/libs/vr/libpdx_uds/service_framework_tests.cpp b/libs/vr/libpdx_uds/service_framework_tests.cpp
index 2943239..2742716 100644
--- a/libs/vr/libpdx_uds/service_framework_tests.cpp
+++ b/libs/vr/libpdx_uds/service_framework_tests.cpp
@@ -1,5 +1,6 @@
 #include <errno.h>
 #include <fcntl.h>
+#include <poll.h>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 #include <unistd.h>
@@ -16,10 +17,10 @@
 #include <pdx/client.h>
 #include <pdx/file_handle.h>
 #include <pdx/service.h>
+#include <pdx/service_dispatcher.h>
 #include <private/android_filesystem_config.h>
 #include <uds/client_channel.h>
 #include <uds/client_channel_factory.h>
-#include <uds/service_dispatcher.h>
 #include <uds/service_endpoint.h>
 
 using android::pdx::BorrowedChannelHandle;
@@ -425,7 +426,7 @@
 
   void SetUp() override {
     // Create a dispatcher to handle messages to services.
-    dispatcher_ = android::pdx::uds::ServiceDispatcher::Create();
+    dispatcher_ = android::pdx::ServiceDispatcher::Create();
     ASSERT_NE(nullptr, dispatcher_);
 
     // Start the message dispatch loop in a separate thread.
@@ -506,6 +507,37 @@
   EXPECT_EQ(-EINVAL, client->SendAsync(invalid_pointer, sizeof(int)));
 }
 
+// Test impulses.
+TEST_F(ServiceFrameworkTest, ImpulseHangup) {
+  // Create a test service and add it to the dispatcher.
+  auto service = TestService::Create(kTestService1);
+  ASSERT_NE(nullptr, service);
+  ASSERT_EQ(0, dispatcher_->AddService(service));
+
+  auto client = TestClient::Create(kTestService1);
+  ASSERT_NE(nullptr, client);
+
+  const int kMaxIterations = 1000;
+  for (int i = 0; i < kMaxIterations; i++) {
+    auto impulse_client = TestClient::Create(kTestService1);
+    ASSERT_NE(nullptr, impulse_client);
+
+    const uint8_t a = (i >> 0) & 0xff;
+    const uint8_t b = (i >> 8) & 0xff;
+    const uint8_t c = (i >> 16) & 0xff;
+    const uint8_t d = (i >> 24) & 0xff;
+    ImpulsePayload expected_payload = {{a, b, c, d}};
+    EXPECT_EQ(0, impulse_client->SendAsync(expected_payload.data(), 4));
+
+    // Hangup the impulse test client, then send a sync message over client to
+    // make sure the hangup message is handled before checking the impulse
+    // payload.
+    impulse_client = nullptr;
+    client->GetThisChannelId();
+    EXPECT_EQ(expected_payload, service->GetImpulsePayload());
+  }
+}
+
 // Test Message::PushChannel/Service::PushChannel API.
 TEST_F(ServiceFrameworkTest, PushChannel) {
   // Create a test service and add it to the dispatcher.
@@ -574,9 +606,7 @@
 
   pid_t process_id2;
 
-  std::thread thread([&]() {
-    process_id2 = client->GetThisProcessId();
-  });
+  std::thread thread([&]() { process_id2 = client->GetThisProcessId(); });
   thread.join();
 
   EXPECT_LT(2, process_id2);
@@ -614,15 +644,15 @@
   auto client = TestClient::Create(kTestService1);
   ASSERT_NE(nullptr, client);
 
-  epoll_event event;
-  int count = epoll_wait(client->event_fd(), &event, 1, 0);
+  pollfd pfd{client->event_fd(), POLLIN, 0};
+  int count = poll(&pfd, 1, 0);
   ASSERT_EQ(0, count);
 
   client->SendPollInEvent();
 
-  count = epoll_wait(client->event_fd(), &event, 1, -1);
+  count = poll(&pfd, 1, 10000 /*10s*/);
   ASSERT_EQ(1, count);
-  ASSERT_TRUE((EPOLLIN & event.events) != 0);
+  ASSERT_TRUE((POLLIN & pfd.revents) != 0);
 }
 
 TEST_F(ServiceFrameworkTest, PollHup) {
@@ -635,15 +665,15 @@
   auto client = TestClient::Create(kTestService1);
   ASSERT_NE(nullptr, client);
 
-  epoll_event event;
-  int count = epoll_wait(client->event_fd(), &event, 1, 0);
+  pollfd pfd{client->event_fd(), POLLIN, 0};
+  int count = poll(&pfd, 1, 0);
   ASSERT_EQ(0, count);
 
   client->SendPollHupEvent();
 
-  count = epoll_wait(client->event_fd(), &event, 1, -1);
+  count = poll(&pfd, 1, 10000 /*10s*/);
   ASSERT_EQ(1, count);
-  auto event_status = client->GetEventMask(event.events);
+  auto event_status = client->GetEventMask(pfd.revents);
   ASSERT_TRUE(event_status.ok());
   ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0);
 }
diff --git a/libs/vr/libperformance/include/dvr/performance_client_api.h b/libs/vr/libperformance/include/dvr/performance_client_api.h
index 2216e38..9d617cb 100644
--- a/libs/vr/libperformance/include/dvr/performance_client_api.h
+++ b/libs/vr/libperformance/include/dvr/performance_client_api.h
@@ -8,6 +8,20 @@
 extern "C" {
 #endif
 
+/// Sets the scheduler policy for a task.
+///
+/// Sets the scheduler policy for a task to the class described by a semantic
+/// string.
+///
+/// Supported policies are device-specific.
+///
+/// @param task_id The task id of task to set the policy for. When task_id is 0
+/// the current task id is substituted.
+/// @param scheduler_policy NULL-terminated ASCII string containing the desired
+/// scheduler policy.
+/// @returns Returns 0 on success or a negative errno error code on error.
+int dvrSetSchedulerPolicy(pid_t task_id, const char* scheduler_policy);
+
 /// Sets the CPU partition for a task.
 ///
 /// Sets the CPU partition for a task to the partition described by a CPU
diff --git a/libs/vr/libperformance/include/private/dvr/performance_client.h b/libs/vr/libperformance/include/private/dvr/performance_client.h
index a61c6b2..3bd90dc 100644
--- a/libs/vr/libperformance/include/private/dvr/performance_client.h
+++ b/libs/vr/libperformance/include/private/dvr/performance_client.h
@@ -14,6 +14,10 @@
 
 class PerformanceClient : public pdx::ClientBase<PerformanceClient> {
  public:
+  int SetSchedulerPolicy(pid_t task_id, const std::string& scheduler_policy);
+  int SetSchedulerPolicy(pid_t task_id, const char* scheduler_policy);
+
+  // TODO(eieio): Consider deprecating this API.
   int SetCpuPartition(pid_t task_id, const std::string& partition);
   int SetCpuPartition(pid_t task_id, const char* partition);
   int SetSchedulerClass(pid_t task_id, const std::string& scheduler_class);
diff --git a/libs/vr/libperformance/include/private/dvr/performance_rpc.h b/libs/vr/libperformance/include/private/dvr/performance_rpc.h
index 73bdaa7..d57bbe8 100644
--- a/libs/vr/libperformance/include/private/dvr/performance_rpc.h
+++ b/libs/vr/libperformance/include/private/dvr/performance_rpc.h
@@ -21,14 +21,17 @@
     kOpSetCpuPartition = 0,
     kOpSetSchedulerClass,
     kOpGetCpuPartition,
+    kOpSetSchedulerPolicy,
   };
 
   // Methods.
   PDX_REMOTE_METHOD(SetCpuPartition, kOpSetCpuPartition,
-                    int(pid_t, const std::string&));
+                    void(pid_t, const std::string&));
   PDX_REMOTE_METHOD(SetSchedulerClass, kOpSetSchedulerClass,
-                    int(pid_t, const std::string&));
+                    void(pid_t, const std::string&));
   PDX_REMOTE_METHOD(GetCpuPartition, kOpGetCpuPartition, std::string(pid_t));
+  PDX_REMOTE_METHOD(SetSchedulerPolicy, kOpSetSchedulerPolicy,
+                    void(pid_t, const std::string&));
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libperformance/performance_client.cpp b/libs/vr/libperformance/performance_client.cpp
index 2124162..bf3726e 100644
--- a/libs/vr/libperformance/performance_client.cpp
+++ b/libs/vr/libperformance/performance_client.cpp
@@ -37,6 +37,26 @@
           task_id, WrapString(partition)));
 }
 
+int PerformanceClient::SetSchedulerPolicy(pid_t task_id,
+                                          const std::string& scheduler_policy) {
+  if (task_id == 0)
+    task_id = gettid();
+
+  return ReturnStatusOrError(
+      InvokeRemoteMethod<PerformanceRPC::SetSchedulerPolicy>(task_id,
+                                                             scheduler_policy));
+}
+
+int PerformanceClient::SetSchedulerPolicy(pid_t task_id,
+                                          const char* scheduler_policy) {
+  if (task_id == 0)
+    task_id = gettid();
+
+  return ReturnStatusOrError(
+      InvokeRemoteMethod<PerformanceRPC::SetSchedulerPolicy>(
+          task_id, WrapString(scheduler_policy)));
+}
+
 int PerformanceClient::SetSchedulerClass(pid_t task_id,
                                          const std::string& scheduler_class) {
   if (task_id == 0)
@@ -101,6 +121,15 @@
     return error;
 }
 
+extern "C" int dvrSetSchedulerPolicy(pid_t task_id,
+                                     const char* scheduler_policy) {
+  int error;
+  if (auto client = android::dvr::PerformanceClient::Create(&error))
+    return client->SetSchedulerPolicy(task_id, scheduler_policy);
+  else
+    return error;
+}
+
 extern "C" int dvrSetSchedulerClass(pid_t task_id,
                                     const char* scheduler_class) {
   int error;
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index de26a74..0fb2d84 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -34,8 +34,10 @@
     "libdvrcommon",
     "libperformance",
     "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
     "libvr_manager",
+    "libbroadcastring",
 ]
 
 sharedLibraries = [
@@ -61,6 +63,10 @@
     "libfmq",
 ]
 
+headerLibraries = [
+    "libdvr_headers"
+]
+
 cc_library_static {
     srcs: sourceFiles,
     export_include_dirs: includeFiles,
@@ -74,5 +80,6 @@
     ],
     shared_libs: sharedLibraries,
     whole_static_libs: staticLibraries,
+    header_libs: headerLibraries,
     name: "libvrflinger",
 }
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 7932a9c..9614c6d 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -9,8 +9,8 @@
 namespace dvr {
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                               LocalHandle acquire_fence)
-    : buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
+                               LocalHandle acquire_fence, std::size_t slot)
+    : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
                                int* error) {
@@ -31,18 +31,20 @@
   }
 }
 
-AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other)
-    : buffer_(std::move(other.buffer_)),
-      acquire_fence_(std::move(other.acquire_fence_)) {}
+AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) {
+  *this = std::move(other);
+}
 
 AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
 
 AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
   if (this != &other) {
-    Release(LocalHandle(kEmptyFence));
+    Release();
 
-    buffer_ = std::move(other.buffer_);
-    acquire_fence_ = std::move(other.acquire_fence_);
+    using std::swap;
+    swap(buffer_, other.buffer_);
+    swap(acquire_fence_, other.acquire_fence_);
+    swap(slot_, other.slot_);
   }
   return *this;
 }
@@ -55,9 +57,9 @@
   if (acquire_fence_) {
     const int ret = sync_wait(acquire_fence_.Get(), 0);
     ALOGD_IF(TRACE || (ret < 0 && errno != ETIME),
-             "AcquiredBuffer::IsAvailable: acquire_fence_=%d sync_wait()=%d "
-             "errno=%d.",
-             acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
+             "AcquiredBuffer::IsAvailable: buffer_id=%d acquire_fence=%d "
+             "sync_wait()=%d errno=%d.",
+             buffer_->id(), acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
     if (ret == 0) {
       // The fence is completed, so to avoid further calls to sync_wait we close
       // it here.
@@ -78,9 +80,9 @@
 }
 
 int AcquiredBuffer::Release(LocalHandle release_fence) {
+  ALOGD_IF(TRACE, "AcquiredBuffer::Release: buffer_id=%d release_fence=%d",
+           buffer_ ? buffer_->id() : -1, release_fence.Get());
   if (buffer_) {
-    // Close the release fence since we can't transfer it with an async release.
-    release_fence.Close();
     const int ret = buffer_->ReleaseAsync();
     if (ret < 0) {
       ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s",
@@ -90,9 +92,10 @@
     }
 
     buffer_ = nullptr;
-    acquire_fence_.Close();
   }
 
+  acquire_fence_.Close();
+  slot_ = 0;
   return 0;
 }
 
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index dd4fcc5..32e912a 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -21,7 +21,7 @@
   // this constructor; the constructor does not attempt to ACQUIRE the buffer
   // itself.
   AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                 pdx::LocalHandle acquire_fence);
+                 pdx::LocalHandle acquire_fence, std::size_t slot = 0);
 
   // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
   // be in the POSTED state prior to calling this constructor, as this
@@ -64,16 +64,21 @@
   // to the producer. On success, the BufferConsumer and acquire fence are set
   // to empty state; if release fails, the BufferConsumer and acquire fence are
   // left in place and a negative error code is returned.
-  int Release(pdx::LocalHandle release_fence);
+  int Release(pdx::LocalHandle release_fence = {});
+
+  // Returns the slot in the queue this buffer belongs to. Buffers that are not
+  // part of a queue return 0.
+  std::size_t slot() const { return slot_; }
 
  private:
-  AcquiredBuffer(const AcquiredBuffer&) = delete;
-  void operator=(const AcquiredBuffer&) = delete;
-
   std::shared_ptr<BufferConsumer> buffer_;
   // Mutable so that the fence can be closed when it is determined to be
   // signaled during IsAvailable().
   mutable pdx::LocalHandle acquire_fence_;
+  std::size_t slot_{0};
+
+  AcquiredBuffer(const AcquiredBuffer&) = delete;
+  void operator=(const AcquiredBuffer&) = delete;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index a0b3efe..ef8cca3 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -65,6 +65,7 @@
 }
 
 pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
+  ATRACE_NAME("DisplayManagerService::HandleMessage");
   auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
 
   switch (message.GetOp()) {
@@ -78,11 +79,6 @@
           *this, &DisplayManagerService::OnGetSurfaceQueue, message);
       return {};
 
-    case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
-          *this, &DisplayManagerService::OnSetupNamedBuffer, message);
-      return {};
-
     default:
       return Service::DefaultHandleMessage(message);
   }
@@ -129,23 +125,6 @@
   return status;
 }
 
-pdx::Status<BorrowedNativeBufferHandle>
-DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
-                                          const std::string& name, size_t size,
-                                          uint64_t usage) {
-  const int user_id = message.GetEffectiveUserId();
-  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
-
-  if (!trusted) {
-    ALOGE(
-        "DisplayService::SetupNamedBuffer: Named buffers may only be created "
-        "by trusted UIDs: user_id=%d",
-        user_id);
-    return ErrorStatus(EPERM);
-  }
-  return display_service_->SetupNamedBuffer(name, size, usage);
-}
-
 void DisplayManagerService::OnDisplaySurfaceChange() {
   if (display_manager_)
     display_manager_->SetNotificationsPending(true);
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 0857eb5..3133fe1 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -56,9 +56,6 @@
   pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
                                                          int surface_id,
                                                          int queue_id);
-  pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
-      pdx::Message& message, const std::string& name, size_t size,
-      uint64_t usage);
 
   // Called by the display service to indicate changes to display surfaces that
   // the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 47efa76..ac68a5e 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,13 +1,21 @@
 #include "display_service.h"
 
 #include <unistd.h>
+
+#include <algorithm>
+#include <sstream>
+#include <string>
 #include <vector>
 
+#include <android-base/file.h>
+#include <android-base/properties.h>
 #include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <pdx/rpc/remote_method.h>
+#include <private/android_filesystem_config.h>
 #include <private/dvr/display_protocol.h>
 #include <private/dvr/numeric.h>
+#include <private/dvr/trusted_uids.h>
 #include <private/dvr/types.h>
 
 using android::dvr::display::DisplayProtocol;
@@ -18,16 +26,22 @@
 using android::pdx::default_transport::Endpoint;
 using android::pdx::rpc::DispatchRemoteMethod;
 
+namespace {
+
+const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
+const char kDvrDeviceMetricsProperty[] = "ro.dvr.device_metrics";
+const char kDvrDeviceConfigProperty[] = "ro.dvr.device_configuration";
+
+}  // namespace
+
 namespace android {
 namespace dvr {
 
 DisplayService::DisplayService(Hwc2::Composer* hidl,
                                RequestDisplayCallback request_display_callback)
     : BASE("DisplayService",
-           Endpoint::Create(display::DisplayProtocol::kClientPath)),
-      hardware_composer_(hidl, request_display_callback),
-      request_display_callback_(request_display_callback) {
-  hardware_composer_.Initialize();
+           Endpoint::Create(display::DisplayProtocol::kClientPath)) {
+  hardware_composer_.Initialize(hidl, request_display_callback);
 }
 
 bool DisplayService::IsInitialized() const {
@@ -35,7 +49,65 @@
 }
 
 std::string DisplayService::DumpState(size_t /*max_length*/) {
-  return hardware_composer_.Dump();
+  std::ostringstream stream;
+
+  auto surfaces = GetDisplaySurfaces();
+  std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
+    return a->surface_id() < b->surface_id();
+  });
+
+  stream << "Application Surfaces:" << std::endl;
+
+  size_t count = 0;
+  for (const auto& surface : surfaces) {
+    if (surface->surface_type() == SurfaceType::Application) {
+      stream << "Surface " << count++ << ":";
+      stream << " surface_id=" << surface->surface_id()
+             << " process_id=" << surface->process_id()
+             << " user_id=" << surface->user_id()
+             << " visible=" << surface->visible()
+             << " z_order=" << surface->z_order();
+
+      stream << " queue_ids=";
+      auto queue_ids = surface->GetQueueIds();
+      std::sort(queue_ids.begin(), queue_ids.end());
+      for (int32_t id : queue_ids) {
+        if (id != queue_ids[0])
+          stream << ",";
+        stream << id;
+      }
+      stream << std::endl;
+    }
+  }
+  stream << std::endl;
+
+  stream << "Direct Surfaces:" << std::endl;
+
+  count = 0;
+  for (const auto& surface : surfaces) {
+    if (surface->surface_type() == SurfaceType::Direct) {
+      stream << "Surface " << count++ << ":";
+      stream << " surface_id=" << surface->surface_id()
+             << " process_id=" << surface->process_id()
+             << " user_id=" << surface->user_id()
+             << " visible=" << surface->visible()
+             << " z_order=" << surface->z_order();
+
+      stream << " queue_ids=";
+      auto queue_ids = surface->GetQueueIds();
+      std::sort(queue_ids.begin(), queue_ids.end());
+      for (int32_t id : queue_ids) {
+        if (id != queue_ids[0])
+          stream << ",";
+        stream << id;
+      }
+      stream << std::endl;
+    }
+  }
+  stream << std::endl;
+
+  stream << hardware_composer_.Dump();
+  return stream.str();
 }
 
 void DisplayService::OnChannelClose(pdx::Message& message,
@@ -44,8 +116,6 @@
     surface->OnSetAttributes(message,
                              {{display::SurfaceAttribute::Visible,
                                display::SurfaceAttributeValue{false}}});
-    SurfaceUpdated(surface->surface_type(),
-                   display::SurfaceUpdateFlags::VisibilityChanged);
   }
 }
 
@@ -54,20 +124,37 @@
 // surface-specific messages to the per-instance handlers.
 Status<void> DisplayService::HandleMessage(pdx::Message& message) {
   ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
+  ATRACE_NAME("DisplayService::HandleMessage");
+
   switch (message.GetOp()) {
     case DisplayProtocol::GetMetrics::Opcode:
       DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
           *this, &DisplayService::OnGetMetrics, message);
       return {};
 
+    case DisplayProtocol::GetConfigurationData::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetConfigurationData>(
+          *this, &DisplayService::OnGetConfigurationData, message);
+      return {};
+
     case DisplayProtocol::CreateSurface::Opcode:
       DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
           *this, &DisplayService::OnCreateSurface, message);
       return {};
 
-    case DisplayProtocol::GetNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
-          *this, &DisplayService::OnGetNamedBuffer, message);
+    case DisplayProtocol::SetupGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(
+          *this, &DisplayService::OnSetupGlobalBuffer, message);
+      return {};
+
+    case DisplayProtocol::DeleteGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(
+          *this, &DisplayService::OnDeleteGlobalBuffer, message);
+      return {};
+
+    case DisplayProtocol::GetGlobalBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetGlobalBuffer>(
+          *this, &DisplayService::OnGetGlobalBuffer, message);
       return {};
 
     case DisplayProtocol::IsVrAppRunning::Opcode:
@@ -102,6 +189,35 @@
            {}}};
 }
 
+pdx::Status<std::string> DisplayService::OnGetConfigurationData(
+    pdx::Message& /*message*/, display::ConfigFileType config_type) {
+  std::string property_name;
+  switch (config_type) {
+    case display::ConfigFileType::kLensMetrics:
+      property_name = kDvrLensMetricsProperty;
+      break;
+    case display::ConfigFileType::kDeviceMetrics:
+      property_name = kDvrDeviceMetricsProperty;
+      break;
+    case display::ConfigFileType::kDeviceConfiguration:
+      property_name = kDvrDeviceConfigProperty;
+      break;
+    default:
+      return ErrorStatus(EINVAL);
+  }
+  std::string file_path = base::GetProperty(property_name, "");
+  if (file_path.empty()) {
+    return ErrorStatus(ENOENT);
+  }
+
+  std::string data;
+  if (!base::ReadFileToString(file_path, &data)) {
+    return ErrorStatus(errno);
+  }
+
+  return std::move(data);
+}
+
 // Creates a new DisplaySurface and associates it with this channel. This may
 // only be done once per channel.
 Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
@@ -129,18 +245,16 @@
           surface_status.GetErrorMessage().c_str());
     return ErrorStatus(surface_status.error());
   }
+  auto surface = surface_status.take();
+  message.SetChannel(surface);
 
-  SurfaceType surface_type = surface_status.get()->surface_type();
-  display::SurfaceUpdateFlags update_flags =
-      surface_status.get()->update_flags();
-  display::SurfaceInfo surface_info{surface_status.get()->surface_id(),
-                                    surface_status.get()->visible(),
-                                    surface_status.get()->z_order()};
+  // Update the surface with the attributes supplied with the create call. For
+  // application surfaces this has the side effect of notifying the display
+  // manager of the new surface. For direct surfaces, this may trigger a mode
+  // change, depending on the value of the visible attribute.
+  surface->OnSetAttributes(message, attributes);
 
-  message.SetChannel(surface_status.take());
-
-  SurfaceUpdated(surface_type, update_flags);
-  return {surface_info};
+  return {{surface->surface_id(), surface->visible(), surface->z_order()}};
 }
 
 void DisplayService::SurfaceUpdated(SurfaceType surface_type,
@@ -155,12 +269,42 @@
   }
 }
 
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
-    pdx::Message& /* message */, const std::string& name) {
-  ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
-  auto named_buffer = named_buffers_.find(name);
-  if (named_buffer != named_buffers_.end())
-    return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnSetupGlobalBuffer(
+    pdx::Message& message, DvrGlobalBufferKey key, size_t size,
+    uint64_t usage) {
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+  if (!trusted) {
+    ALOGE(
+        "DisplayService::OnSetupGlobalBuffer: Permission denied for user_id=%d",
+        user_id);
+    return ErrorStatus(EPERM);
+  }
+  return SetupGlobalBuffer(key, size, usage);
+}
+
+pdx::Status<void> DisplayService::OnDeleteGlobalBuffer(pdx::Message& message,
+                                                       DvrGlobalBufferKey key) {
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = (user_id == AID_ROOT) || IsTrustedUid(user_id);
+
+  if (!trusted) {
+    ALOGE(
+        "DisplayService::OnDeleteGlobalBuffer: Permission denied for "
+        "user_id=%d",
+        user_id);
+    return ErrorStatus(EPERM);
+  }
+  return DeleteGlobalBuffer(key);
+}
+
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetGlobalBuffer(
+    pdx::Message& /* message */, DvrGlobalBufferKey key) {
+  ALOGD_IF(TRACE, "DisplayService::OnGetGlobalBuffer: key=%d", key);
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer != global_buffers_.end())
+    return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
   else
     return pdx::ErrorStatus(EINVAL);
 }
@@ -207,36 +351,41 @@
 
 void DisplayService::UpdateActiveDisplaySurfaces() {
   auto visible_surfaces = GetVisibleDisplaySurfaces();
-
-  std::sort(visible_surfaces.begin(), visible_surfaces.end(),
-            [](const std::shared_ptr<DisplaySurface>& a,
-               const std::shared_ptr<DisplaySurface>& b) {
-              return a->z_order() < b->z_order();
-            });
-
   ALOGD_IF(TRACE,
            "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
            visible_surfaces.size());
-
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
-pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
-    const std::string& name, size_t size, uint64_t usage) {
-  auto named_buffer = named_buffers_.find(name);
-  if (named_buffer == named_buffers_.end()) {
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupGlobalBuffer(
+    DvrGlobalBufferKey key, size_t size, uint64_t usage) {
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer == global_buffers_.end()) {
     auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
                                                   HAL_PIXEL_FORMAT_BLOB, usage);
-    named_buffer =
-        named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+
+    // Some buffers are used internally. If they were configured with an
+    // invalid size or format, this will fail.
+    int result = hardware_composer_.OnNewGlobalBuffer(key, *ion_buffer.get());
+    if (result < 0)
+      return ErrorStatus(result);
+    global_buffer =
+        global_buffers_.insert(std::make_pair(key, std::move(ion_buffer)))
             .first;
   }
 
-  return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
+  return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
 }
 
-void DisplayService::OnHardwareComposerRefresh() {
-  hardware_composer_.OnHardwareComposerRefresh();
+pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
+  auto global_buffer = global_buffers_.find(key);
+  if (global_buffer != global_buffers_.end()) {
+    // Some buffers are used internally.
+    hardware_composer_.OnDeletedGlobalBuffer(key);
+    global_buffers_.erase(global_buffer);
+  }
+
+  return {0};
 }
 
 void DisplayService::SetDisplayConfigurationUpdateNotifier(
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index bb4eeef..55e33ab 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -1,6 +1,7 @@
 #ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 #define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 
+#include <dvr/dvr_api.h>
 #include <pdx/service.h>
 #include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
@@ -40,8 +41,10 @@
   // any change to client/manager attributes that affect visibility or z order.
   void UpdateActiveDisplaySurfaces();
 
-  pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
-      const std::string& name, size_t size, uint64_t usage);
+  pdx::Status<BorrowedNativeBufferHandle> SetupGlobalBuffer(
+      DvrGlobalBufferKey key, size_t size, uint64_t usage);
+
+  pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key);
 
   template <class A>
   void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
@@ -69,8 +72,6 @@
   void GrantDisplayOwnership() { hardware_composer_.Enable(); }
   void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
 
-  void OnHardwareComposerRefresh();
-
  private:
   friend BASE;
   friend DisplaySurface;
@@ -82,11 +83,18 @@
   DisplayService(android::Hwc2::Composer* hidl,
                  RequestDisplayCallback request_display_callback);
 
-  pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
-      pdx::Message& message, const std::string& name);
+  pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer(
+      pdx::Message& message, DvrGlobalBufferKey key);
   pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
+  pdx::Status<std::string> OnGetConfigurationData(
+      pdx::Message& message, display::ConfigFileType config_type);
   pdx::Status<display::SurfaceInfo> OnCreateSurface(
       pdx::Message& message, const display::SurfaceAttributes& attributes);
+  pdx::Status<BorrowedNativeBufferHandle> OnSetupGlobalBuffer(
+      pdx::Message& message, DvrGlobalBufferKey key, size_t size,
+      uint64_t usage);
+  pdx::Status<void> OnDeleteGlobalBuffer(pdx::Message& message,
+                                         DvrGlobalBufferKey key);
 
   // Temporary query for current VR status. Will be removed later.
   pdx::Status<bool> IsVrAppRunning(pdx::Message& message);
@@ -109,11 +117,11 @@
   pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
 
   HardwareComposer hardware_composer_;
-  RequestDisplayCallback request_display_callback_;
   EpollEventDispatcher dispatcher_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
-  std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+  std::unordered_map<DvrGlobalBufferKey, std::unique_ptr<IonBuffer>>
+      global_buffers_;
 
   DisplayService(const DisplayService&) = delete;
   void operator=(const DisplayService&) = delete;
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index fb2751b..87c823e 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,14 +26,12 @@
 
 DisplaySurface::DisplaySurface(DisplayService* service,
                                SurfaceType surface_type, int surface_id,
-                               int process_id, int user_id,
-                               const display::SurfaceAttributes& attributes)
+                               int process_id, int user_id)
     : service_(service),
       surface_type_(surface_type),
       surface_id_(surface_id),
       process_id_(process_id),
       user_id_(user_id),
-      attributes_(attributes),
       update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
 
 DisplaySurface::~DisplaySurface() {
@@ -68,7 +66,7 @@
   display::SurfaceUpdateFlags update_flags;
 
   for (const auto& attribute : attributes) {
-    const auto& key = attribute.first;
+    const auto key = attribute.first;
     const auto* variant = &attribute.second;
     bool invalid_value = false;
     bool visibility_changed = false;
@@ -95,14 +93,23 @@
         break;
     }
 
+    // Only update the attribute map with valid values. This check also has the
+    // effect of preventing special attributes handled above from being deleted
+    // by an empty value.
     if (invalid_value) {
       ALOGW(
           "DisplaySurface::OnClientSetAttributes: Failed to set display "
           "surface attribute '%d' because of incompatible type: %d",
           key, variant->index());
     } else {
-      // Only update the attribute map with valid values.
-      attributes_[attribute.first] = attribute.second;
+      // An empty value indicates the attribute should be deleted.
+      if (variant->empty()) {
+        auto search = attributes_.find(key);
+        if (search != attributes_.end())
+          attributes_.erase(search);
+      } else {
+        attributes_[key] = *variant;
+      }
 
       // All attribute changes generate a notification, even if the value
       // doesn't change. Visibility attributes set a flag only if the value
@@ -127,7 +134,8 @@
 }
 
 void DisplaySurface::ClearUpdate() {
-  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
+  ALOGD_IF(TRACE > 1, "DisplaySurface::ClearUpdate: surface_id=%d",
+           surface_id());
   update_flags_ = display::SurfaceUpdateFlags::None;
 }
 
@@ -184,6 +192,7 @@
            "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
            surface_id(), queue_id);
 
+  std::lock_guard<std::mutex> autolock(lock_);
   auto search = consumer_queues_.find(queue_id);
   if (search != consumer_queues_.end())
     return search->second;
@@ -192,6 +201,7 @@
 }
 
 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
   std::vector<int32_t> queue_ids;
   for (const auto& entry : consumer_queues_)
     queue_ids.push_back(entry.first);
@@ -199,15 +209,15 @@
 }
 
 Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
-    Message& /*message*/, size_t meta_size_bytes) {
+    Message& /*message*/, const ProducerQueueConfig& config) {
   ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
   ALOGD_IF(TRACE,
            "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
-           "meta_size_bytes=%zu",
-           surface_id(), meta_size_bytes);
+           "user_metadata_size=%zu",
+           surface_id(), config.user_metadata_size);
 
   std::lock_guard<std::mutex> autolock(lock_);
-  auto producer = ProducerQueue::Create(meta_size_bytes);
+  auto producer = ProducerQueue::Create(config, UsagePolicy{});
   if (!producer) {
     ALOGE(
         "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
@@ -238,11 +248,12 @@
            "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
            consumer_queue->id(), events);
 
+  std::lock_guard<std::mutex> autolock(lock_);
+
   // Always give the queue a chance to handle its internal bookkeeping.
   consumer_queue->HandleQueueEvents();
 
   // Check for hangup and remove a queue that is no longer needed.
-  std::lock_guard<std::mutex> autolock(lock_);
   if (consumer_queue->hung_up()) {
     ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
     UnregisterQueue(consumer_queue);
@@ -258,17 +269,28 @@
   }
 }
 
+std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
+  std::vector<int32_t> queue_ids;
+  if (direct_queue_)
+    queue_ids.push_back(direct_queue_->id());
+  return queue_ids;
+}
+
 Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
-    Message& /*message*/, size_t meta_size_bytes) {
+    Message& /*message*/, const ProducerQueueConfig& config) {
   ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
-  ALOGD_IF(
-      TRACE,
-      "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
-      surface_id(), meta_size_bytes);
+  ALOGD_IF(TRACE,
+           "DirectDisplaySurface::OnCreateQueue: surface_id=%d "
+           "user_metadata_size=%zu",
+           surface_id(), config.user_metadata_size);
 
   std::lock_guard<std::mutex> autolock(lock_);
   if (!direct_queue_) {
-    auto producer = ProducerQueue::Create(meta_size_bytes);
+    // Inject the hw composer usage flag to enable the display to read the
+    // buffers.
+    auto producer = ProducerQueue::Create(
+        config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
     if (!producer) {
       ALOGE(
           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
@@ -277,6 +299,9 @@
     }
 
     direct_queue_ = producer->CreateConsumerQueue();
+    if (direct_queue_->metadata_size() > 0) {
+      metadata_.reset(new uint8_t[direct_queue_->metadata_size()]);
+    }
     auto status = RegisterQueue(direct_queue_);
     if (!status) {
       ALOGE(
@@ -297,11 +322,12 @@
   ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
            consumer_queue->id(), events);
 
+  std::lock_guard<std::mutex> autolock(lock_);
+
   // Always give the queue a chance to handle its internal bookkeeping.
   consumer_queue->HandleQueueEvents();
 
   // Check for hangup and remove a queue that is no longer needed.
-  std::lock_guard<std::mutex> autolock(lock_);
   if (consumer_queue->hung_up()) {
     ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
     UnregisterQueue(consumer_queue);
@@ -320,10 +346,15 @@
   while (true) {
     LocalHandle acquire_fence;
     size_t slot;
-    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
+    auto buffer_status = direct_queue_->Dequeue(
+        0, &slot, metadata_.get(),
+        direct_queue_->metadata_size(), &acquire_fence);
+    ALOGD_IF(TRACE,
+             "DirectDisplaySurface::DequeueBuffersLocked: Dequeue with metadata_size: %zu",
+             direct_queue_->metadata_size());
     if (!buffer_status) {
       ALOGD_IF(
-          TRACE && buffer_status.error() == ETIMEDOUT,
+          TRACE > 1 && buffer_status.error() == ETIMEDOUT,
           "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
       ALOGE_IF(buffer_status.error() != ETIMEDOUT,
                "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
@@ -351,7 +382,7 @@
     }
 
     acquired_buffers_.Append(
-        AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
+        AcquiredBuffer(buffer_consumer, std::move(acquire_fence), slot));
   }
 }
 
@@ -367,8 +398,8 @@
   }
   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
   acquired_buffers_.PopFront();
-  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
-           buffer.buffer().get());
+  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d",
+           buffer.buffer()->id());
   return buffer;
 }
 
@@ -396,8 +427,8 @@
       break;
   }
   ALOGD_IF(TRACE,
-           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
-           buffer.buffer().get());
+           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d",
+           buffer.buffer()->id());
   return buffer;
 }
 
@@ -438,8 +469,8 @@
   if (direct) {
     const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
     if (trusted) {
-      return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
-          service, surface_id, process_id, user_id, attributes)}};
+      return {std::shared_ptr<DisplaySurface>{
+          new DirectDisplaySurface(service, surface_id, process_id, user_id)}};
     } else {
       ALOGE(
           "DisplaySurface::Create: Direct surfaces may only be created by "
@@ -449,7 +480,7 @@
     }
   } else {
     return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
-        service, surface_id, process_id, user_id, attributes)}};
+        service, surface_id, process_id, user_id)}};
   }
 }
 
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index c456b10..c8b1a07 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -53,8 +53,7 @@
 
  protected:
   DisplaySurface(DisplayService* service, SurfaceType surface_type,
-                 int surface_id, int process_id, int user_id,
-                 const display::SurfaceAttributes& attributes);
+                 int surface_id, int process_id, int user_id);
 
   // Utility to retrieve a shared pointer to this channel as the desired derived
   // type.
@@ -66,7 +65,7 @@
   }
 
   virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
-      pdx::Message& message, size_t meta_size_bytes) = 0;
+      pdx::Message& message, const ProducerQueueConfig& config) = 0;
 
   // Registers a consumer queue with the event dispatcher in DisplayService. The
   // OnQueueEvent callback below is called to handle queue events.
@@ -119,31 +118,32 @@
 class ApplicationDisplaySurface : public DisplaySurface {
  public:
   ApplicationDisplaySurface(DisplayService* service, int surface_id,
-                            int process_id, int user_id,
-                            const display::SurfaceAttributes& attributes)
+                            int process_id, int user_id)
       : DisplaySurface(service, SurfaceType::Application, surface_id,
-                       process_id, user_id, attributes) {}
+                       process_id, user_id) {}
 
   std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
   std::vector<int32_t> GetQueueIds() const override;
 
  private:
   pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
-      pdx::Message& message, size_t meta_size_bytes) override;
+      pdx::Message& message, const ProducerQueueConfig& config) override;
   void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                     int events) override;
 
+  // Accessed by both message dispatch thread and epoll event thread.
   std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
 };
 
 class DirectDisplaySurface : public DisplaySurface {
  public:
   DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
-                       int user_id,
-                       const display::SurfaceAttributes& attributes)
+                       int user_id)
       : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
-                       user_id, attributes),
-        acquired_buffers_(kMaxPostedBuffers) {}
+                       user_id),
+        acquired_buffers_(kMaxPostedBuffers),
+        metadata_(nullptr) {}
+  std::vector<int32_t> GetQueueIds() const override;
   bool IsBufferAvailable();
   bool IsBufferPosted();
   AcquiredBuffer AcquireCurrentBuffer();
@@ -154,7 +154,7 @@
 
  private:
   pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
-      pdx::Message& message, size_t meta_size_bytes) override;
+      pdx::Message& message, const ProducerQueueConfig& config) override;
   void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                     int events) override;
 
@@ -177,6 +177,9 @@
   RingBuffer<AcquiredBuffer> acquired_buffers_;
 
   std::shared_ptr<ConsumerQueue> direct_queue_;
+
+  // Stores metadata when it dequeue buffers from consumer queue.
+  std::unique_ptr<uint8_t[]> metadata_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
index 06b69bb..962c745 100644
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -101,12 +101,12 @@
     if (num_events < 0 && errno != EINTR)
       break;
 
-    ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
+    ALOGD_IF(TRACE > 1, "EpollEventDispatcher::EventThread: num_events=%d",
              num_events);
 
     for (int i = 0; i < num_events; i++) {
       ALOGD_IF(
-          TRACE,
+          TRACE > 1,
           "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
           i, events[i].data.ptr, events[i].events);
 
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 34474d9..b3da120 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -5,12 +5,14 @@
 #include <fcntl.h>
 #include <log/log.h>
 #include <poll.h>
+#include <stdint.h>
 #include <sync/sync.h>
 #include <sys/eventfd.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/system_properties.h>
 #include <sys/timerfd.h>
+#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 #include <utils/Trace.h>
@@ -19,14 +21,20 @@
 #include <chrono>
 #include <functional>
 #include <map>
+#include <sstream>
+#include <string>
+#include <tuple>
 
 #include <dvr/dvr_display_types.h>
 #include <dvr/performance_client_api.h>
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/ion_buffer.h>
-#include <private/dvr/pose_client_internal.h>
 
+using android::hardware::Return;
+using android::hardware::Void;
+using android::pdx::ErrorStatus;
 using android::pdx::LocalHandle;
+using android::pdx::Status;
 using android::pdx::rpc::EmptyVariant;
 using android::pdx::rpc::IfAnyOf;
 
@@ -37,26 +45,11 @@
 
 namespace {
 
-// If the number of pending fences goes over this count at the point when we
-// are about to submit a new frame to HWC, we will drop the frame. This should
-// be a signal that the display driver has begun queuing frames. Note that with
-// smart displays (with RAM), the fence is signaled earlier than the next vsync,
-// at the point when the DMA to the display completes. Currently we use a smart
-// display and the EDS timing coincides with zero pending fences, so this is 0.
-constexpr int kAllowedPendingFenceCount = 0;
-
-// Offset before vsync to submit frames to hardware composer.
-constexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
-
 const char kBacklightBrightnessSysFile[] =
     "/sys/class/leds/lcd-backlight/brightness";
 
-const char kPrimaryDisplayVSyncEventFile[] =
-    "/sys/class/graphics/fb0/vsync_event";
-
-const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
-
 const char kDvrPerformanceProperty[] = "sys.dvr.performance";
+const char kDvrStandaloneProperty[] = "ro.boot.vr";
 
 const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
 
@@ -93,24 +86,33 @@
   return true;
 }
 
+// Utility to generate scoped tracers with arguments.
+// TODO(eieio): Move/merge this into utils/Trace.h?
+class TraceArgs {
+ public:
+  template <typename... Args>
+  TraceArgs(const char* format, Args&&... args) {
+    std::array<char, 1024> buffer;
+    snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
+    atrace_begin(ATRACE_TAG, buffer.data());
+  }
+
+  ~TraceArgs() { atrace_end(ATRACE_TAG); }
+
+ private:
+  TraceArgs(const TraceArgs&) = delete;
+  void operator=(const TraceArgs&) = delete;
+};
+
+// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
+// defined in utils/Trace.h.
+#define TRACE_FORMAT(format, ...) \
+  TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
+
 }  // anonymous namespace
 
-// Layer static data.
-Hwc2::Composer* Layer::hwc2_hidl_;
-const HWCDisplayMetrics* Layer::display_metrics_;
-
-// HardwareComposer static data;
-constexpr size_t HardwareComposer::kMaxHardwareLayers;
-
 HardwareComposer::HardwareComposer()
-    : HardwareComposer(nullptr, RequestDisplayCallback()) {}
-
-HardwareComposer::HardwareComposer(
-    Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
-    : initialized_(false),
-      hwc2_hidl_(hwc2_hidl),
-      request_display_callback_(request_display_callback),
-      callbacks_(new ComposerCallback) {}
+    : initialized_(false), request_display_callback_(nullptr) {}
 
 HardwareComposer::~HardwareComposer(void) {
   UpdatePostThreadState(PostThreadState::Quit, true);
@@ -118,16 +120,21 @@
     post_thread_.join();
 }
 
-bool HardwareComposer::Initialize() {
+bool HardwareComposer::Initialize(
+    Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
   if (initialized_) {
     ALOGE("HardwareComposer::Initialize: already initialized.");
     return false;
   }
 
+  is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
+
+  request_display_callback_ = request_display_callback;
+
   HWC::Error error = HWC::Error::None;
 
   Hwc2::Config config;
-  error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+  error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
 
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -135,8 +142,8 @@
     return false;
   }
 
-  error =
-      GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
+  error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
+                            &native_display_metrics_);
 
   if (error != HWC::Error::None) {
     ALOGE(
@@ -158,8 +165,8 @@
   display_transform_ = HWC_TRANSFORM_NONE;
   display_metrics_ = native_display_metrics_;
 
-  // Pass hwc instance and metrics to setup globals for Layer.
-  Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
+  // Setup the display metrics used by all Layer instances.
+  Layer::SetDisplayMetrics(native_display_metrics_);
 
   post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
   LOG_ALWAYS_FATAL_IF(
@@ -219,19 +226,19 @@
 }
 
 void HardwareComposer::OnPostThreadResumed() {
-  hwc2_hidl_->resetCommands();
+  // Phones create a new composer client on resume and destroy it on pause.
+  // Standalones only create the composer client once and then use SetPowerMode
+  // to control the screen on pause/resume.
+  if (!is_standalone_device_ || !composer_) {
+    composer_.reset(new Hwc2::Composer(false));
+    composer_callback_ = new ComposerCallback;
+    composer_->registerCallback(composer_callback_);
+    Layer::SetComposer(composer_.get());
+  } else {
+    SetPowerMode(true);
+  }
 
-  // Connect to pose service.
-  pose_client_ = dvrPoseCreate();
-  ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
-
-  // HIDL HWC seems to have an internal race condition. If we submit a frame too
-  // soon after turning on VSync we don't get any VSync signals. Give poor HWC
-  // implementations a chance to enable VSync before we continue.
-  EnableVsync(false);
-  std::this_thread::sleep_for(100ms);
   EnableVsync(true);
-  std::this_thread::sleep_for(100ms);
 
   // TODO(skiazyk): We need to do something about accessing this directly,
   // supposedly there is a backlight service on the way.
@@ -246,21 +253,19 @@
 
 void HardwareComposer::OnPostThreadPaused() {
   retire_fence_fds_.clear();
-  display_surfaces_.clear();
+  layers_.clear();
 
-  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
-    layers_[i].Reset();
-  }
-  active_layer_count_ = 0;
-
-  if (pose_client_) {
-    dvrPoseDestroy(pose_client_);
-    pose_client_ = nullptr;
+  if (composer_) {
+    EnableVsync(false);
   }
 
-  EnableVsync(false);
-
-  hwc2_hidl_->resetCommands();
+  if (!is_standalone_device_) {
+    composer_callback_ = nullptr;
+    composer_.reset(nullptr);
+    Layer::SetComposer(nullptr);
+  } else {
+    SetPowerMode(false);
+  }
 
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "idle");
@@ -270,29 +275,35 @@
   uint32_t num_types;
   uint32_t num_requests;
   HWC::Error error =
-      hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+      composer_->validateDisplay(display, &num_types, &num_requests);
 
   if (error == HWC2_ERROR_HAS_CHANGES) {
     // TODO(skiazyk): We might need to inspect the requested changes first, but
     // so far it seems like we shouldn't ever hit a bad state.
     // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
     //                                               display);
-    error = hwc2_hidl_->acceptDisplayChanges(display);
+    error = composer_->acceptDisplayChanges(display);
   }
 
   return error;
 }
 
-int32_t HardwareComposer::EnableVsync(bool enabled) {
-  return (int32_t)hwc2_hidl_->setVsyncEnabled(
+HWC::Error HardwareComposer::EnableVsync(bool enabled) {
+  return composer_->setVsyncEnabled(
       HWC_DISPLAY_PRIMARY,
       (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
                                              : HWC2_VSYNC_DISABLE));
 }
 
+HWC::Error HardwareComposer::SetPowerMode(bool active) {
+  HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
+  return composer_->setPowerMode(
+      HWC_DISPLAY_PRIMARY, power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+}
+
 HWC::Error HardwareComposer::Present(hwc2_display_t display) {
   int32_t present_fence;
-  HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
+  HWC::Error error = composer_->presentDisplay(display, &present_fence);
 
   // According to the documentation, this fence is signaled at the time of
   // vsync/DMA for physical displays.
@@ -306,20 +317,21 @@
   return error;
 }
 
-HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer,
+                                                 hwc2_display_t display,
                                                  hwc2_config_t config,
                                                  hwc2_attribute_t attribute,
                                                  int32_t* out_value) const {
-  return hwc2_hidl_->getDisplayAttribute(
+  return composer->getDisplayAttribute(
       display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
 }
 
 HWC::Error HardwareComposer::GetDisplayMetrics(
-    hwc2_display_t display, hwc2_config_t config,
+    Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config,
     HWCDisplayMetrics* out_metrics) const {
   HWC::Error error;
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+  error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH,
                               &out_metrics->width);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -328,7 +340,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+  error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT,
                               &out_metrics->height);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -337,7 +349,8 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+  error = GetDisplayAttribute(composer, display, config,
+                              HWC2_ATTRIBUTE_VSYNC_PERIOD,
                               &out_metrics->vsync_period_ns);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -346,7 +359,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+  error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X,
                               &out_metrics->dpi.x);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -355,7 +368,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+  error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y,
                               &out_metrics->dpi.y);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -367,14 +380,43 @@
   return HWC::Error::None;
 }
 
-std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
+std::string HardwareComposer::Dump() {
+  std::unique_lock<std::mutex> lock(post_thread_mutex_);
+  std::ostringstream stream;
+
+  stream << "Display metrics:     " << display_metrics_.width << "x"
+         << display_metrics_.height << " " << (display_metrics_.dpi.x / 1000.0)
+         << "x" << (display_metrics_.dpi.y / 1000.0) << " dpi @ "
+         << (1000000000.0 / display_metrics_.vsync_period_ns) << " Hz"
+         << std::endl;
+
+  stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
+  stream << "Active layers:       " << layers_.size() << std::endl;
+  stream << std::endl;
+
+  for (size_t i = 0; i < layers_.size(); i++) {
+    stream << "Layer " << i << ":";
+    stream << " type=" << layers_[i].GetCompositionType().to_string();
+    stream << " surface_id=" << layers_[i].GetSurfaceId();
+    stream << " buffer_id=" << layers_[i].GetBufferId();
+    stream << std::endl;
+  }
+  stream << std::endl;
+
+  if (post_thread_resumed_) {
+    stream << "Hardware Composer Debug Info:" << std::endl;
+    stream << composer_->dumpDebugInfo();
+  }
+
+  return stream.str();
+}
 
 void HardwareComposer::PostLayers() {
   ATRACE_NAME("HardwareComposer::PostLayers");
 
   // Setup the hardware composer layers with current buffers.
-  for (size_t i = 0; i < active_layer_count_; i++) {
-    layers_[i].Prepare();
+  for (auto& layer : layers_) {
+    layer.Prepare();
   }
 
   HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
@@ -396,20 +438,18 @@
     retire_fence_fds_.erase(retire_fence_fds_.begin());
   }
 
-  const bool is_frame_pending = IsFramePendingInDriver();
-  const bool is_fence_pending =
-      retire_fence_fds_.size() > kAllowedPendingFenceCount;
+  const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
+                                post_thread_config_.allowed_pending_fence_count;
 
-  if (is_fence_pending || is_frame_pending) {
+  if (is_fence_pending) {
     ATRACE_INT("frame_skip_count", ++frame_skip_count_);
 
-    ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
     ALOGW_IF(is_fence_pending,
              "Warning: dropping a frame to catch up with HWC (pending = %zd)",
              retire_fence_fds_.size());
 
-    for (size_t i = 0; i < active_layer_count_; i++) {
-      layers_[i].Drop();
+    for (auto& layer : layers_) {
+      layer.Drop();
     }
     return;
   } else {
@@ -418,10 +458,12 @@
     ATRACE_INT("frame_skip_count", 0);
   }
 
-#if TRACE
-  for (size_t i = 0; i < active_layer_count_; i++)
-    ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
+#if TRACE > 1
+  for (size_t i = 0; i < layers_.size(); i++) {
+    ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
+          i, layers_[i].GetBufferId(),
           layers_[i].GetCompositionType().to_string().c_str());
+  }
 #endif
 
   error = Present(HWC_DISPLAY_PRIMARY);
@@ -433,18 +475,18 @@
 
   std::vector<Hwc2::Layer> out_layers;
   std::vector<int> out_fences;
-  error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
-                                       &out_fences);
+  error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+                                      &out_fences);
   ALOGE_IF(error != HWC::Error::None,
            "HardwareComposer::PostLayers: Failed to get release fences: %s",
            error.to_string().c_str());
 
-  // Perform post-frame bookkeeping. Unused layers are a no-op.
+  // Perform post-frame bookkeeping.
   uint32_t num_elements = out_layers.size();
   for (size_t i = 0; i < num_elements; ++i) {
-    for (size_t j = 0; j < active_layer_count_; ++j) {
-      if (layers_[j].GetLayerHandle() == out_layers[i]) {
-        layers_[j].Finish(out_fences[i]);
+    for (auto& layer : layers_) {
+      if (layer.GetLayerHandle() == out_layers[i]) {
+        layer.Finish(out_fences[i]);
       }
     }
   }
@@ -460,23 +502,80 @@
     pending_surfaces_ = std::move(surfaces);
   }
 
+  if (request_display_callback_ && (!is_standalone_device_ || !composer_))
+    request_display_callback_(!display_idle);
+
   // Set idle state based on whether there are any surfaces to handle.
   UpdatePostThreadState(PostThreadState::Idle, display_idle);
+}
 
-  // XXX: TEMPORARY
-  // Request control of the display based on whether there are any surfaces to
-  // handle. This callback sets the post thread active state once the transition
-  // is complete in SurfaceFlinger.
-  // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
-  // mode. Currently this is hooked up to persistent VR mode, but perhaps this
-  // makes more sense to control it from VrCore, which could in turn base its
-  // decision on persistent VR mode.
-  if (request_display_callback_)
-    request_display_callback_(!display_idle);
+int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
+                                        IonBuffer& ion_buffer) {
+  if (key == DvrGlobalBuffers::kVsyncBuffer) {
+    vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
+        &ion_buffer, CPUUsageMode::WRITE_OFTEN);
+
+    if (vsync_ring_->IsMapped() == false) {
+      return -EPERM;
+    }
+  }
+
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
+    return MapConfigBuffer(ion_buffer);
+  }
+
+  return 0;
+}
+
+void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
+    ConfigBufferDeleted();
+  }
+}
+
+int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  shared_config_ring_ = DvrConfigRing();
+
+  if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
+    ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
+    return -EINVAL;
+  }
+
+  void* buffer_base = 0;
+  int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
+                               ion_buffer.height(), &buffer_base);
+  if (result != 0) {
+    ALOGE(
+        "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
+        "buffer.");
+    return -EPERM;
+  }
+
+  shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
+  ion_buffer.Unlock();
+
+  return 0;
+}
+
+void HardwareComposer::ConfigBufferDeleted() {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  shared_config_ring_ = DvrConfigRing();
+}
+
+void HardwareComposer::UpdateConfigBuffer() {
+  std::lock_guard<std::mutex> lock(shared_config_mutex_);
+  if (!shared_config_ring_.is_valid())
+    return;
+  // Copy from latest record in shared_config_ring_ to local copy.
+  DvrConfig record;
+  if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
+    post_thread_config_ = record;
+  }
 }
 
 int HardwareComposer::PostThreadPollInterruptible(
-    const pdx::LocalHandle& event_fd, int requested_events) {
+    const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
   pollfd pfd[2] = {
       {
           .fd = event_fd.Get(),
@@ -491,7 +590,7 @@
   };
   int ret, error;
   do {
-    ret = poll(pfd, 2, -1);
+    ret = poll(pfd, 2, timeout_ms);
     error = errno;
     ALOGW_IF(ret < 0,
              "HardwareComposer::PostThreadPollInterruptible: Error during "
@@ -501,167 +600,40 @@
 
   if (ret < 0) {
     return -error;
+  } else if (ret == 0) {
+    return -ETIMEDOUT;
   } else if (pfd[0].revents != 0) {
     return 0;
   } else if (pfd[1].revents != 0) {
-    ALOGI("VrHwcPost thread interrupted");
+    ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents);
     return kPostThreadInterrupted;
   } else {
     return 0;
   }
 }
 
-// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
-// (the value of the state) on success or a negative error otherwise.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadWaitPPState() {
-  // Gracefully handle when the kernel does not support this feature.
-  if (!primary_display_wait_pp_fd_)
-    return 0;
-
-  const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
-  int ret, error;
-
-  ret = lseek(wait_pp_fd, 0, SEEK_SET);
-  if (ret < 0) {
-    error = errno;
-    ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
-          strerror(error));
-    return -error;
-  }
-
-  char data = -1;
-  ret = read(wait_pp_fd, &data, sizeof(data));
-  if (ret < 0) {
-    error = errno;
-    ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
-          strerror(error));
-    return -error;
-  }
-
-  switch (data) {
-    case '0':
-      return 0;
-    case '1':
-      return 1;
-    default:
-      ALOGE(
-          "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
-          data);
-      return -EINVAL;
-  }
-}
-
-// Reads the timestamp of the last vsync from the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
-  const int event_fd = primary_display_vsync_event_fd_.Get();
-  int ret, error;
-
-  // The driver returns data in the form "VSYNC=<timestamp ns>".
-  std::array<char, 32> data;
-  data.fill('\0');
-
-  // Seek back to the beginning of the event file.
-  ret = lseek(event_fd, 0, SEEK_SET);
-  if (ret < 0) {
-    error = errno;
-    ALOGE(
-        "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  // Read the vsync event timestamp.
-  ret = read(event_fd, data.data(), data.size());
-  if (ret < 0) {
-    error = errno;
-    ALOGE_IF(
-        error != EAGAIN,
-        "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  ret = sscanf(data.data(), "VSYNC=%" PRIu64,
-               reinterpret_cast<uint64_t*>(timestamp));
-  if (ret < 0) {
-    error = errno;
-    ALOGE(
-        "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  return 0;
-}
-
-// Blocks until the next vsync event is signaled by the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::BlockUntilVSync() {
-  // Vsync is signaled by POLLPRI on the fb vsync node.
-  return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
+Status<int64_t> HardwareComposer::GetVSyncTime() {
+  auto status = composer_callback_->GetVsyncTime(HWC_DISPLAY_PRIMARY);
+  ALOGE_IF(!status,
+           "HardwareComposer::GetVSyncTime: Failed to get vsync timestamp: %s",
+           status.GetErrorMessage().c_str());
+  return status;
 }
 
 // Waits for the next vsync and returns the timestamp of the vsync event. If
 // vsync already passed since the last call, returns the latest vsync timestamp
-// instead of blocking. This method updates the last_vsync_timeout_ in the
-// process.
-//
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::WaitForVSync(int64_t* timestamp) {
-  int error;
-
-  // Get the current timestamp and decide what to do.
-  while (true) {
-    int64_t current_vsync_timestamp;
-    error = ReadVSyncTimestamp(&current_vsync_timestamp);
-    if (error < 0 && error != -EAGAIN)
-      return error;
-
-    if (error == -EAGAIN) {
-      // Vsync was turned off, wait for the next vsync event.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-
-      // Try again to get the timestamp for this new vsync interval.
-      continue;
-    }
-
-    // Check that we advanced to a later vsync interval.
-    if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
-      *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
-      return 0;
-    }
-
-    // See how close we are to the next expected vsync. If we're within 1ms,
-    // sleep for 1ms and try again.
-    const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
-    const int64_t threshold_ns = 1000000;  // 1ms
-
-    const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
-    const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
-
-    if (distance_to_vsync_est > threshold_ns) {
-      // Wait for vsync event notification.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-    } else {
-      // Sleep for a short time (1 millisecond) before retrying.
-      error = SleepUntil(GetSystemClockNs() + threshold_ns);
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-    }
+// instead of blocking.
+Status<int64_t> HardwareComposer::WaitForVSync() {
+  const int64_t predicted_vsync_time =
+      last_vsync_timestamp_ +
+      display_metrics_.vsync_period_ns * vsync_prediction_interval_;
+  const int error = SleepUntil(predicted_vsync_time);
+  if (error < 0) {
+    ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
+          strerror(-error));
+    return error;
   }
+  return {predicted_vsync_time};
 }
 
 int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
@@ -679,7 +651,8 @@
     return -error;
   }
 
-  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
+  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
+                                     /*timeout_ms*/ -1);
 }
 
 void HardwareComposer::PostThread() {
@@ -702,24 +675,6 @@
            strerror(errno));
 #endif  // ENABLE_BACKLIGHT_BRIGHTNESS
 
-  // Open the vsync event node for the primary display.
-  // TODO(eieio): Move this into a platform-specific class.
-  primary_display_vsync_event_fd_ =
-      LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
-  ALOGE_IF(!primary_display_vsync_event_fd_,
-           "HardwareComposer: Failed to open vsync event node for primary "
-           "display: %s",
-           strerror(errno));
-
-  // Open the wait pingpong status node for the primary display.
-  // TODO(eieio): Move this into a platform-specific class.
-  primary_display_wait_pp_fd_ =
-      LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
-  ALOGW_IF(
-      !primary_display_wait_pp_fd_,
-      "HardwareComposer: Failed to open wait_pp node for primary display: %s",
-      strerror(errno));
-
   // Create a timerfd based on CLOCK_MONOTINIC.
   vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
   LOG_ALWAYS_FATAL_IF(
@@ -744,12 +699,16 @@
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
+    // Check for updated config once per vsync.
+    UpdateConfigBuffer();
+
     while (post_thread_quiescent_) {
       std::unique_lock<std::mutex> lock(post_thread_mutex_);
       ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
 
-      // Tear down resources.
-      OnPostThreadPaused();
+      // Tear down resources if necessary.
+      if (was_running)
+        OnPostThreadPaused();
 
       was_running = false;
       post_thread_resumed_ = false;
@@ -780,37 +739,56 @@
         thread_policy_setup =
             SetThreadPolicy("graphics:high", "/system/performance");
       }
+
+      // Initialize the last vsync timestamp with the current time. The
+      // predictor below uses this time + the vsync interval in absolute time
+      // units for the initial delay. Once the driver starts reporting vsync the
+      // predictor will sync up with the real vsync.
+      last_vsync_timestamp_ = GetSystemClockNs();
     }
 
     int64_t vsync_timestamp = 0;
     {
-      std::array<char, 128> buf;
-      snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
-               vsync_count_ + 1);
-      ATRACE_NAME(buf.data());
+      TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64
+                   ";prediction_interval=%d|",
+                   vsync_count_ + 1, last_vsync_timestamp_,
+                   vsync_prediction_interval_);
 
-      const int error = WaitForVSync(&vsync_timestamp);
+      auto status = WaitForVSync();
       ALOGE_IF(
-          error < 0,
+          !status,
           "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
-          strerror(-error));
-      // Don't bother processing this frame if a pause was requested
-      if (error == kPostThreadInterrupted)
+          status.GetErrorMessage().c_str());
+
+      // If there was an error either sleeping was interrupted due to pausing or
+      // there was an error getting the latest timestamp.
+      if (!status)
         continue;
+
+      // Predicted vsync timestamp for this interval. This is stable because we
+      // use absolute time for the wakeup timer.
+      vsync_timestamp = status.get();
     }
 
-    ++vsync_count_;
-
-    if (pose_client_) {
-      // Signal the pose service with vsync info.
-      // Display timestamp is in the middle of scanout.
-      privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
-                                vsync_timestamp + photon_offset_ns,
-                                ns_per_frame, right_eye_photon_offset_ns);
-    }
+    // Advance the vsync counter only if the system is keeping up with hardware
+    // vsync to give clients an indication of the delays.
+    if (vsync_prediction_interval_ == 1)
+      ++vsync_count_;
 
     const bool layer_config_changed = UpdateLayerConfig();
 
+    // Publish the vsync event.
+    if (vsync_ring_) {
+      DvrVsync vsync;
+      vsync.vsync_count = vsync_count_;
+      vsync.vsync_timestamp_ns = vsync_timestamp;
+      vsync.vsync_left_eye_offset_ns = photon_offset_ns;
+      vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
+      vsync.vsync_period_ns = ns_per_frame;
+
+      vsync_ring_->Publish(vsync);
+    }
+
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
@@ -823,9 +801,10 @@
 
       const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
       const int64_t now_ns = GetSystemClockNs();
-      const int64_t sleep_time_ns =
-          display_time_est_ns - now_ns - kFramePostOffsetNs;
-      const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
+      const int64_t sleep_time_ns = display_time_est_ns - now_ns -
+                                    post_thread_config_.frame_post_offset_ns;
+      const int64_t wakeup_time_ns =
+          display_time_est_ns - post_thread_config_.frame_post_offset_ns;
 
       ATRACE_INT64("sleep_time_ns", sleep_time_ns);
       if (sleep_time_ns > 0) {
@@ -844,6 +823,38 @@
       }
     }
 
+    {
+      auto status = GetVSyncTime();
+      if (!status) {
+        ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s",
+              status.GetErrorMessage().c_str());
+      }
+
+      // If we failed to read vsync there might be a problem with the driver.
+      // Since there's nothing we can do just behave as though we didn't get an
+      // updated vsync time and let the prediction continue.
+      const int64_t current_vsync_timestamp =
+          status ? status.get() : last_vsync_timestamp_;
+
+      const bool vsync_delayed =
+          last_vsync_timestamp_ == current_vsync_timestamp;
+      ATRACE_INT("vsync_delayed", vsync_delayed);
+
+      // If vsync was delayed advance the prediction interval and allow the
+      // fence logic in PostLayers() to skip the frame.
+      if (vsync_delayed) {
+        ALOGW(
+            "HardwareComposer::PostThread: VSYNC timestamp did not advance "
+            "since last frame: timestamp=%" PRId64 " prediction_interval=%d",
+            current_vsync_timestamp, vsync_prediction_interval_);
+        vsync_prediction_interval_++;
+      } else {
+        // We have an updated vsync timestamp, reset the prediction interval.
+        last_vsync_timestamp_ = current_vsync_timestamp;
+        vsync_prediction_interval_ = 1;
+      }
+    }
+
     PostLayers();
   }
 }
@@ -862,37 +873,60 @@
 
   ATRACE_NAME("UpdateLayerConfig_HwLayers");
 
-  display_surfaces_.clear();
+  // Sort the new direct surface list by z-order to determine the relative order
+  // of the surfaces. This relative order is used for the HWC z-order value to
+  // insulate VrFlinger and HWC z-order semantics from each other.
+  std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
+    return a->z_order() < b->z_order();
+  });
 
-  Layer* target_layer;
-  size_t layer_index;
-  for (layer_index = 0;
-       layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
-       layer_index++) {
+  // Prepare a new layer stack, pulling in layers from the previous
+  // layer stack that are still active and updating their attributes.
+  std::vector<Layer> layers;
+  size_t layer_index = 0;
+  for (const auto& surface : surfaces) {
     // The bottom layer is opaque, other layers blend.
     HWC::BlendMode blending =
         layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
-    layers_[layer_index].Setup(surfaces[layer_index], blending,
-                               display_transform_, HWC::Composition::Device,
-                               layer_index);
-    display_surfaces_.push_back(surfaces[layer_index]);
+
+    // Try to find a layer for this surface in the set of active layers.
+    auto search =
+        std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
+    const bool found = search != layers_.end() &&
+                       search->GetSurfaceId() == surface->surface_id();
+    if (found) {
+      // Update the attributes of the layer that may have changed.
+      search->SetBlending(blending);
+      search->SetZOrder(layer_index);  // Relative z-order.
+
+      // Move the existing layer to the new layer set and remove the empty layer
+      // object from the current set.
+      layers.push_back(std::move(*search));
+      layers_.erase(search);
+    } else {
+      // Insert a layer for the new surface.
+      layers.emplace_back(surface, blending, display_transform_,
+                          HWC::Composition::Device, layer_index);
+    }
+
+    ALOGI_IF(
+        TRACE,
+        "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
+        layer_index, layers[layer_index].GetSurfaceId());
+
+    layer_index++;
   }
 
-  // Clear unused layers.
-  for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
-    layers_[i].Reset();
+  // Sort the new layer stack by ascending surface id.
+  std::sort(layers.begin(), layers.end());
 
-  active_layer_count_ = layer_index;
+  // Replace the previous layer set with the new layer set. The destructor of
+  // the previous set will clean up the remaining Layers that are not moved to
+  // the new layer set.
+  layers_ = std::move(layers);
+
   ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
-           active_layer_count_);
-
-  // Any surfaces left over could not be assigned a hardware layer and will
-  // not be displayed.
-  ALOGW_IF(surfaces.size() != display_surfaces_.size(),
-           "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
-           "pending_surfaces=%zu display_surfaces=%zu",
-           surfaces.size(), display_surfaces_.size());
-
+           layers_.size());
   return true;
 }
 
@@ -900,30 +934,6 @@
   vsync_callback_ = callback;
 }
 
-void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
-                                  hwc2_display_t /*display*/) {
-  // TODO(eieio): implement invalidate callbacks.
-}
-
-void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
-                                hwc2_display_t /*display*/,
-                                int64_t /*timestamp*/) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-  // Intentionally empty. HWC may require a callback to be set to enable vsync
-  // signals. We bypass this callback thread by monitoring the vsync event
-  // directly, but signals still need to be enabled.
-}
-
-void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
-                                  hwc2_display_t /*display*/,
-                                  hwc2_connection_t /*connected*/) {
-  // TODO(eieio): implement display hotplug callbacks.
-}
-
-void HardwareComposer::OnHardwareComposerRefresh() {
-  // TODO(steventhomas): Handle refresh.
-}
-
 void HardwareComposer::SetBacklightBrightness(int brightness) {
   if (backlight_brightness_fd_) {
     std::array<char, 32> text;
@@ -932,15 +942,121 @@
   }
 }
 
-void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
-                              const HWCDisplayMetrics* metrics) {
-  hwc2_hidl_ = hwc2_hidl;
-  display_metrics_ = metrics;
+Return<void> HardwareComposer::ComposerCallback::onHotplug(
+    Hwc2::Display display, IComposerCallback::Connection /*conn*/) {
+  // See if the driver supports the vsync_event node in sysfs.
+  if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES &&
+      !displays_[display].driver_vsync_event_fd) {
+    std::array<char, 1024> buffer;
+    snprintf(buffer.data(), buffer.size(),
+             "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
+    if (LocalHandle handle{buffer.data(), O_RDONLY}) {
+      ALOGI(
+          "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
+          "vsync_event node for display %" PRIu64,
+          display);
+      displays_[display].driver_vsync_event_fd = std::move(handle);
+    } else {
+      ALOGI(
+          "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
+          "support vsync_event node for display %" PRIu64,
+          display);
+    }
+  }
+
+  return Void();
 }
 
+Return<void> HardwareComposer::ComposerCallback::onRefresh(
+    Hwc2::Display /*display*/) {
+  return hardware::Void();
+}
+
+Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
+                                                         int64_t timestamp) {
+  TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
+               display, timestamp);
+  if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    displays_[display].callback_vsync_timestamp = timestamp;
+  } else {
+    ALOGW(
+        "HardwareComposer::ComposerCallback::onVsync: Received vsync on "
+        "non-physical display: display=%" PRId64,
+        display);
+  }
+  return Void();
+}
+
+Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
+    Hwc2::Display display) {
+  if (display >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+    ALOGE(
+        "HardwareComposer::ComposerCallback::GetVsyncTime: Invalid physical "
+        "display requested: display=%" PRIu64,
+        display);
+    return ErrorStatus(EINVAL);
+  }
+
+  // See if the driver supports direct vsync events.
+  LocalHandle& event_fd = displays_[display].driver_vsync_event_fd;
+  if (!event_fd) {
+    // Fall back to returning the last timestamp returned by the vsync
+    // callback.
+    std::lock_guard<std::mutex> autolock(vsync_mutex_);
+    return displays_[display].callback_vsync_timestamp;
+  }
+
+  // When the driver supports the vsync_event sysfs node we can use it to
+  // determine the latest vsync timestamp, even if the HWC callback has been
+  // delayed.
+
+  // The driver returns data in the form "VSYNC=<timestamp ns>".
+  std::array<char, 32> data;
+  data.fill('\0');
+
+  // Seek back to the beginning of the event file.
+  int ret = lseek(event_fd.Get(), 0, SEEK_SET);
+  if (ret < 0) {
+    const int error = errno;
+    ALOGE(
+        "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek "
+        "vsync event fd: %s",
+        strerror(error));
+    return ErrorStatus(error);
+  }
+
+  // Read the vsync event timestamp.
+  ret = read(event_fd.Get(), data.data(), data.size());
+  if (ret < 0) {
+    const int error = errno;
+    ALOGE_IF(error != EAGAIN,
+             "HardwareComposer::ComposerCallback::GetVsyncTime: Error "
+             "while reading timestamp: %s",
+             strerror(error));
+    return ErrorStatus(error);
+  }
+
+  int64_t timestamp;
+  ret = sscanf(data.data(), "VSYNC=%" PRIu64,
+               reinterpret_cast<uint64_t*>(&timestamp));
+  if (ret < 0) {
+    const int error = errno;
+    ALOGE(
+        "HardwareComposer::ComposerCallback::GetVsyncTime: Error while "
+        "parsing timestamp: %s",
+        strerror(error));
+    return ErrorStatus(error);
+  }
+
+  return {timestamp};
+}
+
+Hwc2::Composer* Layer::composer_{nullptr};
+HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
+
 void Layer::Reset() {
-  if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
-    hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+  if (hardware_composer_layer_) {
+    composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
     hardware_composer_layer_ = 0;
   }
 
@@ -952,41 +1068,74 @@
   source_ = EmptyVariant{};
   acquire_fence_.Close();
   surface_rect_functions_applied_ = false;
+  pending_visibility_settings_ = true;
+  cached_buffer_map_.clear();
 }
 
-void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
-                  HWC::BlendMode blending, HWC::Transform transform,
-                  HWC::Composition composition_type, size_t z_order) {
-  Reset();
-  z_order_ = z_order;
-  blending_ = blending;
-  transform_ = transform;
-  composition_type_ = HWC::Composition::Invalid;
-  target_composition_type_ = composition_type;
-  source_ = SourceSurface{surface};
+Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+             HWC::BlendMode blending, HWC::Transform transform,
+             HWC::Composition composition_type, size_t z_order)
+    : z_order_{z_order},
+      blending_{blending},
+      transform_{transform},
+      target_composition_type_{composition_type},
+      source_{SourceSurface{surface}} {
   CommonLayerSetup();
 }
 
-void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
-                  HWC::BlendMode blending, HWC::Transform transform,
-                  HWC::Composition composition_type, size_t z_order) {
-  Reset();
-  z_order_ = z_order;
-  blending_ = blending;
-  transform_ = transform;
-  composition_type_ = HWC::Composition::Invalid;
-  target_composition_type_ = composition_type;
-  source_ = SourceBuffer{buffer};
+Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+             HWC::Transform transform, HWC::Composition composition_type,
+             size_t z_order)
+    : z_order_{z_order},
+      blending_{blending},
+      transform_{transform},
+      target_composition_type_{composition_type},
+      source_{SourceBuffer{buffer}} {
   CommonLayerSetup();
 }
 
+Layer::~Layer() { Reset(); }
+
+Layer::Layer(Layer&& other) { *this = std::move(other); }
+
+Layer& Layer::operator=(Layer&& other) {
+  if (this != &other) {
+    Reset();
+    using std::swap;
+    swap(hardware_composer_layer_, other.hardware_composer_layer_);
+    swap(z_order_, other.z_order_);
+    swap(blending_, other.blending_);
+    swap(transform_, other.transform_);
+    swap(composition_type_, other.composition_type_);
+    swap(target_composition_type_, other.target_composition_type_);
+    swap(source_, other.source_);
+    swap(acquire_fence_, other.acquire_fence_);
+    swap(surface_rect_functions_applied_,
+         other.surface_rect_functions_applied_);
+    swap(pending_visibility_settings_, other.pending_visibility_settings_);
+    swap(cached_buffer_map_, other.cached_buffer_map_);
+  }
+  return *this;
+}
+
 void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
   if (source_.is<SourceBuffer>())
     std::get<SourceBuffer>(source_) = {buffer};
 }
 
-void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
-void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
+void Layer::SetBlending(HWC::BlendMode blending) {
+  if (blending_ != blending) {
+    blending_ = blending;
+    pending_visibility_settings_ = true;
+  }
+}
+
+void Layer::SetZOrder(size_t z_order) {
+  if (z_order_ != z_order) {
+    z_order_ = z_order;
+    pending_visibility_settings_ = true;
+  }
+}
 
 IonBuffer* Layer::GetBuffer() {
   struct Visitor {
@@ -997,93 +1146,108 @@
   return source_.Visit(Visitor{});
 }
 
-void Layer::UpdateLayerSettings() {
-  if (!IsLayerSetup()) {
-    ALOGE(
-        "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
-        "unused Layer!");
-    return;
-  }
+void Layer::UpdateVisibilitySettings() {
+  if (pending_visibility_settings_) {
+    pending_visibility_settings_ = false;
 
+    HWC::Error error;
+    hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+
+    error = composer_->setLayerBlendMode(
+        display, hardware_composer_layer_,
+        blending_.cast<Hwc2::IComposerClient::BlendMode>());
+    ALOGE_IF(error != HWC::Error::None,
+             "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+             error.to_string().c_str());
+
+    error =
+        composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+    ALOGE_IF(error != HWC::Error::None,
+             "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+             error.to_string().c_str());
+  }
+}
+
+void Layer::UpdateLayerSettings() {
   HWC::Error error;
   hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
-  error = hwc2_hidl_->setLayerCompositionType(
-      display, hardware_composer_layer_,
-      composition_type_.cast<Hwc2::IComposerClient::Composition>());
-  ALOGE_IF(
-      error != HWC::Error::None,
-      "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
-      error.to_string().c_str());
-
-  error = hwc2_hidl_->setLayerBlendMode(
-      display, hardware_composer_layer_,
-      blending_.cast<Hwc2::IComposerClient::BlendMode>());
-  ALOGE_IF(error != HWC::Error::None,
-           "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
-           error.to_string().c_str());
+  UpdateVisibilitySettings();
 
   // TODO(eieio): Use surface attributes or some other mechanism to control
   // the layer display frame.
-  error = hwc2_hidl_->setLayerDisplayFrame(
+  error = composer_->setLayerDisplayFrame(
       display, hardware_composer_layer_,
-      {0, 0, display_metrics_->width, display_metrics_->height});
+      {0, 0, display_metrics_.width, display_metrics_.height});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
            error.to_string().c_str());
 
-  error = hwc2_hidl_->setLayerVisibleRegion(
+  error = composer_->setLayerVisibleRegion(
       display, hardware_composer_layer_,
-      {{0, 0, display_metrics_->width, display_metrics_->height}});
+      {{0, 0, display_metrics_.width, display_metrics_.height}});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
            error.to_string().c_str());
 
   error =
-      hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+      composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
            error.to_string().c_str());
-
-  error =
-      hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
-  ALOGE_IF(error != HWC::Error::None,
-           "Layer::UpdateLayerSettings: Error setting z_ order: %s",
-           error.to_string().c_str());
 }
 
 void Layer::CommonLayerSetup() {
   HWC::Error error =
-      hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
-  ALOGE_IF(
-      error != HWC::Error::None,
-      "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
-      error.to_string().c_str());
+      composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::CommonLayerSetup: Failed to create layer on primary "
+           "display: %s",
+           error.to_string().c_str());
   UpdateLayerSettings();
 }
 
+bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) {
+  auto search = cached_buffer_map_.find(slot);
+  if (search != cached_buffer_map_.end() && search->second == buffer_id)
+    return true;
+
+  // Assign or update the buffer slot.
+  if (buffer_id >= 0)
+    cached_buffer_map_[slot] = buffer_id;
+  return false;
+}
+
 void Layer::Prepare() {
-  int right, bottom;
+  int right, bottom, id;
   sp<GraphicBuffer> handle;
+  std::size_t slot;
 
   // Acquire the next buffer according to the type of source.
   IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
-    std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
+    std::tie(right, bottom, id, handle, acquire_fence_, slot) =
+        source.Acquire();
   });
 
-  // When a layer is first setup there may be some time before the first buffer
-  // arrives. Setup the HWC layer as a solid color to stall for time until the
-  // first buffer arrives. Once the first buffer arrives there will always be a
-  // buffer for the frame even if it is old.
+  TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot);
+
+  // Update any visibility (blending, z-order) changes that occurred since
+  // last prepare.
+  UpdateVisibilitySettings();
+
+  // When a layer is first setup there may be some time before the first
+  // buffer arrives. Setup the HWC layer as a solid color to stall for time
+  // until the first buffer arrives. Once the first buffer arrives there will
+  // always be a buffer for the frame even if it is old.
   if (!handle.get()) {
     if (composition_type_ == HWC::Composition::Invalid) {
       composition_type_ = HWC::Composition::SolidColor;
-      hwc2_hidl_->setLayerCompositionType(
+      composer_->setLayerCompositionType(
           HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
       Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
-      hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-                                layer_color);
+      composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+                               layer_color);
     } else {
       // The composition type is already set. Nothing else to do until a
       // buffer arrives.
@@ -1091,15 +1255,20 @@
   } else {
     if (composition_type_ != target_composition_type_) {
       composition_type_ = target_composition_type_;
-      hwc2_hidl_->setLayerCompositionType(
+      composer_->setLayerCompositionType(
           HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
     }
 
+    // See if the HWC cache already has this buffer.
+    const bool cached = CheckAndUpdateCachedBuffer(slot, id);
+    if (cached)
+      handle = nullptr;
+
     HWC::Error error{HWC::Error::None};
-    error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
-                                       hardware_composer_layer_, 0, handle,
-                                       acquire_fence_.Get());
+    error =
+        composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+                                  slot, handle, acquire_fence_.Get());
 
     ALOGE_IF(error != HWC::Error::None,
              "Layer::Prepare: Error setting layer buffer: %s",
@@ -1108,9 +1277,9 @@
     if (!surface_rect_functions_applied_) {
       const float float_right = right;
       const float float_bottom = bottom;
-      error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
-                                             hardware_composer_layer_,
-                                             {0, 0, float_right, float_bottom});
+      error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+                                            hardware_composer_layer_,
+                                            {0, 0, float_right, float_bottom});
 
       ALOGE_IF(error != HWC::Error::None,
                "Layer::Prepare: Error setting layer source crop: %s",
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 8ba72ab..7010db9 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -5,6 +5,7 @@
 #include "DisplayHardware/ComposerHal.h"
 #include "hwc_types.h"
 
+#include <dvr/dvr_shared_buffers.h>
 #include <hardware/gralloc.h>
 #include <log/log.h>
 
@@ -16,10 +17,12 @@
 #include <tuple>
 #include <vector>
 
-#include <dvr/pose_client.h>
+#include <dvr/dvr_config.h>
+#include <dvr/dvr_vsync.h>
 #include <pdx/file_handle.h>
 #include <pdx/rpc/variant.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
 #include "acquired_buffer.h"
 #include "display_surface.h"
@@ -49,15 +52,7 @@
 // source supplying buffers for the layer's contents.
 class Layer {
  public:
-  Layer() {}
-
-  // Sets up the global state used by all Layer instances. This must be called
-  // before using any Layer methods.
-  static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
-                                const HWCDisplayMetrics* metrics);
-
-  // Releases any shared pointers and fence handles held by this instance.
-  void Reset();
+  Layer() = default;
 
   // Sets up the layer to use a display surface as its content source. The Layer
   // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
@@ -68,9 +63,9 @@
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
   // |index| is the index of this surface in the DirectDisplaySurface array.
-  void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
-             HWC::BlendMode blending, HWC::Transform transform,
-             HWC::Composition composition_type, size_t z_roder);
+  Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+        HWC::BlendMode blending, HWC::Transform transform,
+        HWC::Composition composition_type, size_t z_roder);
 
   // Sets up the layer to use a direct buffer as its content source. No special
   // handling of the buffer is performed; responsibility for updating or
@@ -80,9 +75,17 @@
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
-             HWC::Transform transform, HWC::Composition composition_type,
-             size_t z_order);
+  Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+        HWC::Transform transform, HWC::Composition composition_type,
+        size_t z_order);
+
+  Layer(Layer&&);
+  Layer& operator=(Layer&&);
+
+  ~Layer();
+
+  // Releases any shared pointers and fence handles held by this instance.
+  void Reset();
 
   // Layers that use a direct IonBuffer should call this each frame to update
   // which buffer will be used for the next PostLayers.
@@ -117,23 +120,65 @@
   HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
   bool IsLayerSetup() const { return !source_.empty(); }
 
-  // Applies all of the settings to this layer using the hwc functions
-  void UpdateLayerSettings();
-
   int GetSurfaceId() const {
     int surface_id = -1;
     pdx::rpc::IfAnyOf<SourceSurface>::Call(
         &source_, [&surface_id](const SourceSurface& surface_source) {
-          surface_id = surface_source.surface->surface_id();
+          surface_id = surface_source.GetSurfaceId();
         });
     return surface_id;
   }
 
+  int GetBufferId() const {
+    int buffer_id = -1;
+    pdx::rpc::IfAnyOf<SourceSurface>::Call(
+        &source_, [&buffer_id](const SourceSurface& surface_source) {
+          buffer_id = surface_source.GetBufferId();
+        });
+    return buffer_id;
+  }
+
+  // Compares Layers by surface id.
+  bool operator<(const Layer& other) const {
+    return GetSurfaceId() < other.GetSurfaceId();
+  }
+  bool operator<(int surface_id) const { return GetSurfaceId() < surface_id; }
+
+  // Sets the composer instance used by all Layer instances.
+  static void SetComposer(Hwc2::Composer* composer) { composer_ = composer; }
+
+  // Sets the display metrics used by all Layer instances.
+  static void SetDisplayMetrics(HWCDisplayMetrics display_metrics) {
+    display_metrics_ = display_metrics;
+  }
+
  private:
   void CommonLayerSetup();
 
-  static Hwc2::Composer* hwc2_hidl_;
-  static const HWCDisplayMetrics* display_metrics_;
+  // Applies all of the settings to this layer using the hwc functions
+  void UpdateLayerSettings();
+
+  // Applies visibility settings that may have changed.
+  void UpdateVisibilitySettings();
+
+  // Checks whether the buffer, given by id, is associated with the given slot
+  // in the HWC buffer cache. If the slot is not associated with the given
+  // buffer the cache is updated to establish the association and the buffer
+  // should be sent to HWC using setLayerBuffer. Returns true if the association
+  // was already established, false if not. A buffer_id of -1 is never
+  // associated and always returns false.
+  bool CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id);
+
+  // Composer instance shared by all instances of Layer. This must be set
+  // whenever a new instance of the Composer is created. This may be set to
+  // nullptr as long as there are no instances of Layer that might need to use
+  // it.
+  static Hwc2::Composer* composer_;
+
+  // Display metrics shared by all instances of Layer. This must be set at least
+  // once during VrFlinger initialization and is expected to remain constant
+  // thereafter.
+  static HWCDisplayMetrics display_metrics_;
 
   // The hardware composer layer and metrics to use during the prepare cycle.
   hwc2_layer_t hardware_composer_layer_ = 0;
@@ -161,19 +206,21 @@
     // the previous buffer is returned or an empty value if no buffer has ever
     // been posted. When a new buffer is acquired the previous buffer's release
     // fence is passed out automatically.
-    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+    std::tuple<int, int, int, sp<GraphicBuffer>, pdx::LocalHandle, std::size_t>
+    Acquire() {
       if (surface->IsBufferAvailable()) {
         acquired_buffer.Release(std::move(release_fence));
         acquired_buffer = surface->AcquireCurrentBuffer();
         ATRACE_ASYNC_END("BufferPost", acquired_buffer.buffer()->id());
       }
       if (!acquired_buffer.IsEmpty()) {
-        return std::make_tuple(acquired_buffer.buffer()->width(),
-                               acquired_buffer.buffer()->height(),
-                               acquired_buffer.buffer()->buffer()->buffer(),
-                               acquired_buffer.ClaimAcquireFence());
+        return std::make_tuple(
+            acquired_buffer.buffer()->width(),
+            acquired_buffer.buffer()->height(), acquired_buffer.buffer()->id(),
+            acquired_buffer.buffer()->buffer()->buffer(),
+            acquired_buffer.ClaimAcquireFence(), acquired_buffer.slot());
       } else {
-        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+        return std::make_tuple(0, 0, -1, nullptr, pdx::LocalHandle{}, 0);
       }
     }
 
@@ -189,7 +236,15 @@
     }
 
     // Returns the surface id of the surface.
-    int GetSurfaceId() { return surface->surface_id(); }
+    int GetSurfaceId() const { return surface->surface_id(); }
+
+    // Returns the buffer id for the current buffer.
+    int GetBufferId() const {
+      if (acquired_buffer.IsAvailable())
+        return acquired_buffer.buffer()->id();
+      else
+        return -1;
+    }
   };
 
   // State when the layer is connected to a buffer. Provides the same interface
@@ -197,12 +252,13 @@
   struct SourceBuffer {
     std::shared_ptr<IonBuffer> buffer;
 
-    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+    std::tuple<int, int, int, sp<GraphicBuffer>, pdx::LocalHandle, std::size_t>
+    Acquire() {
       if (buffer)
-        return std::make_tuple(buffer->width(), buffer->height(),
-                               buffer->buffer(), pdx::LocalHandle{});
+        return std::make_tuple(buffer->width(), buffer->height(), -1,
+                               buffer->buffer(), pdx::LocalHandle{}, 0);
       else
-        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+        return std::make_tuple(0, 0, -1, nullptr, pdx::LocalHandle{}, 0);
     }
 
     void Finish(pdx::LocalHandle /*fence*/) {}
@@ -210,6 +266,7 @@
     IonBuffer* GetBuffer() { return buffer.get(); }
 
     int GetSurfaceId() const { return -1; }
+    int GetBufferId() const { return -1; }
   };
 
   // The underlying hardware composer layer is supplied buffers either from a
@@ -218,6 +275,13 @@
 
   pdx::LocalHandle acquire_fence_;
   bool surface_rect_functions_applied_ = false;
+  bool pending_visibility_settings_ = true;
+
+  // Map of buffer slot assignments that have already been established with HWC:
+  // slot -> buffer_id. When this map contains a matching slot and buffer_id the
+  // buffer argument to setLayerBuffer may be nullptr to avoid the cost of
+  // importing a buffer HWC already knows about.
+  std::map<std::size_t, int> cached_buffer_map_;
 
   Layer(const Layer&) = delete;
   void operator=(const Layer&) = delete;
@@ -237,16 +301,11 @@
   using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
   using RequestDisplayCallback = std::function<void(bool)>;
 
-  // Since there is no universal way to query the number of hardware layers,
-  // just set it to 4 for now.
-  static constexpr size_t kMaxHardwareLayers = 4;
-
   HardwareComposer();
-  HardwareComposer(Hwc2::Composer* hidl,
-                   RequestDisplayCallback request_display_callback);
   ~HardwareComposer();
 
-  bool Initialize();
+  bool Initialize(Hwc2::Composer* composer,
+                  RequestDisplayCallback request_display_callback);
 
   bool IsInitialized() const { return initialized_; }
 
@@ -260,11 +319,6 @@
   // Get the HMD display metrics for the current display.
   display::Metrics GetHmdDisplayMetrics() const;
 
-  HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
-                                 hwc2_attribute_t attributes,
-                                 int32_t* out_value) const;
-  HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
-                               HWCDisplayMetrics* out_metrics) const;
   std::string Dump();
 
   void SetVSyncCallback(VSyncCallback callback);
@@ -284,34 +338,40 @@
   void SetDisplaySurfaces(
       std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces);
 
-  void OnHardwareComposerRefresh();
+  int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
+  void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
 
  private:
-  int32_t EnableVsync(bool enabled);
+  HWC::Error GetDisplayAttribute(Hwc2::Composer* composer,
+                                 hwc2_display_t display, hwc2_config_t config,
+                                 hwc2_attribute_t attributes,
+                                 int32_t* out_value) const;
+  HWC::Error GetDisplayMetrics(Hwc2::Composer* composer, hwc2_display_t display,
+                               hwc2_config_t config,
+                               HWCDisplayMetrics* out_metrics) const;
+
+  HWC::Error EnableVsync(bool enabled);
+  HWC::Error SetPowerMode(bool active);
 
   class ComposerCallback : public Hwc2::IComposerCallback {
    public:
-    ComposerCallback() {}
+    ComposerCallback() = default;
+    hardware::Return<void> onHotplug(Hwc2::Display display,
+                                     Connection conn) override;
+    hardware::Return<void> onRefresh(Hwc2::Display display) override;
+    hardware::Return<void> onVsync(Hwc2::Display display,
+                                   int64_t timestamp) override;
 
-    hardware::Return<void> onHotplug(Hwc2::Display /*display*/,
-                                     Connection /*connected*/) override {
-      // TODO(skiazyk): depending on how the server is implemented, we might
-      // have to set it up to synchronize with receiving this event, as it can
-      // potentially be a critical event for setting up state within the
-      // hwc2 module. That is, we (technically) should not call any other hwc
-      // methods until this method has been called after registering the
-      // callbacks.
-      return hardware::Void();
-    }
+    pdx::Status<int64_t> GetVsyncTime(Hwc2::Display display);
 
-    hardware::Return<void> onRefresh(Hwc2::Display /*display*/) override {
-      return hardware::Void();
-    }
+   private:
+    std::mutex vsync_mutex_;
 
-    hardware::Return<void> onVsync(Hwc2::Display /*display*/,
-                                   int64_t /*timestamp*/) override {
-      return hardware::Void();
-    }
+    struct Display {
+      pdx::LocalHandle driver_vsync_event_fd;
+      int64_t callback_vsync_timestamp{0};
+    };
+    std::array<Display, HWC_NUM_PHYSICAL_DISPLAY_TYPES> displays_;
   };
 
   HWC::Error Validate(hwc2_display_t display);
@@ -340,22 +400,21 @@
   void UpdatePostThreadState(uint32_t state, bool suspend);
 
   // Blocks until either event_fd becomes readable, or we're interrupted by a
-  // control thread. Any errors are returned as negative errno values. If we're
-  // interrupted, kPostThreadInterrupted will be returned.
+  // control thread, or timeout_ms is reached before any events occur. Any
+  // errors are returned as negative errno values, with -ETIMEDOUT returned in
+  // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
+  // returned.
   int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
-                                  int requested_events);
+                                  int requested_events, int timeout_ms);
 
-  // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
-  // on the post thread that can be interrupted by a control thread. If
-  // interrupted, these calls return kPostThreadInterrupted.
+  // WaitForVSync and SleepUntil are blocking calls made on the post thread that
+  // can be interrupted by a control thread. If interrupted, these calls return
+  // kPostThreadInterrupted.
   int ReadWaitPPState();
-  int BlockUntilVSync();
-  int ReadVSyncTimestamp(int64_t* timestamp);
-  int WaitForVSync(int64_t* timestamp);
+  pdx::Status<int64_t> WaitForVSync();
+  pdx::Status<int64_t> GetVSyncTime();
   int SleepUntil(int64_t wakeup_timestamp);
 
-  bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
-
   // Reconfigures the layer stack if the display surfaces changed since the last
   // frame. Called only from the post thread.
   bool UpdateLayerConfig();
@@ -365,13 +424,19 @@
   // Called on the post thread when the post thread is paused or quits.
   void OnPostThreadPaused();
 
-  bool initialized_;
+  // Map the given shared memory buffer to our broadcast ring to track updates
+  // to the config parameters.
+  int MapConfigBuffer(IonBuffer& ion_buffer);
+  void ConfigBufferDeleted();
+  // Poll for config udpates.
+  void UpdateConfigBuffer();
 
-  // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
-  // this pointer.
-  Hwc2::Composer* hwc2_hidl_;
+  bool initialized_;
+  bool is_standalone_device_;
+
+  std::unique_ptr<Hwc2::Composer> composer_;
+  sp<ComposerCallback> composer_callback_;
   RequestDisplayCallback request_display_callback_;
-  sp<ComposerCallback> callbacks_;
 
   // Display metrics of the physical display.
   HWCDisplayMetrics native_display_metrics_;
@@ -386,13 +451,9 @@
   // thread and read by the post thread.
   std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
 
-  // The surfaces displayed by the post thread. Used exclusively by the post
-  // thread.
-  std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
-
-  // Layer array for handling buffer flow into hardware composer layers.
-  std::array<Layer, kMaxHardwareLayers> layers_;
-  size_t active_layer_count_ = 0;
+  // Layer set for handling buffer flow into hardware composer layers. This
+  // vector must be sorted by surface_id in ascending order.
+  std::vector<Layer> layers_;
 
   // Handler to hook vsync events outside of this class.
   VSyncCallback vsync_callback_;
@@ -402,7 +463,8 @@
   std::thread post_thread_;
 
   // Post thread state machine and synchronization primitives.
-  PostThreadStateType post_thread_state_{PostThreadState::Idle};
+  PostThreadStateType post_thread_state_{PostThreadState::Idle |
+                                         PostThreadState::Suspended};
   std::atomic<bool> post_thread_quiescent_{true};
   bool post_thread_resumed_{false};
   pdx::LocalHandle post_thread_event_fd_;
@@ -413,18 +475,15 @@
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
 
-  // Primary display vsync event sysfs node.
-  pdx::LocalHandle primary_display_vsync_event_fd_;
-
-  // Primary display wait_pingpong state sysfs node.
-  pdx::LocalHandle primary_display_wait_pp_fd_;
-
   // VSync sleep timerfd.
   pdx::LocalHandle vsync_sleep_timer_fd_;
 
   // The timestamp of the last vsync.
   int64_t last_vsync_timestamp_ = 0;
 
+  // The number of vsync intervals to predict since the last vsync.
+  int vsync_prediction_interval_ = 1;
+
   // Vsync count since display on.
   uint32_t vsync_count_ = 0;
 
@@ -435,18 +494,18 @@
   // us to detect when the display driver begins queuing frames.
   std::vector<pdx::LocalHandle> retire_fence_fds_;
 
-  // Pose client for frame count notifications. Pose client predicts poses
-  // out to display frame boundaries, so we need to tell it about vsyncs.
-  DvrPose* pose_client_ = nullptr;
+  // If we are publishing vsync data, we will put it here.
+  std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
+
+  // Broadcast ring for receiving config data from the DisplayManager.
+  DvrConfigRing shared_config_ring_;
+  uint32_t shared_config_ring_sequence_{0};
+  // Config buffer for reading from the post thread.
+  DvrConfig post_thread_config_;
+  std::mutex shared_config_mutex_;
 
   static constexpr int kPostThreadInterrupted = 1;
 
-  static void HwcRefresh(hwc2_callback_data_t data, hwc2_display_t display);
-  static void HwcVSync(hwc2_callback_data_t data, hwc2_display_t display,
-                       int64_t timestamp);
-  static void HwcHotplug(hwc2_callback_data_t callbackData,
-                         hwc2_display_t display, hwc2_connection_t connected);
-
   HardwareComposer(const HardwareComposer&) = delete;
   void operator=(const HardwareComposer&) = delete;
 };
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index 145852e..33cbc84 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -4,7 +4,7 @@
 #include <thread>
 #include <memory>
 
-#include <pdx/default_transport/service_dispatcher.h>
+#include <pdx/service_dispatcher.h>
 #include <vr/vr_manager/vr_manager.h>
 
 namespace android {
@@ -29,8 +29,8 @@
   void GrantDisplayOwnership();
   void SeizeDisplayOwnership();
 
-  // Called on a binder thread.
-  void OnHardwareComposerRefresh();
+  // dump all vr flinger state.
+  std::string Dump();
 
  private:
   VrFlinger();
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index b2dc1d8..85dc586 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -18,8 +18,6 @@
 #include <sys/prctl.h>
 #include <sys/resource.h>
 
-#include <pdx/default_transport/service_dispatcher.h>
-
 #include <functional>
 
 #include "DisplayHardware/ComposerHal.h"
@@ -66,9 +64,6 @@
 
   ALOGI("Starting up VrFlinger...");
 
-  setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
-  set_sched_policy(0, SP_FOREGROUND);
-
   // We need to be able to create endpoints with full perms.
   umask(0000);
 
@@ -76,7 +71,7 @@
 
   request_display_callback_ = request_display_callback;
 
-  dispatcher_ = android::pdx::default_transport::ServiceDispatcher::Create();
+  dispatcher_ = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
 
   display_service_ =
@@ -102,6 +97,9 @@
     prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
     ALOGI("Entering message loop.");
 
+    setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
+    set_sched_policy(0, SP_FOREGROUND);
+
     int ret = dispatcher_->EnterDispatchLoop();
     if (ret < 0) {
       ALOGE("Dispatch loop exited because: %s\n", strerror(-ret));
@@ -135,8 +133,9 @@
   display_service_->SeizeDisplayOwnership();
 }
 
-void VrFlinger::OnHardwareComposerRefresh() {
-  display_service_->OnHardwareComposerRefresh();
+std::string VrFlinger::Dump() {
+  // TODO(karthikrs): Add more state information here.
+  return display_service_->DumpState(0/*unused*/);
 }
 
 void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
@@ -146,6 +145,5 @@
   // Persistent VR mode is not enough.
   // request_display_callback_(enabled);
 }
-
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index 2a83933..fdeb899 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -110,6 +110,7 @@
 }
 
 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
+  ATRACE_NAME("VSyncService::HandleMessage");
   switch (message.GetOp()) {
     case VSyncProtocol::Wait::Opcode:
       AddWaiter(message);
@@ -200,12 +201,12 @@
 }
 
 void VSyncChannel::Ack() {
-  ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
+  ALOGD_IF(TRACE > 1, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
   service_.ModifyChannelEvents(cid_, POLLPRI, 0);
 }
 
 void VSyncChannel::Signal() {
-  ALOGD_IF(TRACE, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
+  ALOGD_IF(TRACE > 1, "VSyncChannel::Signal: pid=%d cid=%d\n", pid_, cid_);
   service_.ModifyChannelEvents(cid_, 0, POLLPRI);
 }
 
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index abad78b..d022adf 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -23,9 +23,11 @@
 ]
 
 staticLibraries = [
+    "libdisplay",
     "libbufferhub",
     "libbufferhubqueue",
     "libdvrcommon",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
@@ -43,6 +45,7 @@
     export_include_dirs: includeFiles,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: ["libdvr_headers"],
     name: "libvrsensor",
 }
 
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index ed75f84..bb25f1d 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -14,63 +14,13 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#include <dvr/dvr_pose.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct DvrPose DvrPose;
-
-// Represents the current state provided by the pose service, containing a
-// rotation and translation.
-typedef struct __attribute__((packed, aligned(8))) DvrPoseState {
-  // A quaternion representing the rotation of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z, w;
-  } head_from_start_rotation;
-  // The position of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } head_from_start_translation;
-  // Time in nanoseconds for the current pose.
-  uint64_t timestamp_ns;
-  // The rotational velocity of the HMD.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } sensor_from_start_rotation_velocity;
-} DvrPoseState;
-
-enum {
-  DVR_POSE_FLAG_VALID = (1UL << 0),       // This pose is valid.
-  DVR_POSE_FLAG_HEAD = (1UL << 1),        // This pose is the head.
-  DVR_POSE_FLAG_CONTROLLER = (1UL << 2),  // This pose is a controller.
-};
-
-// Represents an estimated pose, accessed asynchronously through a shared ring
-// buffer. No assumptions should be made about the data in padding space.
-// The size of this struct is 128 bytes.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
-  // Left eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t orientation;
-  // Left eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t translation;
-  // Right eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t right_orientation;
-  // Right eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t right_translation;
-  // Start-space angular velocity x,y,z,pad in radians per second.
-  float32x4_t angular_velocity;
-  // Start-space positional velocity x,y,z,pad in meters per second.
-  float32x4_t velocity;
-  // Timestamp of when this pose is predicted for, typically halfway through
-  // scanout.
-  int64_t timestamp_ns;
-  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
-  //
-  // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
-  uint64_t flags;
-  // Reserved padding to 128 bytes.
-  uint8_t pad[16];
-} DvrPoseAsync;
+typedef struct DvrPoseClient DvrPoseClient;
 
 // Returned by the async pose ring buffer access API.
 typedef struct DvrPoseRingBufferInfo {
@@ -105,6 +55,8 @@
   DVR_POSE_MODE_MOCK_ROTATE_MEDIUM,
   DVR_POSE_MODE_MOCK_ROTATE_FAST,
   DVR_POSE_MODE_MOCK_CIRCLE_STRAFE,
+  DVR_POSE_MODE_FLOAT,
+  DVR_POSE_MODE_MOCK_MOTION_SICKNESS,
 
   // Always last.
   DVR_POSE_MODE_COUNT,
@@ -118,12 +70,12 @@
 // Creates a new pose client.
 //
 // @return Pointer to the created pose client, nullptr on failure.
-DvrPose* dvrPoseCreate();
+DvrPoseClient* dvrPoseClientCreate();
 
 // Destroys a pose client.
 //
 // @param client Pointer to the pose client to be destroyed.
-void dvrPoseDestroy(DvrPose* client);
+void dvrPoseClientDestroy(DvrPoseClient* client);
 
 // Gets the pose for the given vsync count.
 //
@@ -132,10 +84,11 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose);
 
 // Gets the current vsync count.
-uint32_t dvrPoseGetVsyncCount(DvrPose* client);
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client);
 
 // Gets the pose for the given controller at the given vsync count.
 //
@@ -145,15 +98,15 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose);
 
 // Enables/disables logging for the controller fusion.
 //
 // @param client Pointer to the pose client.
 // @param enable True starts logging, False stops.
 // @return Zero on success, negative error code on failure.
-int dvrPoseLogController(DvrPose* client, bool enable);
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable);
 
 // DEPRECATED
 // Polls current pose state.
@@ -161,30 +114,30 @@
 // @param client Pointer to the pose client.
 // @param state Struct to store polled state.
 // @return Zero on success, negative error code on failure.
-int dvrPosePoll(DvrPose* client, DvrPoseState* state);
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state);
 
 // Freezes the pose to the provided state.
 //
 // Future poll operations will return this state until a different state is
-// frozen or dvrPoseSetMode() is called with a different mode. The timestamp is
+// frozen or dvrPoseClientModeSet() is called with a different mode. The timestamp is
 // not frozen.
 //
 // @param client Pointer to the pose client.
 // @param frozen_state State pose to be frozen to.
 // @return Zero on success, negative error code on failure.
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state);
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state);
 
 // Sets the pose service mode.
 //
 // @param mode The requested pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode);
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode);
 
 // Gets the pose service mode.
 //
 // @param mode Return value for the current pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode);
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode);
 
 // Get access to the shared memory pose ring buffer.
 // A future pose at vsync <current> + <offset> is accessed at index:
@@ -195,8 +148,26 @@
 // |out_fd| will be set to the gralloc buffer file descriptor, which is
 //   required for binding this buffer for GPU use.
 // Returns 0 on success.
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info);
+int dvrPoseClientGetRingBuffer(DvrPoseClient* client,
+                               DvrPoseRingBufferInfo* out_info);
 
+// Sets enabled state for sensors pose processing.
+//
+// @param enabled Whether sensors are enabled or disabled.
+// @return Zero on success
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled);
+
+// Requests a burst of data samples from pose service. The data samples are
+// passed through a shared memory buffer obtained by calling
+// dvrPoseClientGetDataReader().
+//
+// @param DvrPoseDataCaptureRequest Parameters on how to capture data.
+// @return Zero on success.
+int dvrPoseClientDataCapture(DvrPoseClient* client,
+                             const DvrPoseDataCaptureRequest* request);
+
+// Destroys the write buffer queue for the given |data_type|.
+int dvrPoseClientDataReaderDestroy(DvrPoseClient* client, uint64_t data_type);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
index 0616d46..7bf1cd4 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
@@ -11,14 +11,15 @@
 #define DVR_POSE_SERVICE_CLIENT (DVR_POSE_SERVICE_BASE "/client")
 
 enum {
-  DVR_POSE_POLL = 0,
-  DVR_POSE_FREEZE,
+  DVR_POSE_FREEZE = 0,
   DVR_POSE_SET_MODE,
-  DVR_POSE_GET_RING_BUFFER,
-  DVR_POSE_NOTIFY_VSYNC,
   DVR_POSE_GET_MODE,
   DVR_POSE_GET_CONTROLLER_RING_BUFFER,
   DVR_POSE_LOG_CONTROLLER,
+  DVR_POSE_SENSORS_ENABLE,
+  DVR_POSE_GET_TANGO_READER,
+  DVR_POSE_DATA_CAPTURE,
+  DVR_POSE_TANGO_READER_DESTROY,
 };
 
 #ifdef __cplusplus
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
index 66c4c7c..39592bb 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
@@ -1,43 +1,19 @@
 #ifndef ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
 #define ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
 
-#include <stdint.h>
+#include <private/dvr/buffer_hub_queue_client.h>
 
-#include <dvr/pose_client.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/sensor_constants.h>
+using android::dvr::ConsumerQueue;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+typedef struct DvrPoseClient DvrPoseClient;
 
-// Sensord head pose ring buffer.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseRingBuffer {
-  // Ring buffer always at the beginning of the structure, as consumers may
-  // not have access to this parent structure definition.
-  DvrPoseAsync ring[kPoseAsyncBufferTotalCount];
-  // Current vsync_count (where sensord is writing poses from).
-  uint32_t vsync_count;
-} DvrPoseMetadata;
+namespace android {
+namespace dvr {
 
-// Called by displayd to give vsync count info to the pose service.
-// |display_timestamp| Display timestamp is in the middle of scanout.
-// |display_period_ns| Nanos between vsyncs.
-// |right_eye_photon_offset_ns| Nanos to shift the prediction timestamp for
-//    the right eye head pose (relative to the left eye prediction).
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns);
+int dvrPoseClientGetDataReaderHandle(DvrPoseClient *client, uint64_t data_type,
+                                     ConsumerQueue **queue_out);
 
-// Get file descriptor for access to the shared memory pose buffer. This can be
-// used with GL extensions that support shared memory buffer objects. The caller
-// takes ownership of the returned fd and must close it or pass on ownership.
-int privateDvrPoseGetRingBufferFd(DvrPose* client,
-                                  android::pdx::LocalHandle* fd);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+}  // namespace dvr
+}  // namespace android
 
 #endif  // ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h b/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
deleted file mode 100644
index 8fa87b3..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CONSTANTS_H_
-#define ANDROID_DVR_SENSOR_CONSTANTS_H_
-
-namespace android {
-namespace dvr {
-
-// Number of elements in the async pose buffer.
-// Must be power of two.
-// Macro so that shader code can easily include this value.
-#define kPoseAsyncBufferTotalCount 8
-
-// Mask for accessing the current ring buffer array element:
-// index = vsync_count & kPoseAsyncBufferIndexMask
-constexpr uint32_t kPoseAsyncBufferIndexMask = kPoseAsyncBufferTotalCount - 1;
-
-// Number of pose frames including the current frame that are kept updated with
-// pose forecast data. The other poses are left their last known estimates.
-constexpr uint32_t kPoseAsyncBufferMinFutureCount = 4;
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSOR_CONSTANTS_H_
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 9eae3aa..4acc085 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -1,4 +1,5 @@
 #define LOG_TAG "PoseClient"
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/pose_client.h>
 
 #include <stdint.h>
@@ -8,19 +9,25 @@
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_client.h>
 #include <private/dvr/pose-ipc.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sensor_constants.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
+using android::dvr::ConsumerQueue;
 using android::pdx::LocalHandle;
 using android::pdx::LocalChannelHandle;
 using android::pdx::Status;
 using android::pdx::Transaction;
 
-#define arraysize(x) (static_cast<int32_t>(std::extent<decltype(x)>::value))
-
 namespace android {
 namespace dvr {
+namespace {
+
+typedef CPUMappedBroadcastRing<DvrPoseRing> SensorPoseRing;
+
+constexpr static int32_t MAX_CONTROLLERS = 2;
+}  // namespace
 
 // PoseClient is a remote interface to the pose service in sensord.
 class PoseClient : public pdx::ClientBase<PoseClient> {
@@ -28,44 +35,54 @@
   ~PoseClient() override {}
 
   // Casts C handle into an instance of this class.
-  static PoseClient* FromC(DvrPose* client) {
+  static PoseClient* FromC(DvrPoseClient* client) {
     return reinterpret_cast<PoseClient*>(client);
   }
 
   // Polls the pose service for the current state and stores it in *state.
   // Returns zero on success, a negative error code otherwise.
-  int Poll(DvrPoseState* state) {
-    Transaction trans{*this};
-    Status<int> status =
-        trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
-    ALOGE_IF(!status, "Pose poll() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
+  int Poll(DvrPose* state) {
+    // Allocate the helper class to access the sensor pose buffer.
+    if (sensor_pose_buffer_ == nullptr) {
+      sensor_pose_buffer_ = std::make_unique<SensorPoseRing>(
+          DvrGlobalBuffers::kSensorPoseBuffer, CPUUsageMode::READ_RARELY);
+    }
+
+    if (state) {
+      if (sensor_pose_buffer_->GetNewest(state)) {
+        return 0;
+      } else {
+        return -EAGAIN;
+      }
+    }
+
+    return -EINVAL;
   }
 
   int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return ret;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      *out_pose =
+          vsync_buffer
+              ->vsync_poses[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
+      return 0;
+    } else {
+      return -EAGAIN;
     }
-    *out_pose =
-        mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
-    return 0;
   }
 
   uint32_t GetVsyncCount() {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return 0;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      return vsync_buffer->vsync_count;
     }
-    return mapped_pose_buffer_->vsync_count;
+
+    return 0;
   }
 
   int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
                         DvrPoseAsync* out_pose) {
-    if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
+    if (controller_id < 0 || controller_id >= MAX_CONTROLLERS) {
       return -EINVAL;
     }
     if (!controllers_[controller_id].mapped_pose_buffer) {
@@ -75,7 +92,7 @@
     }
     *out_pose =
         controllers_[controller_id]
-            .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
+            .mapped_pose_buffer[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
     return 0;
   }
 
@@ -92,7 +109,7 @@
   // this state until a different state is frozen or SetMode() is called with a
   // different mode.
   // Returns zero on success, a negative error code otherwise.
-  int Freeze(const DvrPoseState& frozen_state) {
+  int Freeze(const DvrPose& frozen_state) {
     Transaction trans{*this};
     Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
                                          sizeof(frozen_state), nullptr, 0);
@@ -124,52 +141,71 @@
     return ReturnStatusOrError(status);
   }
 
-  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
-    if (pose_buffer_.get()) {
-      if (out_info) {
-        GetPoseRingBufferInfo(out_info);
-      }
-      return 0;
-    }
-
+  int GetTangoReaderHandle(uint64_t data_type, ConsumerQueue** queue_out) {
+    // Get buffer.
     Transaction trans{*this};
-    Status<LocalChannelHandle> status =
-        trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
+    Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
+        DVR_POSE_GET_TANGO_READER, &data_type, sizeof(data_type), nullptr, 0);
+
     if (!status) {
-      ALOGE("Pose GetRingBuffer() failed because: %s",
+      ALOGE("PoseClient GetTangoReaderHandle() failed because: %s",
             status.GetErrorMessage().c_str());
+      *queue_out = nullptr;
       return -status.error();
     }
 
-    auto buffer = BufferConsumer::Import(status.take());
-    if (!buffer) {
-      ALOGE("Pose failed to import ring buffer");
-      return -EIO;
-    }
-    void* addr = nullptr;
-    int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
-    if (ret < 0 || !addr) {
-      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
-      return -EIO;
-    }
-    pose_buffer_.swap(buffer);
-    mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
-    ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
-          mapped_pose_buffer_->ring[0].translation[0],
-          mapped_pose_buffer_->ring[0].translation[1],
-          mapped_pose_buffer_->ring[0].translation[2],
-          mapped_pose_buffer_->ring[0].orientation[0],
-          mapped_pose_buffer_->ring[0].orientation[1],
-          mapped_pose_buffer_->ring[0].orientation[2],
-          mapped_pose_buffer_->ring[0].orientation[3]);
-    if (out_info) {
-      GetPoseRingBufferInfo(out_info);
-    }
+    std::unique_ptr<ConsumerQueue> consumer_queue =
+        ConsumerQueue::Import(status.take());
+    *queue_out = consumer_queue.release();
     return 0;
   }
 
+  int DataCapture(const DvrPoseDataCaptureRequest* request) {
+    Transaction trans{*this};
+    Status<int> status = trans.Send<int>(DVR_POSE_DATA_CAPTURE, request,
+                                         sizeof(*request), nullptr, 0);
+    ALOGE_IF(!status, "PoseClient DataCapture() failed because: %s\n",
+             status.GetErrorMessage().c_str());
+    return ReturnStatusOrError(status);
+  }
+
+  int DataReaderDestroy(uint64_t data_type) {
+    Transaction trans{*this};
+    Status<int> status = trans.Send<int>(DVR_POSE_TANGO_READER_DESTROY,
+                                         &data_type, sizeof(data_type), nullptr,
+                                         0);
+    ALOGE_IF(!status, "PoseClient DataReaderDestroy() failed because: %s\n",
+             status.GetErrorMessage().c_str());
+    return ReturnStatusOrError(status);
+  }
+
+  // Enables or disables all pose processing from sensors
+  int EnableSensors(bool enabled) {
+    Transaction trans{*this};
+    Status<int> status = trans.Send<int>(DVR_POSE_SENSORS_ENABLE, &enabled,
+                                         sizeof(enabled), nullptr, 0);
+    ALOGE_IF(!status, "Pose EnableSensors() failed because: %s\n",
+             status.GetErrorMessage().c_str());
+    return ReturnStatusOrError(status);
+  }
+
+  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
+    // First time mapping the buffer?
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      if (out_info) {
+        out_info->min_future_count = DvrVsyncPoseBuffer::kMinFutureCount;
+        out_info->total_count = DvrVsyncPoseBuffer::kSize;
+        out_info->buffer = vsync_buffer->vsync_poses;
+      }
+      return -EINVAL;
+    }
+
+    return -EAGAIN;
+  }
+
   int GetControllerRingBuffer(int32_t controller_id) {
-    if (controller_id < 0 || controller_id >= arraysize(controllers_)) {
+    if (controller_id < 0 || controller_id >= MAX_CONTROLLERS) {
       return -EINVAL;
     }
     ControllerClientState& client_state = controllers_[controller_id];
@@ -190,7 +226,7 @@
       ALOGE("Pose failed to import ring buffer");
       return -EIO;
     }
-    constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
+    constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
     void* addr = nullptr;
     int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
     if (ret < 0 || !addr) {
@@ -201,9 +237,9 @@
     client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
     ALOGI(
         "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
-        controller_id, client_state.mapped_pose_buffer[0].translation[0],
-        client_state.mapped_pose_buffer[0].translation[1],
-        client_state.mapped_pose_buffer[0].translation[2],
+        controller_id, client_state.mapped_pose_buffer[0].position[0],
+        client_state.mapped_pose_buffer[0].position[1],
+        client_state.mapped_pose_buffer[0].position[2],
         client_state.mapped_pose_buffer[0].orientation[0],
         client_state.mapped_pose_buffer[0].orientation[1],
         client_state.mapped_pose_buffer[0].orientation[2],
@@ -211,32 +247,6 @@
     return 0;
   }
 
-  int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
-                  int64_t display_period_ns,
-                  int64_t right_eye_photon_offset_ns) {
-    const struct iovec data[] = {
-        {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
-        {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
-        {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
-        {.iov_base = &right_eye_photon_offset_ns,
-         .iov_len = sizeof(right_eye_photon_offset_ns)},
-    };
-    Transaction trans{*this};
-    Status<int> status =
-        trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
-    ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
-  }
-
-  int GetRingBufferFd(LocalHandle* fd) {
-    int ret = GetRingBuffer(nullptr);
-    if (ret < 0)
-      return ret;
-    *fd = pose_buffer_->GetBlobFd();
-    return 0;
-  }
-
  private:
   friend BASE;
 
@@ -252,87 +262,107 @@
   PoseClient(const PoseClient&) = delete;
   PoseClient& operator=(const PoseClient&) = delete;
 
-  void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
-    out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
-    out_info->total_count = kPoseAsyncBufferTotalCount;
-    out_info->buffer = mapped_pose_buffer_->ring;
+  const DvrVsyncPoseBuffer* GetVsyncBuffer() {
+    if (mapped_vsync_pose_buffer_ == nullptr) {
+      if (vsync_pose_buffer_ == nullptr) {
+        // The constructor tries mapping it so we do not need TryMapping after.
+        vsync_pose_buffer_ = std::make_unique<CPUMappedBuffer>(
+            DvrGlobalBuffers::kVsyncPoseBuffer, CPUUsageMode::READ_OFTEN);
+      } else if (vsync_pose_buffer_->IsMapped() == false) {
+        vsync_pose_buffer_->TryMapping();
+      }
+
+      if (vsync_pose_buffer_->IsMapped()) {
+        mapped_vsync_pose_buffer_ =
+            static_cast<DvrVsyncPoseBuffer*>(vsync_pose_buffer_->Address());
+      }
+    }
+
+    return mapped_vsync_pose_buffer_;
   }
 
-  std::unique_ptr<BufferConsumer> pose_buffer_;
-  const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
+  // The vsync pose buffer if already mapped.
+  std::unique_ptr<CPUMappedBuffer> vsync_pose_buffer_;
+
+  // The direct sensor pose buffer.
+  std::unique_ptr<SensorPoseRing> sensor_pose_buffer_;
+
+  const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
 
   struct ControllerClientState {
     std::unique_ptr<BufferConsumer> pose_buffer;
     const DvrPoseAsync* mapped_pose_buffer = nullptr;
   };
-  ControllerClientState controllers_[2];
+  ControllerClientState controllers_[MAX_CONTROLLERS];
 };
 
+int dvrPoseClientGetDataReaderHandle(DvrPoseClient* client, uint64_t type,
+                                     ConsumerQueue** queue_out) {
+  return PoseClient::FromC(client)->GetTangoReaderHandle(type, queue_out);
+}
+
 }  // namespace dvr
 }  // namespace android
 
 using android::dvr::PoseClient;
 
-struct DvrPose {};
-
 extern "C" {
 
-DvrPose* dvrPoseCreate() {
-  PoseClient* client = PoseClient::Create().release();
-  return reinterpret_cast<DvrPose*>(client);
+DvrPoseClient* dvrPoseClientCreate() {
+  auto* client = PoseClient::Create().release();
+  return reinterpret_cast<DvrPoseClient*>(client);
 }
 
-void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
+void dvrPoseClientDestroy(DvrPoseClient* client) {
+  delete PoseClient::FromC(client);
+}
 
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
 }
 
-uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client) {
   return PoseClient::FromC(client)->GetVsyncCount();
 }
 
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetControllerPose(controller_id,
                                                       vsync_count, out_pose);
 }
 
-int dvrPoseLogController(DvrPose* client, bool enable) {
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable) {
   return PoseClient::FromC(client)->LogController(enable);
 }
 
-int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state) {
   return PoseClient::FromC(client)->Poll(state);
 }
 
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state) {
   return PoseClient::FromC(client)->Freeze(*frozen_state);
 }
 
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode) {
   return PoseClient::FromC(client)->SetMode(mode);
 }
 
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode) {
   return PoseClient::FromC(client)->GetMode(mode);
 }
 
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
-  return PoseClient::FromC(client)->GetRingBuffer(out_info);
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled) {
+  return PoseClient::FromC(client)->EnableSensors(enabled);
 }
 
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns) {
-  return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
-                                                display_period_ns,
-                                                right_eye_photon_offset_ns);
+int dvrPoseClientDataCapture(DvrPoseClient* client,
+                             const DvrPoseDataCaptureRequest* request) {
+  return PoseClient::FromC(client)->DataCapture(request);
 }
 
-int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
-  return PoseClient::FromC(client)->GetRingBufferFd(fd);
+int dvrPoseClientDataReaderDestroy(DvrPoseClient* client, uint64_t data_type) {
+  return PoseClient::FromC(client)->DataReaderDestroy(data_type);
 }
 
 }  // extern "C"
diff --git a/opengl/Android.bp b/opengl/Android.bp
index c520bda..9ca8b0b 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -52,6 +52,36 @@
     license: "include/KHR/NOTICE",
 }
 
+llndk_library {
+    name: "libEGL",
+    symbol_file: "libs/libEGL.map.txt",
+    export_include_dirs: ["include"],
+}
+
+llndk_library {
+    name: "libGLESv1_CM",
+    symbol_file: "libs/libGLESv1_CM.map.txt",
+    export_include_dirs: ["include"],
+}
+
+llndk_library {
+    name: "libGLESv2",
+    symbol_file: "libs/libGLESv2.map.txt",
+    export_include_dirs: ["include"],
+}
+
+llndk_library {
+    name: "libGLESv3",
+    symbol_file: "libs/libGLESv3.map.txt",
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "gl_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+}
+
 subdirs = [
     "*",
 ]
diff --git a/opengl/include/EGL/NOTICE b/opengl/include/EGL/NOTICE
index 55f5efa..93d0f2e 100644
--- a/opengl/include/EGL/NOTICE
+++ b/opengl/include/EGL/NOTICE
@@ -1,4 +1,4 @@
-Copyright (c) 2007-2009 The Khronos Group Inc.
+Copyright (c) 2007-2017 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
diff --git a/opengl/include/EGL/egl.h b/opengl/include/EGL/egl.h
index ccb54ea..93a3965 100644
--- a/opengl/include/EGL/egl.h
+++ b/opengl/include/EGL/egl.h
@@ -1,11 +1,12 @@
-/* -*- mode: c; tab-width: 8; -*- */
-/* vi: set sw=4 ts=8: */
-/* Reference version of egl.h for EGL 1.4.
- * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
- */
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2013-2017 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
@@ -26,304 +27,221 @@
 ** 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 OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.khronos.org/registry/egl
+**
+** Khronos $Git commit SHA1: a732b061e7 $ on $Git commit date: 2017-06-17 23:27:53 +0100 $
+*/
 
-#ifndef __egl_h_
-#define __egl_h_
-
-/* All platform-dependent types and macro boilerplate (such as EGLAPI
- * and EGLAPIENTRY) should go in eglplatform.h.
- */
 #include <EGL/eglplatform.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+/* Generated on date 20170627 */
 
-/* EGL Types */
-/* EGLint is defined in eglplatform.h */
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
 typedef unsigned int EGLBoolean;
-typedef unsigned int EGLenum;
-typedef void *EGLConfig;
-typedef void *EGLContext;
 typedef void *EGLDisplay;
+#include <KHR/khrplatform.h>
+#include <EGL/eglplatform.h>
+typedef void *EGLConfig;
 typedef void *EGLSurface;
-typedef void *EGLClientBuffer;
-
-/* EGL Versioning */
-#define EGL_VERSION_1_0			1
-#define EGL_VERSION_1_1			1
-#define EGL_VERSION_1_2			1
-#define EGL_VERSION_1_3			1
-#define EGL_VERSION_1_4			1
-
-/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
- * enums are assigned unique values starting at 0x3000.
- */
-
-/* EGL aliases */
-#define EGL_FALSE			0
-#define EGL_TRUE			1
-
-/* Out-of-band handle values */
-#define EGL_DEFAULT_DISPLAY		EGL_CAST(EGLNativeDisplayType, 0)
-#define EGL_NO_CONTEXT			EGL_CAST(EGLContext, 0)
-#define EGL_NO_DISPLAY			EGL_CAST(EGLDisplay, 0)
-#define EGL_NO_SURFACE			EGL_CAST(EGLSurface, 0)
-
-/* Out-of-band attribute value */
-#define EGL_DONT_CARE			EGL_CAST(EGLint, -1)
-
-/* Errors / GetError return values */
-#define EGL_SUCCESS			0x3000
-#define EGL_NOT_INITIALIZED		0x3001
-#define EGL_BAD_ACCESS			0x3002
-#define EGL_BAD_ALLOC			0x3003
-#define EGL_BAD_ATTRIBUTE		0x3004
-#define EGL_BAD_CONFIG			0x3005
-#define EGL_BAD_CONTEXT			0x3006
-#define EGL_BAD_CURRENT_SURFACE		0x3007
-#define EGL_BAD_DISPLAY			0x3008
-#define EGL_BAD_MATCH			0x3009
-#define EGL_BAD_NATIVE_PIXMAP		0x300A
-#define EGL_BAD_NATIVE_WINDOW		0x300B
-#define EGL_BAD_PARAMETER		0x300C
-#define EGL_BAD_SURFACE			0x300D
-#define EGL_CONTEXT_LOST		0x300E	/* EGL 1.1 - IMG_power_management */
-
-/* Reserved 0x300F-0x301F for additional errors */
-
-/* Config attributes */
-#define EGL_BUFFER_SIZE			0x3020
-#define EGL_ALPHA_SIZE			0x3021
-#define EGL_BLUE_SIZE			0x3022
-#define EGL_GREEN_SIZE			0x3023
-#define EGL_RED_SIZE			0x3024
-#define EGL_DEPTH_SIZE			0x3025
-#define EGL_STENCIL_SIZE		0x3026
-#define EGL_CONFIG_CAVEAT		0x3027
-#define EGL_CONFIG_ID			0x3028
-#define EGL_LEVEL			0x3029
-#define EGL_MAX_PBUFFER_HEIGHT		0x302A
-#define EGL_MAX_PBUFFER_PIXELS		0x302B
-#define EGL_MAX_PBUFFER_WIDTH		0x302C
-#define EGL_NATIVE_RENDERABLE		0x302D
-#define EGL_NATIVE_VISUAL_ID		0x302E
-#define EGL_NATIVE_VISUAL_TYPE		0x302F
-#define EGL_SAMPLES			0x3031
-#define EGL_SAMPLE_BUFFERS		0x3032
-#define EGL_SURFACE_TYPE		0x3033
-#define EGL_TRANSPARENT_TYPE		0x3034
-#define EGL_TRANSPARENT_BLUE_VALUE	0x3035
-#define EGL_TRANSPARENT_GREEN_VALUE	0x3036
-#define EGL_TRANSPARENT_RED_VALUE	0x3037
-#define EGL_NONE			0x3038	/* Attrib list terminator */
-#define EGL_BIND_TO_TEXTURE_RGB		0x3039
-#define EGL_BIND_TO_TEXTURE_RGBA	0x303A
-#define EGL_MIN_SWAP_INTERVAL		0x303B
-#define EGL_MAX_SWAP_INTERVAL		0x303C
-#define EGL_LUMINANCE_SIZE		0x303D
-#define EGL_ALPHA_MASK_SIZE		0x303E
-#define EGL_COLOR_BUFFER_TYPE		0x303F
-#define EGL_RENDERABLE_TYPE		0x3040
-#define EGL_MATCH_NATIVE_PIXMAP		0x3041	/* Pseudo-attribute (not queryable) */
-#define EGL_CONFORMANT			0x3042
-
-/* Reserved 0x3041-0x304F for additional config attributes */
-
-/* Config attribute values */
-#define EGL_SLOW_CONFIG			0x3050	/* EGL_CONFIG_CAVEAT value */
-#define EGL_NON_CONFORMANT_CONFIG	0x3051	/* EGL_CONFIG_CAVEAT value */
-#define EGL_TRANSPARENT_RGB		0x3052	/* EGL_TRANSPARENT_TYPE value */
-#define EGL_RGB_BUFFER			0x308E	/* EGL_COLOR_BUFFER_TYPE value */
-#define EGL_LUMINANCE_BUFFER		0x308F	/* EGL_COLOR_BUFFER_TYPE value */
-
-/* More config attribute values, for EGL_TEXTURE_FORMAT */
-#define EGL_NO_TEXTURE			0x305C
-#define EGL_TEXTURE_RGB			0x305D
-#define EGL_TEXTURE_RGBA		0x305E
-#define EGL_TEXTURE_2D			0x305F
-
-/* Config attribute mask bits */
-#define EGL_PBUFFER_BIT			0x0001	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_PIXMAP_BIT			0x0002	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_WINDOW_BIT			0x0004	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_VG_COLORSPACE_LINEAR_BIT	0x0020	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT	0x0040	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200	/* EGL_SURFACE_TYPE mask bits */
-#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400	/* EGL_SURFACE_TYPE mask bits */
-
-#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENVG_BIT			0x0002	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_BIT			0x0008	/* EGL_RENDERABLE_TYPE mask bits */
-
-/* QueryString targets */
-#define EGL_VENDOR			0x3053
-#define EGL_VERSION			0x3054
-#define EGL_EXTENSIONS			0x3055
-#define EGL_CLIENT_APIS			0x308D
-
-/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
-#define EGL_HEIGHT			0x3056
-#define EGL_WIDTH			0x3057
-#define EGL_LARGEST_PBUFFER		0x3058
-#define EGL_TEXTURE_FORMAT		0x3080
-#define EGL_TEXTURE_TARGET		0x3081
-#define EGL_MIPMAP_TEXTURE		0x3082
-#define EGL_MIPMAP_LEVEL		0x3083
-#define EGL_RENDER_BUFFER		0x3086
-#define EGL_VG_COLORSPACE		0x3087
-#define EGL_VG_ALPHA_FORMAT		0x3088
-#define EGL_HORIZONTAL_RESOLUTION	0x3090
-#define EGL_VERTICAL_RESOLUTION		0x3091
-#define EGL_PIXEL_ASPECT_RATIO		0x3092
-#define EGL_SWAP_BEHAVIOR		0x3093
-#define EGL_MULTISAMPLE_RESOLVE		0x3099
-
-/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
-#define EGL_BACK_BUFFER			0x3084
-#define EGL_SINGLE_BUFFER		0x3085
-
-/* OpenVG color spaces */
-#define EGL_VG_COLORSPACE_sRGB		0x3089	/* EGL_VG_COLORSPACE value */
-#define EGL_VG_COLORSPACE_LINEAR	0x308A	/* EGL_VG_COLORSPACE value */
-
-/* OpenVG alpha formats */
-#define EGL_VG_ALPHA_FORMAT_NONPRE	0x308B	/* EGL_ALPHA_FORMAT value */
-#define EGL_VG_ALPHA_FORMAT_PRE		0x308C	/* EGL_ALPHA_FORMAT value */
-
-/* Constant scale factor by which fractional display resolutions &
- * aspect ratio are scaled when queried as integer values.
- */
-#define EGL_DISPLAY_SCALING		10000
-
-/* Unknown display resolution/aspect ratio */
-#define EGL_UNKNOWN			EGL_CAST(EGLint, -1)
-
-/* Back buffer swap behaviors */
-#define EGL_BUFFER_PRESERVED		0x3094	/* EGL_SWAP_BEHAVIOR value */
-#define EGL_BUFFER_DESTROYED		0x3095	/* EGL_SWAP_BEHAVIOR value */
-
-/* CreatePbufferFromClientBuffer buffer types */
-#define EGL_OPENVG_IMAGE		0x3096
-
-/* QueryContext targets */
-#define EGL_CONTEXT_CLIENT_TYPE		0x3097
-
-/* CreateContext attributes */
-#define EGL_CONTEXT_CLIENT_VERSION	0x3098
-
-/* Multisample resolution behaviors */
-#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A	/* EGL_MULTISAMPLE_RESOLVE value */
-#define EGL_MULTISAMPLE_RESOLVE_BOX	0x309B	/* EGL_MULTISAMPLE_RESOLVE value */
-
-/* BindAPI/QueryAPI targets */
-#define EGL_OPENGL_ES_API		0x30A0
-#define EGL_OPENVG_API			0x30A1
-#define EGL_OPENGL_API			0x30A2
-
-/* GetCurrentSurface targets */
-#define EGL_DRAW			0x3059
-#define EGL_READ			0x305A
-
-/* WaitNative engines */
-#define EGL_CORE_NATIVE_ENGINE		0x305B
-
-/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
-#define EGL_COLORSPACE			EGL_VG_COLORSPACE
-#define EGL_ALPHA_FORMAT		EGL_VG_ALPHA_FORMAT
-#define EGL_COLORSPACE_sRGB		EGL_VG_COLORSPACE_sRGB
-#define EGL_COLORSPACE_LINEAR		EGL_VG_COLORSPACE_LINEAR
-#define EGL_ALPHA_FORMAT_NONPRE		EGL_VG_ALPHA_FORMAT_NONPRE
-#define EGL_ALPHA_FORMAT_PRE		EGL_VG_ALPHA_FORMAT_PRE
-
-/* EGL extensions must request enum blocks from the Khronos
- * API Registrar, who maintains the enumerant registry. Submit
- * a bug in Khronos Bugzilla against task "Registry".
- */
-
-
-
-/* EGL Functions */
-
-EGLAPI EGLint EGLAPIENTRY eglGetError(void);
-
-EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
-EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
-EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
-
-EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
-			 EGLint config_size, EGLint *num_config);
-EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
-			   EGLConfig *configs, EGLint config_size,
-			   EGLint *num_config);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
-			      EGLint attribute, EGLint *value);
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
-				  EGLNativeWindowType win,
-				  const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
-				   const EGLint *attrib_list);
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
-				  EGLNativePixmapType pixmap,
-				  const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
-			   EGLint attribute, EGLint *value);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
-EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
-
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
-	      EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
-	      EGLConfig config, const EGLint *attrib_list);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
-			    EGLint attribute, EGLint value);
-EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
-
-
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
-
-
-EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
-			    EGLContext share_context,
-			    const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
-EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
-			  EGLSurface read, EGLContext ctx);
-
-EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
-EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
-EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
-			   EGLint attribute, EGLint *value);
-
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
-EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
-EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
-EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
-			  EGLNativePixmapType target);
-
-/* This is a generic function pointer type, whose name indicates it must
- * be cast to the proper type *and calling convention* before use.
- */
+typedef void *EGLContext;
 typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE                    0x3021
+#define EGL_BAD_ACCESS                    0x3002
+#define EGL_BAD_ALLOC                     0x3003
+#define EGL_BAD_ATTRIBUTE                 0x3004
+#define EGL_BAD_CONFIG                    0x3005
+#define EGL_BAD_CONTEXT                   0x3006
+#define EGL_BAD_CURRENT_SURFACE           0x3007
+#define EGL_BAD_DISPLAY                   0x3008
+#define EGL_BAD_MATCH                     0x3009
+#define EGL_BAD_NATIVE_PIXMAP             0x300A
+#define EGL_BAD_NATIVE_WINDOW             0x300B
+#define EGL_BAD_PARAMETER                 0x300C
+#define EGL_BAD_SURFACE                   0x300D
+#define EGL_BLUE_SIZE                     0x3022
+#define EGL_BUFFER_SIZE                   0x3020
+#define EGL_CONFIG_CAVEAT                 0x3027
+#define EGL_CONFIG_ID                     0x3028
+#define EGL_CORE_NATIVE_ENGINE            0x305B
+#define EGL_DEPTH_SIZE                    0x3025
+#define EGL_DONT_CARE                     EGL_CAST(EGLint,-1)
+#define EGL_DRAW                          0x3059
+#define EGL_EXTENSIONS                    0x3055
+#define EGL_FALSE                         0
+#define EGL_GREEN_SIZE                    0x3023
+#define EGL_HEIGHT                        0x3056
+#define EGL_LARGEST_PBUFFER               0x3058
+#define EGL_LEVEL                         0x3029
+#define EGL_MAX_PBUFFER_HEIGHT            0x302A
+#define EGL_MAX_PBUFFER_PIXELS            0x302B
+#define EGL_MAX_PBUFFER_WIDTH             0x302C
+#define EGL_NATIVE_RENDERABLE             0x302D
+#define EGL_NATIVE_VISUAL_ID              0x302E
+#define EGL_NATIVE_VISUAL_TYPE            0x302F
+#define EGL_NONE                          0x3038
+#define EGL_NON_CONFORMANT_CONFIG         0x3051
+#define EGL_NOT_INITIALIZED               0x3001
+#define EGL_NO_CONTEXT                    EGL_CAST(EGLContext,0)
+#define EGL_NO_DISPLAY                    EGL_CAST(EGLDisplay,0)
+#define EGL_NO_SURFACE                    EGL_CAST(EGLSurface,0)
+#define EGL_PBUFFER_BIT                   0x0001
+#define EGL_PIXMAP_BIT                    0x0002
+#define EGL_READ                          0x305A
+#define EGL_RED_SIZE                      0x3024
+#define EGL_SAMPLES                       0x3031
+#define EGL_SAMPLE_BUFFERS                0x3032
+#define EGL_SLOW_CONFIG                   0x3050
+#define EGL_STENCIL_SIZE                  0x3026
+#define EGL_SUCCESS                       0x3000
+#define EGL_SURFACE_TYPE                  0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE        0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE       0x3036
+#define EGL_TRANSPARENT_RED_VALUE         0x3037
+#define EGL_TRANSPARENT_RGB               0x3052
+#define EGL_TRANSPARENT_TYPE              0x3034
+#define EGL_TRUE                          1
+#define EGL_VENDOR                        0x3053
+#define EGL_VERSION                       0x3054
+#define EGL_WIDTH                         0x3057
+#define EGL_WINDOW_BIT                    0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
 
-/* Now, define eglGetProcAddress using the generic function ptr. type */
-EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
-       eglGetProcAddress(const char *procname);
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER                   0x3084
+#define EGL_BIND_TO_TEXTURE_RGB           0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA          0x303A
+#define EGL_CONTEXT_LOST                  0x300E
+#define EGL_MIN_SWAP_INTERVAL             0x303B
+#define EGL_MAX_SWAP_INTERVAL             0x303C
+#define EGL_MIPMAP_TEXTURE                0x3082
+#define EGL_MIPMAP_LEVEL                  0x3083
+#define EGL_NO_TEXTURE                    0x305C
+#define EGL_TEXTURE_2D                    0x305F
+#define EGL_TEXTURE_FORMAT                0x3080
+#define EGL_TEXTURE_RGB                   0x305D
+#define EGL_TEXTURE_RGBA                  0x305E
+#define EGL_TEXTURE_TARGET                0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT                  0x3088
+#define EGL_ALPHA_FORMAT_NONPRE           0x308B
+#define EGL_ALPHA_FORMAT_PRE              0x308C
+#define EGL_ALPHA_MASK_SIZE               0x303E
+#define EGL_BUFFER_PRESERVED              0x3094
+#define EGL_BUFFER_DESTROYED              0x3095
+#define EGL_CLIENT_APIS                   0x308D
+#define EGL_COLORSPACE                    0x3087
+#define EGL_COLORSPACE_sRGB               0x3089
+#define EGL_COLORSPACE_LINEAR             0x308A
+#define EGL_COLOR_BUFFER_TYPE             0x303F
+#define EGL_CONTEXT_CLIENT_TYPE           0x3097
+#define EGL_DISPLAY_SCALING               10000
+#define EGL_HORIZONTAL_RESOLUTION         0x3090
+#define EGL_LUMINANCE_BUFFER              0x308F
+#define EGL_LUMINANCE_SIZE                0x303D
+#define EGL_OPENGL_ES_BIT                 0x0001
+#define EGL_OPENVG_BIT                    0x0002
+#define EGL_OPENGL_ES_API                 0x30A0
+#define EGL_OPENVG_API                    0x30A1
+#define EGL_OPENVG_IMAGE                  0x3096
+#define EGL_PIXEL_ASPECT_RATIO            0x3092
+#define EGL_RENDERABLE_TYPE               0x3040
+#define EGL_RENDER_BUFFER                 0x3086
+#define EGL_RGB_BUFFER                    0x308E
+#define EGL_SINGLE_BUFFER                 0x3085
+#define EGL_SWAP_BEHAVIOR                 0x3093
+#define EGL_UNKNOWN                       EGL_CAST(EGLint,-1)
+#define EGL_VERTICAL_RESOLUTION           0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT                    0x3042
+#define EGL_CONTEXT_CLIENT_VERSION        0x3098
+#define EGL_MATCH_NATIVE_PIXMAP           0x3041
+#define EGL_OPENGL_ES2_BIT                0x0004
+#define EGL_VG_ALPHA_FORMAT               0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE        0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE           0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT       0x0040
+#define EGL_VG_COLORSPACE                 0x3087
+#define EGL_VG_COLORSPACE_sRGB            0x3089
+#define EGL_VG_COLORSPACE_LINEAR          0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT      0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY               EGL_CAST(EGLNativeDisplayType,0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT   0x0200
+#define EGL_MULTISAMPLE_RESOLVE           0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT   0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX       0x309B
+#define EGL_OPENGL_API                    0x30A2
+#define EGL_OPENGL_BIT                    0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT   0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+/* This version of Android does not yet support EGL 1.5, but the following
+ * portion of EGL 1.5 is included in order to support portions of "eglext.h".
+ */
+typedef intptr_t EGLAttrib;
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __egl_h_ */
+#endif
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index d0996f0..466768a 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -1,12 +1,12 @@
 #ifndef __eglext_h_
-#define __eglext_h_
+#define __eglext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
-** Copyright (c) 2007-2013 The Khronos Group Inc.
+** Copyright (c) 2013-2017 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
@@ -27,161 +27,254 @@
 ** 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 OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.khronos.org/registry/egl
+**
+** Khronos $Git commit SHA1: a732b061e7 $ on $Git commit date: 2017-06-17 23:27:53 +0100 $
+*/
 
 #include <EGL/eglplatform.h>
 
-/*************************************************************/
+#define EGL_EGLEXT_VERSION 20170627
 
-/* Header file version number */
-/* Current version at http://www.khronos.org/registry/egl/ */
-/* $Revision: 20690 $ on $Date: 2013-02-22 17:15:05 -0800 (Fri, 22 Feb 2013) $ */
-#define EGL_EGLEXT_VERSION 15
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR           0x309C
+#define EGL_SYNC_CL_EVENT_KHR             0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR    0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
 
 #ifndef EGL_KHR_config_attribs
 #define EGL_KHR_config_attribs 1
-#define EGL_CONFORMANT_KHR			0x3042	/* EGLConfig attribute */
-#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR	0x0020	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR		0x0040	/* EGL_SURFACE_TYPE bitfield */
-#endif
+#define EGL_CONFORMANT_KHR                0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR  0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR   0x0040
+#endif /* EGL_KHR_config_attribs */
 
-#ifndef EGL_KHR_lock_surface
-#define EGL_KHR_lock_surface 1
-#define EGL_READ_SURFACE_BIT_KHR		0x0001	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
-#define EGL_WRITE_SURFACE_BIT_KHR		0x0002	/* EGL_LOCK_USAGE_HINT_KHR bitfield */
-#define EGL_LOCK_SURFACE_BIT_KHR		0x0080	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_OPTIMAL_FORMAT_BIT_KHR		0x0100	/* EGL_SURFACE_TYPE bitfield */
-#define EGL_MATCH_FORMAT_KHR			0x3043	/* EGLConfig attribute */
-#define EGL_FORMAT_RGB_565_EXACT_KHR		0x30C0	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGB_565_KHR			0x30C1	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGBA_8888_EXACT_KHR		0x30C2	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_FORMAT_RGBA_8888_KHR		0x30C3	/* EGL_MATCH_FORMAT_KHR value */
-#define EGL_MAP_PRESERVE_PIXELS_KHR		0x30C4	/* eglLockSurfaceKHR attribute */
-#define EGL_LOCK_USAGE_HINT_KHR			0x30C5	/* eglLockSurfaceKHR attribute */
-#define EGL_BITMAP_POINTER_KHR			0x30C6	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PITCH_KHR			0x30C7	/* eglQuerySurface attribute */
-#define EGL_BITMAP_ORIGIN_KHR			0x30C8	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR		0x30C9	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR	0x30CA	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR	0x30CB	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR	0x30CC	/* eglQuerySurface attribute */
-#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR	0x30CD	/* eglQuerySurface attribute */
-#define EGL_LOWER_LEFT_KHR			0x30CE	/* EGL_BITMAP_ORIGIN_KHR value */
-#define EGL_UPPER_LEFT_KHR			0x30CF	/* EGL_BITMAP_ORIGIN_KHR value */
+#ifndef EGL_KHR_context_flush_control
+#define EGL_KHR_context_flush_control 1
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR  0x2097
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+#endif /* EGL_KHR_context_flush_control */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR     0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR     0x30FB
+#define EGL_CONTEXT_FLAGS_KHR             0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR     0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR  0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR            0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR   0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
+#ifndef EGL_KHR_debug
+#define EGL_KHR_debug 1
+typedef void *EGLLabelKHR;
+typedef void *EGLObjectKHR;
+typedef void (EGLAPIENTRY  *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
+#define EGL_OBJECT_THREAD_KHR             0x33B0
+#define EGL_OBJECT_DISPLAY_KHR            0x33B1
+#define EGL_OBJECT_CONTEXT_KHR            0x33B2
+#define EGL_OBJECT_SURFACE_KHR            0x33B3
+#define EGL_OBJECT_IMAGE_KHR              0x33B4
+#define EGL_OBJECT_SYNC_KHR               0x33B5
+#define EGL_OBJECT_STREAM_KHR             0x33B6
+#define EGL_DEBUG_MSG_CRITICAL_KHR        0x33B9
+#define EGL_DEBUG_MSG_ERROR_KHR           0x33BA
+#define EGL_DEBUG_MSG_WARN_KHR            0x33BB
+#define EGL_DEBUG_MSG_INFO_KHR            0x33BC
+#define EGL_DEBUG_CALLBACK_KHR            0x33B8
+typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value);
+typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
+EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value);
+EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
 #endif
+#endif /* EGL_KHR_debug */
 
-#ifndef EGL_KHR_image
-#define EGL_KHR_image 1
-#define EGL_NATIVE_PIXMAP_KHR			0x30B0	/* eglCreateImageKHR target */
-typedef void *EGLImageKHR;
-#define EGL_NO_IMAGE_KHR			EGL_CAST(EGLImageKHR, 0)
+#ifndef EGL_KHR_display_reference
+#define EGL_KHR_display_reference 1
+#define EGL_TRACK_REFERENCES_KHR          0x3352
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBKHRPROC) (EGLDisplay dpy, EGLint name, EGLAttrib *value);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribKHR (EGLDisplay dpy, EGLint name, EGLAttrib *value);
 #endif
+#endif /* EGL_KHR_display_reference */
 
-#ifndef EGL_KHR_vg_parent_image
-#define EGL_KHR_vg_parent_image 1
-#define EGL_VG_PARENT_IMAGE_KHR			0x30BA	/* eglCreateImageKHR target */
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR            0x30F8
+#define EGL_SYNC_FENCE_KHR                0x30F9
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
 #endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
 
-#ifndef EGL_KHR_gl_texture_2D_image
-#define EGL_KHR_gl_texture_2D_image 1
-#define EGL_GL_TEXTURE_2D_KHR			0x30B1	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_LEVEL_KHR		0x30BC	/* eglCreateImageKHR attribute */
-#endif
-
-#ifndef EGL_KHR_gl_texture_cubemap_image
-#define EGL_KHR_gl_texture_cubemap_image 1
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR	0x30B3	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR	0x30B4	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR	0x30B5	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR	0x30B6	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR	0x30B7	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR	0x30B8	/* eglCreateImageKHR target */
-#endif
-
-#ifndef EGL_KHR_gl_texture_3D_image
-#define EGL_KHR_gl_texture_3D_image 1
-#define EGL_GL_TEXTURE_3D_KHR			0x30B2	/* eglCreateImageKHR target */
-#define EGL_GL_TEXTURE_ZOFFSET_KHR		0x30BD	/* eglCreateImageKHR attribute */
-#endif
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
 
 #ifndef EGL_KHR_gl_colorspace
 #define EGL_KHR_gl_colorspace 1
 #define EGL_GL_COLORSPACE_KHR             0x309D
 #define EGL_GL_COLORSPACE_SRGB_KHR        0x3089
 #define EGL_GL_COLORSPACE_LINEAR_KHR      0x308A
-#endif
+#endif /* EGL_KHR_gl_colorspace */
 
 #ifndef EGL_KHR_gl_renderbuffer_image
 #define EGL_KHR_gl_renderbuffer_image 1
-#define EGL_GL_RENDERBUFFER_KHR			0x30B9	/* eglCreateImageKHR target */
-#endif
+#define EGL_GL_RENDERBUFFER_KHR           0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
 
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
-#ifndef EGL_KHR_reusable_sync
-#define EGL_KHR_reusable_sync 1
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR             0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR          0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
 
-typedef void* EGLSyncKHR;
-typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR             0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR        0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
 
-#define EGL_SYNC_STATUS_KHR			0x30F1
-#define EGL_SIGNALED_KHR			0x30F2
-#define EGL_UNSIGNALED_KHR			0x30F3
-#define EGL_TIMEOUT_EXPIRED_KHR			0x30F5
-#define EGL_CONDITION_SATISFIED_KHR		0x30F6
-#define EGL_SYNC_TYPE_KHR			0x30F7
-#define EGL_SYNC_REUSABLE_KHR			0x30FA
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR		0x0001	/* eglClientWaitSyncKHR <flags> bitfield */
-#define EGL_FOREVER_KHR				0xFFFFFFFFFFFFFFFFull
-#define EGL_NO_SYNC_KHR				EGL_CAST(EGLSyncKHR, 0)
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR             0x30B0
+#define EGL_NO_IMAGE_KHR                  EGL_CAST(EGLImageKHR,0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
 #endif
-#endif
+#endif /* EGL_KHR_image */
 
 #ifndef EGL_KHR_image_base
 #define EGL_KHR_image_base 1
-/* Most interfaces defined by EGL_KHR_image_pixmap above */
-#define EGL_IMAGE_PRESERVED_KHR			0x30D2	/* eglCreateImageKHR attribute */
-#endif
+#define EGL_IMAGE_PRESERVED_KHR           0x30D2
+#endif /* EGL_KHR_image_base */
 
 #ifndef EGL_KHR_image_pixmap
 #define EGL_KHR_image_pixmap 1
-/* Interfaces defined by EGL_KHR_image above */
-#endif
+#endif /* EGL_KHR_image_pixmap */
 
-#ifndef EGL_IMG_context_priority
-#define EGL_IMG_context_priority 1
-#define EGL_CONTEXT_PRIORITY_LEVEL_IMG		0x3100
-#define EGL_CONTEXT_PRIORITY_HIGH_IMG		0x3101
-#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG		0x3102
-#define EGL_CONTEXT_PRIORITY_LOW_IMG		0x3103
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR          0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR         0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR          0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR        0x0100
+#define EGL_MATCH_FORMAT_KHR              0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR      0x30C0
+#define EGL_FORMAT_RGB_565_KHR            0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR    0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR          0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR       0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR           0x30C5
+#define EGL_BITMAP_POINTER_KHR            0x30C6
+#define EGL_BITMAP_PITCH_KHR              0x30C7
+#define EGL_BITMAP_ORIGIN_KHR             0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR   0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR  0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR                0x30CE
+#define EGL_UPPER_LEFT_KHR                0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
 #endif
+#endif /* EGL_KHR_lock_surface */
 
 #ifndef EGL_KHR_lock_surface2
 #define EGL_KHR_lock_surface2 1
-#define EGL_BITMAP_PIXEL_SIZE_KHR		0x3110
+#define EGL_BITMAP_PIXEL_SIZE_KHR         0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
 #endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_mutable_render_buffer
+#define EGL_KHR_mutable_render_buffer 1
+#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#endif /* EGL_KHR_mutable_render_buffer */
+
+#ifndef EGL_KHR_no_config_context
+#define EGL_KHR_no_config_context 1
+#define EGL_NO_CONFIG_KHR                 EGL_CAST(EGLConfig,0)
+#endif /* EGL_KHR_no_config_context */
 
 #ifndef EGL_KHR_partial_update
 #define EGL_KHR_partial_update 1
@@ -192,274 +285,161 @@
 #endif
 #endif /* EGL_KHR_partial_update */
 
-#ifndef EGL_NV_coverage_sample
-#define EGL_NV_coverage_sample 1
-#define EGL_COVERAGE_BUFFERS_NV			0x30E0
-#define EGL_COVERAGE_SAMPLES_NV			0x30E1
-#endif
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR          0x3141
+#endif /* EGL_KHR_platform_android */
 
-#ifndef EGL_NV_depth_nonlinear
-#define EGL_NV_depth_nonlinear 1
-#define EGL_DEPTH_ENCODING_NV			0x30E2
-#define EGL_DEPTH_ENCODING_NONE_NV 0
-#define EGL_DEPTH_ENCODING_NONLINEAR_NV		0x30E3
-#endif
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR              0x31D7
+#endif /* EGL_KHR_platform_gbm */
 
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeNV requires 64-bit uint support */
-#ifndef EGL_NV_sync
-#define EGL_NV_sync 1
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV	0x30E6
-#define EGL_SYNC_STATUS_NV			0x30E7
-#define EGL_SIGNALED_NV				0x30E8
-#define EGL_UNSIGNALED_NV			0x30E9
-#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV		0x0001
-#define EGL_FOREVER_NV				0xFFFFFFFFFFFFFFFFull
-#define EGL_ALREADY_SIGNALED_NV			0x30EA
-#define EGL_TIMEOUT_EXPIRED_NV			0x30EB
-#define EGL_CONDITION_SATISFIED_NV		0x30EC
-#define EGL_SYNC_TYPE_NV			0x30ED
-#define EGL_SYNC_CONDITION_NV			0x30EE
-#define EGL_SYNC_FENCE_NV			0x30EF
-#define EGL_NO_SYNC_NV				EGL_CAST(EGLSyncNV, 0)
-typedef void* EGLSyncNV;
-typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR          0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR       0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR               0x30F1
+#define EGL_SIGNALED_KHR                  0x30F2
+#define EGL_UNSIGNALED_KHR                0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR           0x30F5
+#define EGL_CONDITION_SATISFIED_KHR       0x30F6
+#define EGL_SYNC_TYPE_KHR                 0x30F7
+#define EGL_SYNC_REUSABLE_KHR             0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR   0x0001
+#define EGL_FOREVER_KHR                   0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR                   EGL_CAST(EGLSyncKHR,0)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
-EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
-EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
-typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
 #endif
-#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
 
-#if KHRONOS_SUPPORT_INT64   /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
-#ifndef EGL_KHR_fence_sync
-#define EGL_KHR_fence_sync 1
-/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
-#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR	0x30F0
-#define EGL_SYNC_CONDITION_KHR			0x30F8
-#define EGL_SYNC_FENCE_KHR			0x30F9
-#endif
-#endif
-
-#ifndef EGL_HI_clientpixmap
-#define EGL_HI_clientpixmap 1
-
-/* Surface Attribute */
-#define EGL_CLIENT_PIXMAP_POINTER_HI		0x8F74
-/*
- * Structure representing a client pixmap
- * (pixmap's data is in client-space memory).
- */
-struct EGLClientPixmapHI
-{
-	void*		pData;
-	EGLint		iWidth;
-	EGLint		iHeight;
-	EGLint		iStride;
-};
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
-#endif	/* EGL_HI_clientpixmap */
-
-#ifndef EGL_HI_colorformats
-#define EGL_HI_colorformats 1
-/* Config Attribute */
-#define EGL_COLOR_FORMAT_HI			0x8F70
-/* Color Formats */
-#define EGL_COLOR_RGB_HI			0x8F71
-#define EGL_COLOR_RGBA_HI			0x8F72
-#define EGL_COLOR_ARGB_HI			0x8F73
-#endif /* EGL_HI_colorformats */
-
-#ifndef EGL_MESA_drm_image
-#define EGL_MESA_drm_image 1
-#define EGL_DRM_BUFFER_FORMAT_MESA		0x31D0	    /* CreateDRMImageMESA attribute */
-#define EGL_DRM_BUFFER_USE_MESA			0x31D1	    /* CreateDRMImageMESA attribute */
-#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA	0x31D2	    /* EGL_IMAGE_FORMAT_MESA attribute value */
-#define EGL_DRM_BUFFER_MESA			0x31D3	    /* eglCreateImageKHR target */
-#define EGL_DRM_BUFFER_STRIDE_MESA		0x31D4
-#define EGL_DRM_BUFFER_USE_SCANOUT_MESA		0x00000001  /* EGL_DRM_BUFFER_USE_MESA bits */
-#define EGL_DRM_BUFFER_USE_SHARE_MESA		0x00000002  /* EGL_DRM_BUFFER_USE_MESA bits */
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
-#endif
-
-#ifndef EGL_NV_post_sub_buffer
-#define EGL_NV_post_sub_buffer 1
-#define EGL_POST_SUB_BUFFER_SUPPORTED_NV	0x30BE
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
-#endif
-
-#ifndef EGL_ANGLE_query_surface_pointer
-#define EGL_ANGLE_query_surface_pointer 1
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#endif
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
-#endif
-
-#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
-#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
-#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE	0x3200
-#endif
-
-#ifndef EGL_NV_coverage_sample_resolve
-#define EGL_NV_coverage_sample_resolve 1
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NV		0x3131
-#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV	0x3132
-#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV	0x3133
-#endif
-
-#if KHRONOS_SUPPORT_INT64   /* EGLuint64NV requires 64-bit uint support */
-#ifndef EGL_NV_system_time
-#define EGL_NV_system_time 1
-typedef khronos_utime_nanoseconds_t EGLuint64NV;
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
-EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
-typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
-#endif
-#endif
-
-#if KHRONOS_SUPPORT_INT64 /* EGLuint64KHR requires 64-bit uint support */
 #ifndef EGL_KHR_stream
 #define EGL_KHR_stream 1
-typedef void* EGLStreamKHR;
+typedef void *EGLStreamKHR;
 typedef khronos_uint64_t EGLuint64KHR;
-#define EGL_NO_STREAM_KHR			EGL_CAST(EGLStreamKHR, 0)
-#define EGL_CONSUMER_LATENCY_USEC_KHR		0x3210
-#define EGL_PRODUCER_FRAME_KHR			0x3212
-#define EGL_CONSUMER_FRAME_KHR			0x3213
-#define EGL_STREAM_STATE_KHR			0x3214
-#define EGL_STREAM_STATE_CREATED_KHR		0x3215
-#define EGL_STREAM_STATE_CONNECTING_KHR		0x3216
-#define EGL_STREAM_STATE_EMPTY_KHR		0x3217
-#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR    0x3218
-#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR    0x3219
-#define EGL_STREAM_STATE_DISCONNECTED_KHR	0x321A
-#define EGL_BAD_STREAM_KHR			0x321B
-#define EGL_BAD_STATE_KHR			0x321C
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR                 EGL_CAST(EGLStreamKHR,0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR     0x3210
+#define EGL_PRODUCER_FRAME_KHR            0x3212
+#define EGL_CONSUMER_FRAME_KHR            0x3213
+#define EGL_STREAM_STATE_KHR              0x3214
+#define EGL_STREAM_STATE_CREATED_KHR      0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR   0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR        0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR                0x321B
+#define EGL_BAD_STATE_KHR                 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC)(EGLDisplay dpy, const EGLint *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
 #endif
-#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
 
-#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_attrib
+#define EGL_KHR_stream_attrib 1
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBKHRPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribKHR (EGLDisplay dpy, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream_attrib */
+
 #ifndef EGL_KHR_stream_consumer_gltexture
 #define EGL_KHR_stream_consumer_gltexture 1
-#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR	0x321E
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
 #endif
-#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
 
-#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
-#ifndef EGL_KHR_stream_producer_eglsurface
-#define EGL_KHR_stream_producer_eglsurface 1
-#define EGL_STREAM_BIT_KHR			0x0800
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR        EGL_CAST(EGLNativeFileDescriptorKHR,-1)
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
 #endif
-#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
 
-#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
-#ifndef EGL_KHR_stream_producer_aldatalocator
-#define EGL_KHR_stream_producer_aldatalocator 1
-#endif
-#endif
-
-#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
 #ifndef EGL_KHR_stream_fifo
 #define EGL_KHR_stream_fifo 1
-/* reuse EGLTimeKHR */
-#define EGL_STREAM_FIFO_LENGTH_KHR		0x31FC
-#define EGL_STREAM_TIME_NOW_KHR			0x31FD
-#define EGL_STREAM_TIME_CONSUMER_KHR		0x31FE
-#define EGL_STREAM_TIME_PRODUCER_KHR		0x31FF
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR        0x31FC
+#define EGL_STREAM_TIME_NOW_KHR           0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR      0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR      0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
 #endif
-#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
 
-#ifndef EGL_EXT_create_context_robustness
-#define EGL_EXT_create_context_robustness 1
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT	0x30BF
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
-#define EGL_NO_RESET_NOTIFICATION_EXT		0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET_EXT		0x31BF
-#endif
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
 
-#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
-#define EGL_ANGLE_d3d_share_handle_client_buffer 1
-/* reuse EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE */
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR                0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
 #endif
-
-#ifndef EGL_KHR_create_context
-#define EGL_KHR_create_context 1
-#define EGL_CONTEXT_MAJOR_VERSION_KHR			    EGL_CONTEXT_CLIENT_VERSION
-#define EGL_CONTEXT_MINOR_VERSION_KHR			    0x30FB
-#define EGL_CONTEXT_FLAGS_KHR				    0x30FC
-#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR		    0x30FD
-#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR  0x31BD
-#define EGL_NO_RESET_NOTIFICATION_KHR			    0x31BE
-#define EGL_LOSE_CONTEXT_ON_RESET_KHR			    0x31BF
-#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR		    0x00000001
-#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR	    0x00000002
-#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR	    0x00000004
-#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR		    0x00000001
-#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR    0x00000002
-#define EGL_OPENGL_ES3_BIT_KHR				    0x00000040
-#endif
-
-#ifndef EGL_KHR_create_context_no_error
-#define EGL_KHR_create_context_no_error 1
-#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR   0x31B3
-#endif /* EGL_KHR_create_context_no_error */
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
 
 #ifndef EGL_KHR_surfaceless_context
 #define EGL_KHR_surfaceless_context 1
-/* No tokens/entry points, just relaxes an error condition */
-#endif
+#endif /* EGL_KHR_surfaceless_context */
 
 #ifndef EGL_KHR_swap_buffers_with_damage
 #define EGL_KHR_swap_buffers_with_damage 1
@@ -469,162 +449,91 @@
 #endif
 #endif /* EGL_KHR_swap_buffers_with_damage */
 
-#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
-#ifndef EGL_KHR_stream_cross_process_fd
-#define EGL_KHR_stream_cross_process_fd 1
-typedef int EGLNativeFileDescriptorKHR;
-#define EGL_NO_FILE_DESCRIPTOR_KHR		EGL_CAST(EGLNativeFileDescriptorKHR, -1)
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR(EGLDisplay dpy, EGLStreamKHR stream);
-EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
-typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
-#endif
-#endif
-
-#ifndef EGL_EXT_multiview_window
-#define EGL_EXT_multiview_window 1
-#define EGL_MULTIVIEW_VIEW_COUNT_EXT		0x3134
-#endif
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR           0x30BA
+#endif /* EGL_KHR_vg_parent_image */
 
 #ifndef EGL_KHR_wait_sync
 #define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
 #endif
-
-#ifndef EGL_NV_post_convert_rounding
-#define EGL_NV_post_convert_rounding 1
-/* No tokens or entry points, just relaxes behavior of SwapBuffers */
-#endif
-
-#ifndef EGL_NV_native_query
-#define EGL_NV_native_query 1
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV( EGLDisplay dpy, EGLNativeDisplayType* display_id);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV( EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType* window);
-EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV( EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType* pixmap);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC)(EGLDisplay dpy, EGLNativeDisplayType *display_id);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
-#endif
-
-#ifndef EGL_NV_3dvision_surface
-#define EGL_NV_3dvision_surface 1
-#define EGL_AUTO_STEREO_NV			0x3136
-#endif
-
-#ifndef EGL_ANDROID_framebuffer_target
-#define EGL_ANDROID_framebuffer_target 1
-#define EGL_FRAMEBUFFER_TARGET_ANDROID		0x3147
-#endif
-
-#ifndef EGL_ANDROID_image_crop
-#define EGL_ANDROID_image_crop 1
-#define EGL_IMAGE_CROP_LEFT_ANDROID   0x3148
-#define EGL_IMAGE_CROP_TOP_ANDROID    0x3149
-#define EGL_IMAGE_CROP_RIGHT_ANDROID  0x314A
-#define EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B
-#endif
+#endif /* EGL_KHR_wait_sync */
 
 #ifndef EGL_ANDROID_blob_cache
 #define EGL_ANDROID_blob_cache 1
 typedef khronos_ssize_t EGLsizeiANDROID;
 typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
 typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC)(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
 #endif
+#endif /* EGL_ANDROID_blob_cache */
 
-#ifndef EGL_ANDROID_image_native_buffer
-#define EGL_ANDROID_image_native_buffer 1
-#define EGL_NATIVE_BUFFER_ANDROID		0x3140
-#endif
-
-#ifndef EGL_ANDROID_native_fence_sync
-#define EGL_ANDROID_native_fence_sync 1
-#define EGL_SYNC_NATIVE_FENCE_ANDROID		0x3144
-#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID	0x3145
-#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID	0x3146
-#define EGL_NO_NATIVE_FENCE_FD_ANDROID		(-1)
+#ifndef EGL_ANDROID_create_native_client_buffer
+#define EGL_ANDROID_create_native_client_buffer 1
+#define EGL_NATIVE_BUFFER_USAGE_ANDROID   0x3143
+#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list);
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID( EGLDisplay dpy, EGLSyncKHR);
-#endif /* EGL_EGLEXT_PROTOTYPES */
-typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC)(EGLDisplay dpy, EGLSyncKHR);
+EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
 #endif
+#endif /* EGL_ANDROID_create_native_client_buffer */
 
-#ifndef EGL_ANDROID_recordable
-#define EGL_ANDROID_recordable 1
-#define EGL_RECORDABLE_ANDROID			0x3142
-#endif
-
-#ifndef EGL_EXT_buffer_age
-#define EGL_EXT_buffer_age 1
-#define EGL_BUFFER_AGE_EXT			0x313D
-#endif
-
-#ifndef EGL_EXT_image_dma_buf_import
-#define EGL_EXT_image_dma_buf_import 1
-#define EGL_LINUX_DMA_BUF_EXT			0x3270
-#define EGL_LINUX_DRM_FOURCC_EXT		0x3271
-#define EGL_DMA_BUF_PLANE0_FD_EXT		0x3272
-#define EGL_DMA_BUF_PLANE0_OFFSET_EXT		0x3273
-#define EGL_DMA_BUF_PLANE0_PITCH_EXT		0x3274
-#define EGL_DMA_BUF_PLANE1_FD_EXT		0x3275
-#define EGL_DMA_BUF_PLANE1_OFFSET_EXT		0x3276
-#define EGL_DMA_BUF_PLANE1_PITCH_EXT		0x3277
-#define EGL_DMA_BUF_PLANE2_FD_EXT		0x3278
-#define EGL_DMA_BUF_PLANE2_OFFSET_EXT		0x3279
-#define EGL_DMA_BUF_PLANE2_PITCH_EXT		0x327A
-#define EGL_YUV_COLOR_SPACE_HINT_EXT		0x327B
-#define EGL_SAMPLE_RANGE_HINT_EXT		0x327C
-#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
-#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
-#define EGL_ITU_REC601_EXT			0x327F
-#define EGL_ITU_REC709_EXT			0x3280
-#define EGL_ITU_REC2020_EXT			0x3281
-#define EGL_YUV_FULL_RANGE_EXT			0x3282
-#define EGL_YUV_NARROW_RANGE_EXT		0x3283
-#define EGL_YUV_CHROMA_SITING_0_EXT		0x3284
-#define EGL_YUV_CHROMA_SITING_0_5_EXT		0x3285
-#endif
-
-#ifndef EGL_ANDROID_presentation_time
-#define EGL_ANDROID_presentation_time 1
-typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time);
-#else
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROID) (EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time);
-#endif
-#endif
-
-#ifndef EGL_ANDROID_get_native_client_buffer
-#define EGL_ANDROID_get_native_client_buffer 1
-struct AHardwareBuffer;
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
-#else
-typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);
-#endif
-#endif
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID    0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
 
 #ifndef EGL_ANDROID_front_buffer_auto_refresh
 #define EGL_ANDROID_front_buffer_auto_refresh 1
 #define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#endif /* EGL_ANDROID_front_buffer_auto_refresh */
+
+#ifndef EGL_ANDROID_image_crop
+#define EGL_ANDROID_image_crop 1
+#define EGL_IMAGE_CROP_LEFT_ANDROID       0x3148
+#define EGL_IMAGE_CROP_TOP_ANDROID        0x3149
+#define EGL_IMAGE_CROP_RIGHT_ANDROID      0x314A
+#define EGL_IMAGE_CROP_BOTTOM_ANDROID     0x314B
 #endif
 
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID         0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
 #ifndef EGL_KHR_mutable_render_buffer
 #define EGL_KHR_mutable_render_buffer 1
 #define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
 #endif
 
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID     0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID  0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID    -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_presentation_time
+#define EGL_ANDROID_presentation_time 1
+typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPresentationTimeANDROID (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#endif
+#endif /* EGL_ANDROID_presentation_time */
+
 #ifndef EGL_ANDROID_get_frame_timestamps
 #define EGL_ANDROID_get_frame_timestamps 1
 #define EGL_TIMESTAMPS_ANDROID 0x3430
@@ -657,6 +566,131 @@
 #endif
 #endif
 
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID            0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE             0x33A0
+#define EGL_D3D11_DEVICE_ANGLE            0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE              0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ARM_implicit_external_sync
+#define EGL_ARM_implicit_external_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif /* EGL_ARM_implicit_external_sync */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM           0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_bind_to_front
+#define EGL_EXT_bind_to_front 1
+#define EGL_FRONT_BUFFER_EXT              0x3464
+#endif /* EGL_EXT_bind_to_front */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT                0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_compositor
+#define EGL_EXT_compositor 1
+#define EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460
+#define EGL_EXTERNAL_REF_ID_EXT           0x3461
+#define EGL_COMPOSITOR_DROP_NEWEST_FRAME_EXT 0x3462
+#define EGL_COMPOSITOR_KEEP_NEWEST_FRAME_EXT 0x3463
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTLISTEXTPROC) (const EGLint *external_ref_ids, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTATTRIBUTESEXTPROC) (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWLISTEXTPROC) (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWATTRIBUTESEXTPROC) (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORBINDTEXWINDOWEXTPROC) (EGLint external_win_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETSIZEEXTPROC) (EGLint external_win_id, EGLint width, EGLint height);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSWAPPOLICYEXTPROC) (EGLint external_win_id, EGLint policy);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextListEXT (const EGLint *external_ref_ids, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextAttributesEXT (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowListEXT (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowAttributesEXT (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorBindTexWindowEXT (EGLint external_win_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetSizeEXT (EGLint external_win_id, EGLint width, EGLint height);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSwapPolicyEXT (EGLint external_win_id, EGLint policy);
+#endif
+#endif /* EGL_EXT_compositor */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT     0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT     0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT                 EGL_CAST(EGLDeviceEXT,0)
+#define EGL_BAD_DEVICE_EXT                0x322B
+#define EGL_DEVICE_EXT                    0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_device_drm
+#define EGL_EXT_device_drm 1
+#define EGL_DRM_DEVICE_FILE_EXT           0x3233
+#endif /* EGL_EXT_device_drm */
+
+#ifndef EGL_EXT_device_enumeration
+#define EGL_EXT_device_enumeration 1
+#endif /* EGL_EXT_device_enumeration */
+
+#ifndef EGL_EXT_device_openwf
+#define EGL_EXT_device_openwf 1
+#define EGL_OPENWF_DEVICE_ID_EXT          0x3237
+#endif /* EGL_EXT_device_openwf */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
 #ifndef EGL_EXT_gl_colorspace_bt2020_linear
 #define EGL_EXT_gl_colorspace_bt2020_linear 1
 #define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F
@@ -667,11 +701,127 @@
 #define EGL_GL_COLORSPACE_BT2020_PQ_EXT   0x3340
 #endif /* EGL_EXT_gl_colorspace_bt2020_pq */
 
+#ifndef EGL_EXT_gl_colorspace_display_p3
+#define EGL_EXT_gl_colorspace_display_p3 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT  0x3363
+#endif /* EGL_EXT_gl_colorspace_display_p3 */
+
+#ifndef EGL_EXT_gl_colorspace_display_p3_linear
+#define EGL_EXT_gl_colorspace_display_p3_linear 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
+#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
+
+#ifndef EGL_EXT_gl_colorspace_scrgb
+#define EGL_EXT_gl_colorspace_scrgb 1
+#define EGL_GL_COLORSPACE_SCRGB_EXT       0x3351
+#endif /* EGL_EXT_gl_colorspace_scrgb */
+
 #ifndef EGL_EXT_gl_colorspace_scrgb_linear
 #define EGL_EXT_gl_colorspace_scrgb_linear 1
 #define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
 #endif /* EGL_EXT_gl_colorspace_scrgb_linear */
 
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT             0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT          0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT         0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT     0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT      0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT         0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT     0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT      0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT         0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT     0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT      0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT      0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT         0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT                0x327F
+#define EGL_ITU_REC709_EXT                0x3280
+#define EGL_ITU_REC2020_EXT               0x3281
+#define EGL_YUV_FULL_RANGE_EXT            0x3282
+#define EGL_YUV_NARROW_RANGE_EXT          0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT       0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT     0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_image_dma_buf_import_modifiers
+#define EGL_EXT_image_dma_buf_import_modifiers 1
+#define EGL_DMA_BUF_PLANE3_FD_EXT         0x3440
+#define EGL_DMA_BUF_PLANE3_OFFSET_EXT     0x3441
+#define EGL_DMA_BUF_PLANE3_PITCH_EXT      0x3442
+#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufFormatsEXT (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufModifiersEXT (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#endif
+#endif /* EGL_EXT_image_dma_buf_import_modifiers */
+
+#ifndef EGL_EXT_image_implicit_sync_control
+#define EGL_EXT_image_implicit_sync_control 1
+#define EGL_IMPORT_SYNC_TYPE_EXT          0x3470
+#define EGL_IMPORT_IMPLICIT_SYNC_EXT      0x3471
+#define EGL_IMPORT_EXPLICIT_SYNC_EXT      0x3472
+#endif /* EGL_EXT_image_implicit_sync_control */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT      0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_output_base
+#define EGL_EXT_output_base 1
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT           EGL_CAST(EGLOutputLayerEXT,0)
+#define EGL_NO_OUTPUT_PORT_EXT            EGL_CAST(EGLOutputPortEXT,0)
+#define EGL_BAD_OUTPUT_LAYER_EXT          0x322D
+#define EGL_BAD_OUTPUT_PORT_EXT           0x322E
+#define EGL_SWAP_INTERVAL_EXT             0x322F
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+#endif /* EGL_EXT_output_base */
+
+#ifndef EGL_EXT_output_drm
+#define EGL_EXT_output_drm 1
+#define EGL_DRM_CRTC_EXT                  0x3234
+#define EGL_DRM_PLANE_EXT                 0x3235
+#define EGL_DRM_CONNECTOR_EXT             0x3236
+#endif /* EGL_EXT_output_drm */
+
+#ifndef EGL_EXT_output_openwf
+#define EGL_EXT_output_openwf 1
+#define EGL_OPENWF_PIPELINE_ID_EXT        0x3238
+#define EGL_OPENWF_PORT_ID_EXT            0x3239
+#endif /* EGL_EXT_output_openwf */
+
 #ifndef EGL_EXT_pixel_format_float
 #define EGL_EXT_pixel_format_float 1
 #define EGL_COLOR_COMPONENT_TYPE_EXT      0x3339
@@ -679,6 +829,57 @@
 #define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
 #endif /* EGL_EXT_pixel_format_float */
 
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT           0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT          0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT              0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT       0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_content
+#define EGL_EXT_protected_content 1
+#define EGL_PROTECTED_CONTENT_EXT         0x32C0
+#endif /* EGL_EXT_protected_content */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_stream_consumer_egloutput
+#define EGL_EXT_stream_consumer_egloutput 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+#endif /* EGL_EXT_stream_consumer_egloutput */
+
+#ifndef EGL_EXT_surface_CTA861_3_metadata
+#define EGL_EXT_surface_CTA861_3_metadata 1
+#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT 0x3360
+#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT 0x3361
+#endif /* EGL_EXT_surface_CTA861_3_metadata */
+
 #ifndef EGL_EXT_surface_SMPTE2086_metadata
 #define EGL_EXT_surface_SMPTE2086_metadata 1
 #define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341
@@ -694,8 +895,402 @@
 #define EGL_METADATA_SCALING_EXT          50000
 #endif /* EGL_EXT_surface_SMPTE2086_metadata */
 
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_EXT_yuv_surface
+#define EGL_EXT_yuv_surface 1
+#define EGL_YUV_ORDER_EXT                 0x3301
+#define EGL_YUV_NUMBER_OF_PLANES_EXT      0x3311
+#define EGL_YUV_SUBSAMPLE_EXT             0x3312
+#define EGL_YUV_DEPTH_RANGE_EXT           0x3317
+#define EGL_YUV_CSC_STANDARD_EXT          0x330A
+#define EGL_YUV_PLANE_BPP_EXT             0x331A
+#define EGL_YUV_BUFFER_EXT                0x3300
+#define EGL_YUV_ORDER_YUV_EXT             0x3302
+#define EGL_YUV_ORDER_YVU_EXT             0x3303
+#define EGL_YUV_ORDER_YUYV_EXT            0x3304
+#define EGL_YUV_ORDER_UYVY_EXT            0x3305
+#define EGL_YUV_ORDER_YVYU_EXT            0x3306
+#define EGL_YUV_ORDER_VYUY_EXT            0x3307
+#define EGL_YUV_ORDER_AYUV_EXT            0x3308
+#define EGL_YUV_SUBSAMPLE_4_2_0_EXT       0x3313
+#define EGL_YUV_SUBSAMPLE_4_2_2_EXT       0x3314
+#define EGL_YUV_SUBSAMPLE_4_4_4_EXT       0x3315
+#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT   0x3318
+#define EGL_YUV_DEPTH_RANGE_FULL_EXT      0x3319
+#define EGL_YUV_CSC_STANDARD_601_EXT      0x330B
+#define EGL_YUV_CSC_STANDARD_709_EXT      0x330C
+#define EGL_YUV_CSC_STANDARD_2020_EXT     0x330D
+#define EGL_YUV_PLANE_BPP_0_EXT           0x331B
+#define EGL_YUV_PLANE_BPP_8_EXT           0x331C
+#define EGL_YUV_PLANE_BPP_10_EXT          0x331D
+#endif /* EGL_EXT_yuv_surface */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+    void  *pData;
+    EGLint iWidth;
+    EGLint iHeight;
+    EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI      0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI               0x8F70
+#define EGL_COLOR_RGB_HI                  0x8F71
+#define EGL_COLOR_RGBA_HI                 0x8F72
+#define EGL_COLOR_ARGB_HI                 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG    0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG     0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG   0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG      0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_IMG_image_plane_attribs
+#define EGL_IMG_image_plane_attribs 1
+#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
+#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
+#endif /* EGL_IMG_image_plane_attribs */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA        0x31D0
+#define EGL_DRM_BUFFER_USE_MESA           0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA               0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA        0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA   0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA     0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_ANDROID_get_native_client_buffer
+#define EGL_ANDROID_get_native_client_buffer 1
+struct AHardwareBuffer;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
+#else
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);
+#endif
+#endif
+
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
+#endif /* EGL_MESA_image_dma_buf_export */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA             0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_MESA_platform_surfaceless
+#define EGL_MESA_platform_surfaceless 1
+#define EGL_PLATFORM_SURFACELESS_MESA     0x31DD
+#endif /* EGL_MESA_platform_surfaceless */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK                0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV                0x3136
+#endif /* EGL_NV_3dvision_surface */
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV           0x30E0
+#define EGL_COVERAGE_SAMPLES_NV           0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV    0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_cuda_event
+#define EGL_NV_cuda_event 1
+#define EGL_CUDA_EVENT_HANDLE_NV          0x323B
+#define EGL_SYNC_CUDA_EVENT_NV            0x323C
+#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV   0x323D
+#endif /* EGL_NV_cuda_event */
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV             0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV        0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV   0x30E3
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifndef EGL_NV_device_cuda
+#define EGL_NV_device_cuda 1
+#define EGL_CUDA_DEVICE_NV                0x323A
+#endif /* EGL_NV_device_cuda */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV  0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_robustness_video_memory_purge
+#define EGL_NV_robustness_video_memory_purge 1
+#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
+#endif /* EGL_NV_robustness_video_memory_purge */
+
+#ifndef EGL_NV_stream_consumer_gltexture_yuv
+#define EGL_NV_stream_consumer_gltexture_yuv 1
+#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV    0x332C
+#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV    0x332D
+#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV    0x332E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_NV_stream_consumer_gltexture_yuv */
+
+#ifndef EGL_NV_stream_cross_display
+#define EGL_NV_stream_cross_display 1
+#define EGL_STREAM_CROSS_DISPLAY_NV       0x334E
+#endif /* EGL_NV_stream_cross_display */
+
+#ifndef EGL_NV_stream_cross_object
+#define EGL_NV_stream_cross_object 1
+#define EGL_STREAM_CROSS_OBJECT_NV        0x334D
+#endif /* EGL_NV_stream_cross_object */
+
+#ifndef EGL_NV_stream_cross_partition
+#define EGL_NV_stream_cross_partition 1
+#define EGL_STREAM_CROSS_PARTITION_NV     0x323F
+#endif /* EGL_NV_stream_cross_partition */
+
+#ifndef EGL_NV_stream_cross_process
+#define EGL_NV_stream_cross_process 1
+#define EGL_STREAM_CROSS_PROCESS_NV       0x3245
+#endif /* EGL_NV_stream_cross_process */
+
+#ifndef EGL_NV_stream_cross_system
+#define EGL_NV_stream_cross_system 1
+#define EGL_STREAM_CROSS_SYSTEM_NV        0x334F
+#endif /* EGL_NV_stream_cross_system */
+
+#ifndef EGL_NV_stream_fifo_next
+#define EGL_NV_stream_fifo_next 1
+#define EGL_PENDING_FRAME_NV              0x3329
+#define EGL_STREAM_TIME_PENDING_NV        0x332A
+#endif /* EGL_NV_stream_fifo_next */
+
+#ifndef EGL_NV_stream_fifo_synchronous
+#define EGL_NV_stream_fifo_synchronous 1
+#define EGL_STREAM_FIFO_SYNCHRONOUS_NV    0x3336
+#endif /* EGL_NV_stream_fifo_synchronous */
+
+#ifndef EGL_NV_stream_frame_limits
+#define EGL_NV_stream_frame_limits 1
+#define EGL_PRODUCER_MAX_FRAME_HINT_NV    0x3337
+#define EGL_CONSUMER_MAX_FRAME_HINT_NV    0x3338
+#endif /* EGL_NV_stream_frame_limits */
+
+#ifndef EGL_NV_stream_metadata
+#define EGL_NV_stream_metadata 1
+#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
+#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
+#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
+#define EGL_PRODUCER_METADATA_NV          0x3253
+#define EGL_CONSUMER_METADATA_NV          0x3254
+#define EGL_PENDING_METADATA_NV           0x3328
+#define EGL_METADATA0_SIZE_NV             0x3255
+#define EGL_METADATA1_SIZE_NV             0x3256
+#define EGL_METADATA2_SIZE_NV             0x3257
+#define EGL_METADATA3_SIZE_NV             0x3258
+#define EGL_METADATA0_TYPE_NV             0x3259
+#define EGL_METADATA1_TYPE_NV             0x325A
+#define EGL_METADATA2_TYPE_NV             0x325B
+#define EGL_METADATA3_TYPE_NV             0x325C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#endif
+#endif /* EGL_NV_stream_metadata */
+
+#ifndef EGL_NV_stream_remote
+#define EGL_NV_stream_remote 1
+#define EGL_STREAM_STATE_INITIALIZING_NV  0x3240
+#define EGL_STREAM_TYPE_NV                0x3241
+#define EGL_STREAM_PROTOCOL_NV            0x3242
+#define EGL_STREAM_ENDPOINT_NV            0x3243
+#define EGL_STREAM_LOCAL_NV               0x3244
+#define EGL_STREAM_PRODUCER_NV            0x3247
+#define EGL_STREAM_CONSUMER_NV            0x3248
+#define EGL_STREAM_PROTOCOL_FD_NV         0x3246
+#endif /* EGL_NV_stream_remote */
+
+#ifndef EGL_NV_stream_reset
+#define EGL_NV_stream_reset 1
+#define EGL_SUPPORT_RESET_NV              0x3334
+#define EGL_SUPPORT_REUSE_NV              0x3335
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLRESETSTREAMNVPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglResetStreamNV (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_NV_stream_reset */
+
+#ifndef EGL_NV_stream_socket
+#define EGL_NV_stream_socket 1
+#define EGL_STREAM_PROTOCOL_SOCKET_NV     0x324B
+#define EGL_SOCKET_HANDLE_NV              0x324C
+#define EGL_SOCKET_TYPE_NV                0x324D
+#endif /* EGL_NV_stream_socket */
+
+#ifndef EGL_NV_stream_socket_inet
+#define EGL_NV_stream_socket_inet 1
+#define EGL_SOCKET_TYPE_INET_NV           0x324F
+#endif /* EGL_NV_stream_socket_inet */
+
+#ifndef EGL_NV_stream_socket_unix
+#define EGL_NV_stream_socket_unix 1
+#define EGL_SOCKET_TYPE_UNIX_NV           0x324E
+#endif /* EGL_NV_stream_socket_unix */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV             0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+typedef void *EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV                0x30E7
+#define EGL_SIGNALED_NV                   0x30E8
+#define EGL_UNSIGNALED_NV                 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV    0x0001
+#define EGL_FOREVER_NV                    0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV           0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV            0x30EB
+#define EGL_CONDITION_SATISFIED_NV        0x30EC
+#define EGL_SYNC_TYPE_NV                  0x30ED
+#define EGL_SYNC_CONDITION_NV             0x30EE
+#define EGL_SYNC_FENCE_NV                 0x30EF
+#define EGL_NO_SYNC_NV                    EGL_CAST(EGLSyncNV,0)
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
+
+#ifndef EGL_TIZEN_image_native_buffer
+#define EGL_TIZEN_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_TIZEN           0x32A0
+#endif /* EGL_TIZEN_image_native_buffer */
+
+#ifndef EGL_TIZEN_image_native_surface
+#define EGL_TIZEN_image_native_surface 1
+#define EGL_NATIVE_SURFACE_TIZEN          0x32A1
+#endif /* EGL_TIZEN_image_native_surface */
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __eglext_h_ */
+#endif
diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h
index 54011c8..c77c333 100644
--- a/opengl/include/EGL/eglplatform.h
+++ b/opengl/include/EGL/eglplatform.h
@@ -2,7 +2,7 @@
 #define __eglplatform_h_
 
 /*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2007-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
@@ -25,7 +25,7 @@
 */
 
 /* Platform-specific types and definitions for egl.h
- * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+ * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
  *
  * Adopters may modify khrplatform.h and this file to suit their platform.
  * You are encouraged to submit all modifications to the Khronos group so that
@@ -77,7 +77,7 @@
 typedef HBITMAP EGLNativePixmapType;
 typedef HWND    EGLNativeWindowType;
 
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
+#elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
 
 typedef int   EGLNativeDisplayType;
 typedef void *EGLNativeWindowType;
@@ -121,6 +121,8 @@
  */
 typedef khronos_int32_t EGLint;
 
+
+/* C++ / C typecast macros for special EGL handle values */
 #if defined(__cplusplus)
 #define EGL_CAST(type, value) (static_cast<type>(value))
 #else
diff --git a/opengl/include/GLES/NOTICE b/opengl/include/GLES/NOTICE
index 4dc6614..710388f 100644
--- a/opengl/include/GLES/NOTICE
+++ b/opengl/include/GLES/NOTICE
@@ -1,2 +1,35 @@
-This document is licensed under the SGI Free Software B License Version 2.0.
-For details, see http://oss.sgi.com/projects/FreeB/ .
+Copyright (c) 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.
+
+Copyright (c) 2013-2017 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.
+
diff --git a/opengl/include/GLES/egl.h b/opengl/include/GLES/egl.h
index 5778e00..86f644c 100644
--- a/opengl/include/GLES/egl.h
+++ b/opengl/include/GLES/egl.h
@@ -1,9 +1,23 @@
 /*
+** Copyright (c) 2008-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.
+*/
+
+/*
  * Skeleton egl.h to provide compatibility for early GLES 1.0
  * applications. Several early implementations included gl.h
  * in egl.h leading applications to include only egl.h
- *
- * $Revision: 6252 $ on $Date:: 2008-08-06 16:35:08 -0700 #$
  */
 
 #ifndef __legacy_egl_h_
diff --git a/opengl/include/GLES/gl.h b/opengl/include/GLES/gl.h
index 5b8d85a..36acff9 100644
--- a/opengl/include/GLES/gl.h
+++ b/opengl/include/GLES/gl.h
@@ -1,58 +1,81 @@
 #ifndef __gl_h_
-#define __gl_h_
-
-/* $Revision: 10601 $ on $Date:: 2010-03-04 22:15:27 -0800 #$ */
-
-#include <GLES/glplatform.h>
+#define __gl_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+** Copyright (c) 2013-2017 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 OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   https://github.com/KhronosGroup/OpenGL-Registry
+*/
+
+#include <GLES/glplatform.h>
+
+/* Generated on date 20170613 */
+
+/* Generated C header for:
+ * API: gles1
+ * Profile: common
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: ^(GL_OES_read_format|GL_OES_compressed_paletted_texture|GL_OES_point_size_array|GL_OES_point_sprite)$
+ * Extensions removed: _nomatch_^
  */
 
-typedef void             GLvoid;
-typedef char             GLchar;
-typedef unsigned int     GLenum;
-typedef unsigned char    GLboolean;
-typedef unsigned int     GLbitfield;
-typedef khronos_int8_t   GLbyte;
-typedef short            GLshort;
-typedef int              GLint;
-typedef int              GLsizei;
-typedef khronos_uint8_t  GLubyte;
-typedef unsigned short   GLushort;
-typedef unsigned int     GLuint;
-typedef khronos_float_t  GLfloat;
-typedef khronos_float_t  GLclampf;
-typedef khronos_int32_t  GLfixed;
-typedef khronos_int32_t  GLclampx;
-
+#ifndef GL_VERSION_ES_CM_1_0
+#define GL_VERSION_ES_CM_1_0 1
+typedef void GLvoid;
+typedef unsigned int GLenum;
+#include <KHR/khrplatform.h>
+typedef khronos_float_t GLfloat;
+typedef khronos_int32_t GLfixed;
+typedef unsigned int GLuint;
+typedef khronos_ssize_t GLsizeiptr;
 typedef khronos_intptr_t GLintptr;
-typedef khronos_ssize_t  GLsizeiptr;
-
-
-/*************************************************************/
-
-/* OpenGL ES core versions */
-#define GL_VERSION_ES_CM_1_0          1
-#define GL_VERSION_ES_CL_1_0          1
-#define GL_VERSION_ES_CM_1_1          1
-#define GL_VERSION_ES_CL_1_1          1
-
-/* ClearBufferMask */
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned short GLushort;
+typedef short GLshort;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLclampx;
+#define GL_VERSION_ES_CL_1_0              1
+#define GL_VERSION_ES_CM_1_1              1
+#define GL_VERSION_ES_CL_1_1              1
 #define GL_DEPTH_BUFFER_BIT               0x00000100
 #define GL_STENCIL_BUFFER_BIT             0x00000400
 #define GL_COLOR_BUFFER_BIT               0x00004000
-
-/* Boolean */
 #define GL_FALSE                          0
 #define GL_TRUE                           1
-
-/* BeginMode */
 #define GL_POINTS                         0x0000
 #define GL_LINES                          0x0001
 #define GL_LINE_LOOP                      0x0002
@@ -60,8 +83,6 @@
 #define GL_TRIANGLES                      0x0004
 #define GL_TRIANGLE_STRIP                 0x0005
 #define GL_TRIANGLE_FAN                   0x0006
-
-/* AlphaFunction */
 #define GL_NEVER                          0x0200
 #define GL_LESS                           0x0201
 #define GL_EQUAL                          0x0202
@@ -70,8 +91,6 @@
 #define GL_NOTEQUAL                       0x0205
 #define GL_GEQUAL                         0x0206
 #define GL_ALWAYS                         0x0207
-
-/* BlendingFactorDest */
 #define GL_ZERO                           0
 #define GL_ONE                            1
 #define GL_SRC_COLOR                      0x0300
@@ -80,53 +99,18 @@
 #define GL_ONE_MINUS_SRC_ALPHA            0x0303
 #define GL_DST_ALPHA                      0x0304
 #define GL_ONE_MINUS_DST_ALPHA            0x0305
-
-/* BlendingFactorSrc */
-/*      GL_ZERO */
-/*      GL_ONE */
 #define GL_DST_COLOR                      0x0306
 #define GL_ONE_MINUS_DST_COLOR            0x0307
 #define GL_SRC_ALPHA_SATURATE             0x0308
-/*      GL_SRC_ALPHA */
-/*      GL_ONE_MINUS_SRC_ALPHA */
-/*      GL_DST_ALPHA */
-/*      GL_ONE_MINUS_DST_ALPHA */
-
-/* ClipPlaneName */
 #define GL_CLIP_PLANE0                    0x3000
 #define GL_CLIP_PLANE1                    0x3001
 #define GL_CLIP_PLANE2                    0x3002
 #define GL_CLIP_PLANE3                    0x3003
 #define GL_CLIP_PLANE4                    0x3004
 #define GL_CLIP_PLANE5                    0x3005
-
-/* ColorMaterialFace */
-/*      GL_FRONT_AND_BACK */
-
-/* ColorMaterialParameter */
-/*      GL_AMBIENT_AND_DIFFUSE */
-
-/* ColorPointerType */
-/*      GL_UNSIGNED_BYTE */
-/*      GL_FLOAT */
-/*      GL_FIXED */
-
-/* CullFaceMode */
 #define GL_FRONT                          0x0404
 #define GL_BACK                           0x0405
 #define GL_FRONT_AND_BACK                 0x0408
-
-/* DepthFunction */
-/*      GL_NEVER */
-/*      GL_LESS */
-/*      GL_EQUAL */
-/*      GL_LEQUAL */
-/*      GL_GREATER */
-/*      GL_NOTEQUAL */
-/*      GL_GEQUAL */
-/*      GL_ALWAYS */
-
-/* EnableCap */
 #define GL_FOG                            0x0B60
 #define GL_LIGHTING                       0x0B50
 #define GL_TEXTURE_2D                     0x0DE1
@@ -137,21 +121,12 @@
 #define GL_DITHER                         0x0BD0
 #define GL_STENCIL_TEST                   0x0B90
 #define GL_DEPTH_TEST                     0x0B71
-/*      GL_LIGHT0 */
-/*      GL_LIGHT1 */
-/*      GL_LIGHT2 */
-/*      GL_LIGHT3 */
-/*      GL_LIGHT4 */
-/*      GL_LIGHT5 */
-/*      GL_LIGHT6 */
-/*      GL_LIGHT7 */
 #define GL_POINT_SMOOTH                   0x0B10
 #define GL_LINE_SMOOTH                    0x0B20
 #define GL_SCISSOR_TEST                   0x0C11
 #define GL_COLOR_MATERIAL                 0x0B57
 #define GL_NORMALIZE                      0x0BA1
 #define GL_RESCALE_NORMAL                 0x803A
-#define GL_POLYGON_OFFSET_FILL            0x8037
 #define GL_VERTEX_ARRAY                   0x8074
 #define GL_NORMAL_ARRAY                   0x8075
 #define GL_COLOR_ARRAY                    0x8076
@@ -160,8 +135,6 @@
 #define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
 #define GL_SAMPLE_ALPHA_TO_ONE            0x809F
 #define GL_SAMPLE_COVERAGE                0x80A0
-
-/* ErrorCode */
 #define GL_NO_ERROR                       0
 #define GL_INVALID_ENUM                   0x0500
 #define GL_INVALID_VALUE                  0x0501
@@ -169,24 +142,15 @@
 #define GL_STACK_OVERFLOW                 0x0503
 #define GL_STACK_UNDERFLOW                0x0504
 #define GL_OUT_OF_MEMORY                  0x0505
-
-/* FogMode */
-/*      GL_LINEAR */
 #define GL_EXP                            0x0800
 #define GL_EXP2                           0x0801
-
-/* FogParameter */
 #define GL_FOG_DENSITY                    0x0B62
 #define GL_FOG_START                      0x0B63
 #define GL_FOG_END                        0x0B64
 #define GL_FOG_MODE                       0x0B65
 #define GL_FOG_COLOR                      0x0B66
-
-/* FrontFaceDirection */
 #define GL_CW                             0x0900
 #define GL_CCW                            0x0901
-
-/* GetPName */
 #define GL_CURRENT_COLOR                  0x0B00
 #define GL_CURRENT_NORMAL                 0x0B02
 #define GL_CURRENT_TEXTURE_COORDS         0x0B03
@@ -229,11 +193,8 @@
 #define GL_BLEND_SRC                      0x0BE1
 #define GL_LOGIC_OP_MODE                  0x0BF0
 #define GL_SCISSOR_BOX                    0x0C10
-#define GL_SCISSOR_TEST                   0x0C11
 #define GL_COLOR_CLEAR_VALUE              0x0C22
 #define GL_COLOR_WRITEMASK                0x0C23
-#define GL_UNPACK_ALIGNMENT               0x0CF5
-#define GL_PACK_ALIGNMENT                 0x0D05
 #define GL_MAX_LIGHTS                     0x0D31
 #define GL_MAX_CLIP_PLANES                0x0D32
 #define GL_MAX_TEXTURE_SIZE               0x0D33
@@ -272,33 +233,18 @@
 #define GL_SAMPLES                        0x80A9
 #define GL_SAMPLE_COVERAGE_VALUE          0x80AA
 #define GL_SAMPLE_COVERAGE_INVERT         0x80AB
-
-/* GetTextureParameter */
-/*      GL_TEXTURE_MAG_FILTER */
-/*      GL_TEXTURE_MIN_FILTER */
-/*      GL_TEXTURE_WRAP_S */
-/*      GL_TEXTURE_WRAP_T */
-
 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
 #define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
-
-/* HintMode */
 #define GL_DONT_CARE                      0x1100
 #define GL_FASTEST                        0x1101
 #define GL_NICEST                         0x1102
-
-/* HintTarget */
 #define GL_PERSPECTIVE_CORRECTION_HINT    0x0C50
 #define GL_POINT_SMOOTH_HINT              0x0C51
 #define GL_LINE_SMOOTH_HINT               0x0C52
 #define GL_FOG_HINT                       0x0C54
 #define GL_GENERATE_MIPMAP_HINT           0x8192
-
-/* LightModelParameter */
 #define GL_LIGHT_MODEL_AMBIENT            0x0B53
 #define GL_LIGHT_MODEL_TWO_SIDE           0x0B52
-
-/* LightParameter */
 #define GL_AMBIENT                        0x1200
 #define GL_DIFFUSE                        0x1201
 #define GL_SPECULAR                       0x1202
@@ -309,16 +255,12 @@
 #define GL_CONSTANT_ATTENUATION           0x1207
 #define GL_LINEAR_ATTENUATION             0x1208
 #define GL_QUADRATIC_ATTENUATION          0x1209
-
-/* DataType */
 #define GL_BYTE                           0x1400
 #define GL_UNSIGNED_BYTE                  0x1401
 #define GL_SHORT                          0x1402
 #define GL_UNSIGNED_SHORT                 0x1403
 #define GL_FLOAT                          0x1406
 #define GL_FIXED                          0x140C
-
-/* LogicOp */
 #define GL_CLEAR                          0x1500
 #define GL_AND                            0x1501
 #define GL_AND_REVERSE                    0x1502
@@ -335,117 +277,49 @@
 #define GL_OR_INVERTED                    0x150D
 #define GL_NAND                           0x150E
 #define GL_SET                            0x150F
-
-/* MaterialFace */
-/*      GL_FRONT_AND_BACK */
-
-/* MaterialParameter */
 #define GL_EMISSION                       0x1600
 #define GL_SHININESS                      0x1601
 #define GL_AMBIENT_AND_DIFFUSE            0x1602
-/*      GL_AMBIENT */
-/*      GL_DIFFUSE */
-/*      GL_SPECULAR */
-
-/* MatrixMode */
 #define GL_MODELVIEW                      0x1700
 #define GL_PROJECTION                     0x1701
 #define GL_TEXTURE                        0x1702
-
-/* NormalPointerType */
-/*      GL_BYTE */
-/*      GL_SHORT */
-/*      GL_FLOAT */
-/*      GL_FIXED */
-
-/* PixelFormat */
 #define GL_ALPHA                          0x1906
 #define GL_RGB                            0x1907
 #define GL_RGBA                           0x1908
 #define GL_LUMINANCE                      0x1909
 #define GL_LUMINANCE_ALPHA                0x190A
-
-/* PixelStoreParameter */
 #define GL_UNPACK_ALIGNMENT               0x0CF5
 #define GL_PACK_ALIGNMENT                 0x0D05
-
-/* PixelType */
-/*      GL_UNSIGNED_BYTE */
 #define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
 #define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
 #define GL_UNSIGNED_SHORT_5_6_5           0x8363
-
-/* ShadingModel */
 #define GL_FLAT                           0x1D00
 #define GL_SMOOTH                         0x1D01
-
-/* StencilFunction */
-/*      GL_NEVER */
-/*      GL_LESS */
-/*      GL_EQUAL */
-/*      GL_LEQUAL */
-/*      GL_GREATER */
-/*      GL_NOTEQUAL */
-/*      GL_GEQUAL */
-/*      GL_ALWAYS */
-
-/* StencilOp */
-/*      GL_ZERO */
 #define GL_KEEP                           0x1E00
 #define GL_REPLACE                        0x1E01
 #define GL_INCR                           0x1E02
 #define GL_DECR                           0x1E03
-/*      GL_INVERT */
-
-/* StringName */
 #define GL_VENDOR                         0x1F00
 #define GL_RENDERER                       0x1F01
 #define GL_VERSION                        0x1F02
 #define GL_EXTENSIONS                     0x1F03
-
-/* TexCoordPointerType */
-/*      GL_SHORT */
-/*      GL_FLOAT */
-/*      GL_FIXED */
-/*      GL_BYTE */
-
-/* TextureEnvMode */
 #define GL_MODULATE                       0x2100
 #define GL_DECAL                          0x2101
-/*      GL_BLEND */
 #define GL_ADD                            0x0104
-/*      GL_REPLACE */
-
-/* TextureEnvParameter */
 #define GL_TEXTURE_ENV_MODE               0x2200
 #define GL_TEXTURE_ENV_COLOR              0x2201
-
-/* TextureEnvTarget */
 #define GL_TEXTURE_ENV                    0x2300
-
-/* TextureMagFilter */
 #define GL_NEAREST                        0x2600
 #define GL_LINEAR                         0x2601
-
-/* TextureMinFilter */
-/*      GL_NEAREST */
-/*      GL_LINEAR */
 #define GL_NEAREST_MIPMAP_NEAREST         0x2700
 #define GL_LINEAR_MIPMAP_NEAREST          0x2701
 #define GL_NEAREST_MIPMAP_LINEAR          0x2702
 #define GL_LINEAR_MIPMAP_LINEAR           0x2703
-
-/* TextureParameterName */
 #define GL_TEXTURE_MAG_FILTER             0x2800
 #define GL_TEXTURE_MIN_FILTER             0x2801
 #define GL_TEXTURE_WRAP_S                 0x2802
 #define GL_TEXTURE_WRAP_T                 0x2803
 #define GL_GENERATE_MIPMAP                0x8191
-
-/* TextureTarget */
-/*      GL_TEXTURE_2D */
-
-/* TextureUnit */
 #define GL_TEXTURE0                       0x84C0
 #define GL_TEXTURE1                       0x84C1
 #define GL_TEXTURE2                       0x84C2
@@ -480,18 +354,8 @@
 #define GL_TEXTURE31                      0x84DF
 #define GL_ACTIVE_TEXTURE                 0x84E0
 #define GL_CLIENT_ACTIVE_TEXTURE          0x84E1
-
-/* TextureWrapMode */
 #define GL_REPEAT                         0x2901
 #define GL_CLAMP_TO_EDGE                  0x812F
-
-/* VertexPointerType */
-/*      GL_SHORT */
-/*      GL_FLOAT */
-/*      GL_FIXED */
-/*      GL_BYTE */
-
-/* LightName */
 #define GL_LIGHT0                         0x4000
 #define GL_LIGHT1                         0x4001
 #define GL_LIGHT2                         0x4002
@@ -500,25 +364,18 @@
 #define GL_LIGHT5                         0x4005
 #define GL_LIGHT6                         0x4006
 #define GL_LIGHT7                         0x4007
-
-/* Buffer Objects */
 #define GL_ARRAY_BUFFER                   0x8892
 #define GL_ELEMENT_ARRAY_BUFFER           0x8893
-
-#define GL_ARRAY_BUFFER_BINDING               0x8894
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING       0x8895
-#define GL_VERTEX_ARRAY_BUFFER_BINDING        0x8896
-#define GL_NORMAL_ARRAY_BUFFER_BINDING        0x8897
-#define GL_COLOR_ARRAY_BUFFER_BINDING         0x8898
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING    0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING    0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING     0x8898
 #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
-
 #define GL_STATIC_DRAW                    0x88E4
 #define GL_DYNAMIC_DRAW                   0x88E8
-
 #define GL_BUFFER_SIZE                    0x8764
 #define GL_BUFFER_USAGE                   0x8765
-
-/* Texture combine + dot3 */
 #define GL_SUBTRACT                       0x84E7
 #define GL_COMBINE                        0x8570
 #define GL_COMBINE_RGB                    0x8571
@@ -535,75 +392,29 @@
 #define GL_OPERAND0_ALPHA                 0x8598
 #define GL_OPERAND1_ALPHA                 0x8599
 #define GL_OPERAND2_ALPHA                 0x859A
-
 #define GL_ALPHA_SCALE                    0x0D1C
-
 #define GL_SRC0_RGB                       0x8580
 #define GL_SRC1_RGB                       0x8581
 #define GL_SRC2_RGB                       0x8582
 #define GL_SRC0_ALPHA                     0x8588
 #define GL_SRC1_ALPHA                     0x8589
 #define GL_SRC2_ALPHA                     0x858A
-
 #define GL_DOT3_RGB                       0x86AE
 #define GL_DOT3_RGBA                      0x86AF
-
-/*------------------------------------------------------------------------*
- * required OES extension tokens
- *------------------------------------------------------------------------*/
-
-/* OES_read_format */
-#ifndef GL_OES_read_format
-#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES                   0x8B9A
-#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES                 0x8B9B
-#endif
-
-/* GL_OES_compressed_paletted_texture */
-#ifndef GL_OES_compressed_paletted_texture
-#define GL_PALETTE4_RGB8_OES                                    0x8B90
-#define GL_PALETTE4_RGBA8_OES                                   0x8B91
-#define GL_PALETTE4_R5_G6_B5_OES                                0x8B92
-#define GL_PALETTE4_RGBA4_OES                                   0x8B93
-#define GL_PALETTE4_RGB5_A1_OES                                 0x8B94
-#define GL_PALETTE8_RGB8_OES                                    0x8B95
-#define GL_PALETTE8_RGBA8_OES                                   0x8B96
-#define GL_PALETTE8_R5_G6_B5_OES                                0x8B97
-#define GL_PALETTE8_RGBA4_OES                                   0x8B98
-#define GL_PALETTE8_RGB5_A1_OES                                 0x8B99
-#endif
-
-/* OES_point_size_array */
-#ifndef GL_OES_point_size_array
-#define GL_POINT_SIZE_ARRAY_OES                                 0x8B9C
-#define GL_POINT_SIZE_ARRAY_TYPE_OES                            0x898A
-#define GL_POINT_SIZE_ARRAY_STRIDE_OES                          0x898B
-#define GL_POINT_SIZE_ARRAY_POINTER_OES                         0x898C
-#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES                  0x8B9F
-#endif
-
-/* GL_OES_point_sprite */
-#ifndef GL_OES_point_sprite
-#define GL_POINT_SPRITE_OES                                     0x8861
-#define GL_COORD_REPLACE_OES                                    0x8862
-#endif
-
-/*************************************************************/
-
-/* Available only in Common profile */
-GL_API void GL_APIENTRY glAlphaFunc (GLenum func, GLclampf ref);
-GL_API void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-GL_API void GL_APIENTRY glClearDepthf (GLclampf depth);
-GL_API void GL_APIENTRY glClipPlanef (GLenum plane, const GLfloat *equation);
+GL_API void GL_APIENTRY glAlphaFunc (GLenum func, GLfloat ref);
+GL_API void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_API void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_API void GL_APIENTRY glClipPlanef (GLenum p, const GLfloat *eqn);
 GL_API void GL_APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-GL_API void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_API void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
 GL_API void GL_APIENTRY glFogf (GLenum pname, GLfloat param);
 GL_API void GL_APIENTRY glFogfv (GLenum pname, const GLfloat *params);
-GL_API void GL_APIENTRY glFrustumf (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
-GL_API void GL_APIENTRY glGetClipPlanef (GLenum pname, GLfloat eqn[4]);
-GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *params);
+GL_API void GL_APIENTRY glFrustumf (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+GL_API void GL_APIENTRY glGetClipPlanef (GLenum plane, GLfloat *equation);
+GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
 GL_API void GL_APIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params);
 GL_API void GL_APIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params);
-GL_API void GL_APIENTRY glGetTexEnvfv (GLenum env, GLenum pname, GLfloat *params);
+GL_API void GL_APIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params);
 GL_API void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
 GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param);
 GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params);
@@ -616,7 +427,7 @@
 GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m);
 GL_API void GL_APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
 GL_API void GL_APIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);
-GL_API void GL_APIENTRY glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
+GL_API void GL_APIENTRY glOrthof (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
 GL_API void GL_APIENTRY glPointParameterf (GLenum pname, GLfloat param);
 GL_API void GL_APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
 GL_API void GL_APIENTRY glPointSize (GLfloat size);
@@ -628,27 +439,25 @@
 GL_API void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
 GL_API void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
 GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z);
-
-/* Available in both Common and Common-Lite profiles */
 GL_API void GL_APIENTRY glActiveTexture (GLenum texture);
-GL_API void GL_APIENTRY glAlphaFuncx (GLenum func, GLclampx ref);
+GL_API void GL_APIENTRY glAlphaFuncx (GLenum func, GLfixed ref);
 GL_API void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
 GL_API void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
 GL_API void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
-GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
-GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
 GL_API void GL_APIENTRY glClear (GLbitfield mask);
-GL_API void GL_APIENTRY glClearColorx (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
-GL_API void GL_APIENTRY glClearDepthx (GLclampx depth);
+GL_API void GL_APIENTRY glClearColorx (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GL_API void GL_APIENTRY glClearDepthx (GLfixed depth);
 GL_API void GL_APIENTRY glClearStencil (GLint s);
 GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture);
 GL_API void GL_APIENTRY glClipPlanex (GLenum plane, const GLfixed *equation);
 GL_API void GL_APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
 GL_API void GL_APIENTRY glColor4x (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
 GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-GL_API void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
-GL_API void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_API void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_API void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
 GL_API void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
 GL_API void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 GL_API void GL_APIENTRY glCullFace (GLenum mode);
@@ -656,33 +465,33 @@
 GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
 GL_API void GL_APIENTRY glDepthFunc (GLenum func);
 GL_API void GL_APIENTRY glDepthMask (GLboolean flag);
-GL_API void GL_APIENTRY glDepthRangex (GLclampx zNear, GLclampx zFar);
+GL_API void GL_APIENTRY glDepthRangex (GLfixed n, GLfixed f);
 GL_API void GL_APIENTRY glDisable (GLenum cap);
 GL_API void GL_APIENTRY glDisableClientState (GLenum array);
 GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
-GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
 GL_API void GL_APIENTRY glEnable (GLenum cap);
 GL_API void GL_APIENTRY glEnableClientState (GLenum array);
 GL_API void GL_APIENTRY glFinish (void);
 GL_API void GL_APIENTRY glFlush (void);
 GL_API void GL_APIENTRY glFogx (GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glFogxv (GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glFogxv (GLenum pname, const GLfixed *param);
 GL_API void GL_APIENTRY glFrontFace (GLenum mode);
-GL_API void GL_APIENTRY glFrustumx (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
-GL_API void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *params);
+GL_API void GL_APIENTRY glFrustumx (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GL_API void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
 GL_API void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
-GL_API void GL_APIENTRY glGetClipPlanex (GLenum pname, GLfixed eqn[4]);
+GL_API void GL_APIENTRY glGetClipPlanex (GLenum plane, GLfixed *equation);
 GL_API void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
 GL_API void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
 GL_API GLenum GL_APIENTRY glGetError (void);
 GL_API void GL_APIENTRY glGetFixedv (GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
 GL_API void GL_APIENTRY glGetLightxv (GLenum light, GLenum pname, GLfixed *params);
 GL_API void GL_APIENTRY glGetMaterialxv (GLenum face, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetPointerv (GLenum pname, GLvoid **params);
-GL_API const GLubyte * GL_APIENTRY glGetString (GLenum name);
-GL_API void GL_APIENTRY glGetTexEnviv (GLenum env, GLenum pname, GLint *params);
-GL_API void GL_APIENTRY glGetTexEnvxv (GLenum env, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+GL_API const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_API void GL_APIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glGetTexEnvxv (GLenum target, GLenum pname, GLfixed *params);
 GL_API void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
 GL_API void GL_APIENTRY glGetTexParameterxv (GLenum target, GLenum pname, GLfixed *params);
 GL_API void GL_APIENTRY glHint (GLenum target, GLenum mode);
@@ -690,7 +499,7 @@
 GL_API GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
 GL_API GLboolean GL_APIENTRY glIsTexture (GLuint texture);
 GL_API void GL_APIENTRY glLightModelx (GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glLightModelxv (GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glLightModelxv (GLenum pname, const GLfixed *param);
 GL_API void GL_APIENTRY glLightx (GLenum light, GLenum pname, GLfixed param);
 GL_API void GL_APIENTRY glLightxv (GLenum light, GLenum pname, const GLfixed *params);
 GL_API void GL_APIENTRY glLineWidthx (GLfixed width);
@@ -698,13 +507,13 @@
 GL_API void GL_APIENTRY glLoadMatrixx (const GLfixed *m);
 GL_API void GL_APIENTRY glLogicOp (GLenum opcode);
 GL_API void GL_APIENTRY glMaterialx (GLenum face, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glMaterialxv (GLenum face, GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glMaterialxv (GLenum face, GLenum pname, const GLfixed *param);
 GL_API void GL_APIENTRY glMatrixMode (GLenum mode);
 GL_API void GL_APIENTRY glMultMatrixx (const GLfixed *m);
-GL_API void GL_APIENTRY glMultiTexCoord4x (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GL_API void GL_APIENTRY glMultiTexCoord4x (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
 GL_API void GL_APIENTRY glNormal3x (GLfixed nx, GLfixed ny, GLfixed nz);
-GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
-GL_API void GL_APIENTRY glOrthox (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
+GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const void *pointer);
+GL_API void GL_APIENTRY glOrthox (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
 GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
 GL_API void GL_APIENTRY glPointParameterx (GLenum pname, GLfixed param);
 GL_API void GL_APIENTRY glPointParameterxv (GLenum pname, const GLfixed *params);
@@ -712,9 +521,9 @@
 GL_API void GL_APIENTRY glPolygonOffsetx (GLfixed factor, GLfixed units);
 GL_API void GL_APIENTRY glPopMatrix (void);
 GL_API void GL_APIENTRY glPushMatrix (void);
-GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
 GL_API void GL_APIENTRY glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-GL_API void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_API void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
 GL_API void GL_APIENTRY glSampleCoveragex (GLclampx value, GLboolean invert);
 GL_API void GL_APIENTRY glScalex (GLfixed x, GLfixed y, GLfixed z);
 GL_API void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
@@ -722,49 +531,60 @@
 GL_API void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
 GL_API void GL_APIENTRY glStencilMask (GLuint mask);
 GL_API void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
-GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
 GL_API void GL_APIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param);
 GL_API void GL_APIENTRY glTexEnvx (GLenum target, GLenum pname, GLfixed param);
 GL_API void GL_APIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params);
 GL_API void GL_APIENTRY glTexEnvxv (GLenum target, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
 GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
 GL_API void GL_APIENTRY glTexParameterx (GLenum target, GLenum pname, GLfixed param);
 GL_API void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
 GL_API void GL_APIENTRY glTexParameterxv (GLenum target, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+GL_API void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
 GL_API void GL_APIENTRY glTranslatex (GLfixed x, GLfixed y, GLfixed z);
-GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
 GL_API void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif /* GL_VERSION_ES_CM_1_0 */
 
-/*------------------------------------------------------------------------*
- * Required OES extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_OES_read_format */
-#ifndef GL_OES_read_format
-#define GL_OES_read_format 1
-#endif
-
-/* GL_OES_compressed_paletted_texture */
 #ifndef GL_OES_compressed_paletted_texture
 #define GL_OES_compressed_paletted_texture 1
-#endif
+#define GL_PALETTE4_RGB8_OES              0x8B90
+#define GL_PALETTE4_RGBA8_OES             0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES          0x8B92
+#define GL_PALETTE4_RGBA4_OES             0x8B93
+#define GL_PALETTE4_RGB5_A1_OES           0x8B94
+#define GL_PALETTE8_RGB8_OES              0x8B95
+#define GL_PALETTE8_RGBA8_OES             0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES          0x8B97
+#define GL_PALETTE8_RGBA4_OES             0x8B98
+#define GL_PALETTE8_RGB5_A1_OES           0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
 
-/* GL_OES_point_size_array */
 #ifndef GL_OES_point_size_array
 #define GL_OES_point_size_array 1
-GL_API void GL_APIENTRY glPointSizePointerOES (GLenum type, GLsizei stride, const GLvoid *pointer);
-#endif
+#define GL_POINT_SIZE_ARRAY_OES           0x8B9C
+#define GL_POINT_SIZE_ARRAY_TYPE_OES      0x898A
+#define GL_POINT_SIZE_ARRAY_STRIDE_OES    0x898B
+#define GL_POINT_SIZE_ARRAY_POINTER_OES   0x898C
+#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F
+GL_API void GL_APIENTRY glPointSizePointerOES (GLenum type, GLsizei stride, const void *pointer);
+#endif /* GL_OES_point_size_array */
 
-/* GL_OES_point_sprite */
 #ifndef GL_OES_point_sprite
 #define GL_OES_point_sprite 1
-#endif
+#define GL_POINT_SPRITE_OES               0x8861
+#define GL_COORD_REPLACE_OES              0x8862
+#endif /* GL_OES_point_sprite */
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif /* GL_OES_read_format */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __gl_h_ */
-
+#endif
diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h
index 5843d5e..b6fe620 100644
--- a/opengl/include/GLES/glext.h
+++ b/opengl/include/GLES/glext.h
@@ -1,613 +1,143 @@
 #ifndef __glext_h_
-#define __glext_h_
-
-/* $Revision: 20798 $ on $Date:: 2013-03-07 01:19:34 -0800 #$ */
+#define __glext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
+** Copyright (c) 2013-2017 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 OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   https://github.com/KhronosGroup/OpenGL-Registry
+*/
 
 #ifndef GL_APIENTRYP
-#   define GL_APIENTRYP GL_APIENTRY*
+#define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-/*------------------------------------------------------------------------*
- * OES extension tokens
- *------------------------------------------------------------------------*/
+/* Generated on date 20170613 */
 
-/* GL_OES_blend_equation_separate */
-#ifndef GL_OES_blend_equation_separate
-/* BLEND_EQUATION_RGB_OES same as BLEND_EQUATION_OES */
-#define GL_BLEND_EQUATION_RGB_OES                               0x8009
-#define GL_BLEND_EQUATION_ALPHA_OES                             0x883D
-#endif
-
-/* GL_OES_blend_func_separate */
-#ifndef GL_OES_blend_func_separate
-#define GL_BLEND_DST_RGB_OES                                    0x80C8
-#define GL_BLEND_SRC_RGB_OES                                    0x80C9
-#define GL_BLEND_DST_ALPHA_OES                                  0x80CA
-#define GL_BLEND_SRC_ALPHA_OES                                  0x80CB
-#endif
-
-/* GL_OES_blend_subtract */
-#ifndef GL_OES_blend_subtract
-#define GL_BLEND_EQUATION_OES                                   0x8009
-#define GL_FUNC_ADD_OES                                         0x8006
-#define GL_FUNC_SUBTRACT_OES                                    0x800A
-#define GL_FUNC_REVERSE_SUBTRACT_OES                            0x800B
-#endif
-
-/* GL_OES_compressed_ETC1_RGB8_texture */
-#ifndef GL_OES_compressed_ETC1_RGB8_texture
-#define GL_ETC1_RGB8_OES                                        0x8D64
-#endif
-
-/* GL_OES_depth24 */
-#ifndef GL_OES_depth24
-#define GL_DEPTH_COMPONENT24_OES                                0x81A6
-#endif
-
-/* GL_OES_depth32 */
-#ifndef GL_OES_depth32
-#define GL_DEPTH_COMPONENT32_OES                                0x81A7
-#endif
-
-/* GL_OES_draw_texture */
-#ifndef GL_OES_draw_texture
-#define GL_TEXTURE_CROP_RECT_OES                                0x8B9D
-#endif
-
-/* GL_OES_EGL_image */
-#ifndef GL_OES_EGL_image
-typedef void* GLeglImageOES;
-#endif
-
-/* GL_OES_EGL_image_external */
-#ifndef GL_OES_EGL_image_external
-/* GLeglImageOES defined in GL_OES_EGL_image already. */
-#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
-#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
-#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
-#endif
-
-/* GL_OES_element_index_uint */
-#ifndef GL_OES_element_index_uint
-#define GL_UNSIGNED_INT                                         0x1405
-#endif
-
-/* GL_OES_fixed_point */
-#ifndef GL_OES_fixed_point
-#define GL_FIXED_OES                                            0x140C
-#endif
-
-/* GL_OES_framebuffer_object */
-#ifndef GL_OES_framebuffer_object
-#define GL_NONE_OES                                             0
-#define GL_FRAMEBUFFER_OES                                      0x8D40
-#define GL_RENDERBUFFER_OES                                     0x8D41
-#define GL_RGBA4_OES                                            0x8056
-#define GL_RGB5_A1_OES                                          0x8057
-#define GL_RGB565_OES                                           0x8D62
-#define GL_DEPTH_COMPONENT16_OES                                0x81A5
-#define GL_RENDERBUFFER_WIDTH_OES                               0x8D42
-#define GL_RENDERBUFFER_HEIGHT_OES                              0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES                     0x8D44
-#define GL_RENDERBUFFER_RED_SIZE_OES                            0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE_OES                          0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE_OES                           0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE_OES                          0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE_OES                          0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE_OES                        0x8D55
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES               0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES               0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES             0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES     0x8CD3
-#define GL_COLOR_ATTACHMENT0_OES                                0x8CE0
-#define GL_DEPTH_ATTACHMENT_OES                                 0x8D00
-#define GL_STENCIL_ATTACHMENT_OES                               0x8D20
-#define GL_FRAMEBUFFER_COMPLETE_OES                             0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES                0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES        0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES                0x8CD9
-#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES                   0x8CDA
-#define GL_FRAMEBUFFER_UNSUPPORTED_OES                          0x8CDD
-#define GL_FRAMEBUFFER_BINDING_OES                              0x8CA6
-#define GL_RENDERBUFFER_BINDING_OES                             0x8CA7
-#define GL_MAX_RENDERBUFFER_SIZE_OES                            0x84E8
-#define GL_INVALID_FRAMEBUFFER_OPERATION_OES                    0x0506
-#endif
-
-/* GL_OES_mapbuffer */
-#ifndef GL_OES_mapbuffer
-#define GL_WRITE_ONLY_OES                                       0x88B9
-#define GL_BUFFER_ACCESS_OES                                    0x88BB
-#define GL_BUFFER_MAPPED_OES                                    0x88BC
-#define GL_BUFFER_MAP_POINTER_OES                               0x88BD
-#endif
-
-/* GL_OES_matrix_get */
-#ifndef GL_OES_matrix_get
-#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES               0x898D
-#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES              0x898E
-#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES                 0x898F
-#endif
-
-/* GL_OES_matrix_palette */
-#ifndef GL_OES_matrix_palette
-#define GL_MAX_VERTEX_UNITS_OES                                 0x86A4
-#define GL_MAX_PALETTE_MATRICES_OES                             0x8842
-#define GL_MATRIX_PALETTE_OES                                   0x8840
-#define GL_MATRIX_INDEX_ARRAY_OES                               0x8844
-#define GL_WEIGHT_ARRAY_OES                                     0x86AD
-#define GL_CURRENT_PALETTE_MATRIX_OES                           0x8843
-#define GL_MATRIX_INDEX_ARRAY_SIZE_OES                          0x8846
-#define GL_MATRIX_INDEX_ARRAY_TYPE_OES                          0x8847
-#define GL_MATRIX_INDEX_ARRAY_STRIDE_OES                        0x8848
-#define GL_MATRIX_INDEX_ARRAY_POINTER_OES                       0x8849
-#define GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES                0x8B9E
-#define GL_WEIGHT_ARRAY_SIZE_OES                                0x86AB
-#define GL_WEIGHT_ARRAY_TYPE_OES                                0x86A9
-#define GL_WEIGHT_ARRAY_STRIDE_OES                              0x86AA
-#define GL_WEIGHT_ARRAY_POINTER_OES                             0x86AC
-#define GL_WEIGHT_ARRAY_BUFFER_BINDING_OES                      0x889E
-#endif
-
-/* GL_OES_packed_depth_stencil */
-#ifndef GL_OES_packed_depth_stencil
-#define GL_DEPTH_STENCIL_OES                                    0x84F9
-#define GL_UNSIGNED_INT_24_8_OES                                0x84FA
-#define GL_DEPTH24_STENCIL8_OES                                 0x88F0
-#endif
-
-/* GL_OES_required_internalformat */
-/* No new tokens introduced by this extension. */
-
-/* GL_OES_rgb8_rgba8 */
-#ifndef GL_OES_rgb8_rgba8
-#define GL_RGB8_OES                                             0x8051
-#define GL_RGBA8_OES                                            0x8058
-#endif
-
-/* GL_OES_stencil1 */
-#ifndef GL_OES_stencil1
-#define GL_STENCIL_INDEX1_OES                                   0x8D46
-#endif
-
-/* GL_OES_stencil4 */
-#ifndef GL_OES_stencil4
-#define GL_STENCIL_INDEX4_OES                                   0x8D47
-#endif
-
-/* GL_OES_stencil8 */
-#ifndef GL_OES_stencil8
-#define GL_STENCIL_INDEX8_OES                                   0x8D48
-#endif
-
-/* GL_OES_stencil_wrap */
-#ifndef GL_OES_stencil_wrap
-#define GL_INCR_WRAP_OES                                        0x8507
-#define GL_DECR_WRAP_OES                                        0x8508
-#endif
-
-/* GL_OES_texture_cube_map */
-#ifndef GL_OES_texture_cube_map
-#define GL_NORMAL_MAP_OES                                       0x8511
-#define GL_REFLECTION_MAP_OES                                   0x8512
-#define GL_TEXTURE_CUBE_MAP_OES                                 0x8513
-#define GL_TEXTURE_BINDING_CUBE_MAP_OES                         0x8514
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES                      0x8515
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES                      0x8516
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES                      0x8517
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES                      0x8518
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES                      0x8519
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES                      0x851A
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES                        0x851C
-#define GL_TEXTURE_GEN_MODE_OES                                 0x2500
-#define GL_TEXTURE_GEN_STR_OES                                  0x8D60
-#endif
-
-/* GL_OES_texture_mirrored_repeat */
-#ifndef GL_OES_texture_mirrored_repeat
-#define GL_MIRRORED_REPEAT_OES                                  0x8370
-#endif
-
-/* GL_OES_vertex_array_object */
-#ifndef GL_OES_vertex_array_object
-#define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
-#endif
-
-/*------------------------------------------------------------------------*
- * AMD extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_AMD_compressed_3DC_texture */
-#ifndef GL_AMD_compressed_3DC_texture
-#define GL_3DC_X_AMD                                            0x87F9
-#define GL_3DC_XY_AMD                                           0x87FA
-#endif
-
-/* GL_AMD_compressed_ATC_texture */
-#ifndef GL_AMD_compressed_ATC_texture
-#define GL_ATC_RGB_AMD                                          0x8C92
-#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          0x8C93
-#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      0x87EE
-#endif
-
-/*------------------------------------------------------------------------*
- * APPLE extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_APPLE_copy_texture_levels */
-/* No new tokens introduced by this extension. */
-
-/* GL_APPLE_framebuffer_multisample */
-#ifndef GL_APPLE_framebuffer_multisample
-#define GL_RENDERBUFFER_SAMPLES_APPLE                           0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE             0x8D56
-#define GL_MAX_SAMPLES_APPLE                                    0x8D57
-#define GL_READ_FRAMEBUFFER_APPLE                               0x8CA8
-#define GL_DRAW_FRAMEBUFFER_APPLE                               0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE                       0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_APPLE                       0x8CAA
-#endif
-
-/* GL_APPLE_sync */
-#ifndef GL_APPLE_sync
-
-/* These types are defined with reference to <inttypes.h>
- * in the Apple extension spec, but here we use the Khronos
- * portable types in khrplatform.h, and assume those types
- * are always defined.
- * If any other extensions using these types are defined,
- * the typedefs must move out of this block and be shared.
+/* Generated C header for:
+ * API: gles1
+ * Profile: common
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: gles1
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: ^(GL_OES_read_format|GL_OES_compressed_paletted_texture|GL_OES_point_size_array|GL_OES_point_sprite)$
  */
-typedef khronos_int64_t GLint64;
-typedef khronos_uint64_t GLuint64;
-typedef struct __GLsync *GLsync;
 
-#define GL_SYNC_OBJECT_APPLE                                    0x8A53
-#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE                        0x9111
-#define GL_OBJECT_TYPE_APPLE                                    0x9112
-#define GL_SYNC_CONDITION_APPLE                                 0x9113
-#define GL_SYNC_STATUS_APPLE                                    0x9114
-#define GL_SYNC_FLAGS_APPLE                                     0x9115
-#define GL_SYNC_FENCE_APPLE                                     0x9116
-#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE                     0x9117
-#define GL_UNSIGNALED_APPLE                                     0x9118
-#define GL_SIGNALED_APPLE                                       0x9119
-#define GL_ALREADY_SIGNALED_APPLE                               0x911A
-#define GL_TIMEOUT_EXPIRED_APPLE                                0x911B
-#define GL_CONDITION_SATISFIED_APPLE                            0x911C
-#define GL_WAIT_FAILED_APPLE                                    0x911D
-#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE                        0x00000001
-#define GL_TIMEOUT_IGNORED_APPLE                                0xFFFFFFFFFFFFFFFFull
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+typedef void *GLeglImageOES;
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
 #endif
+#endif /* GL_OES_EGL_image */
 
-/* GL_APPLE_texture_2D_limited_npot */
-/* No new tokens introduced by this extension. */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+#define GL_TEXTURE_EXTERNAL_OES           0x8D65
+#define GL_TEXTURE_BINDING_EXTERNAL_OES   0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#endif /* GL_OES_EGL_image_external */
 
-/* GL_APPLE_texture_format_BGRA8888 */
-#ifndef GL_APPLE_texture_format_BGRA8888
-#define GL_BGRA_EXT                                             0x80E1
-#endif
-
-/* GL_APPLE_texture_max_level */
-#ifndef GL_APPLE_texture_max_level
-#define GL_TEXTURE_MAX_LEVEL_APPLE                              0x813D
-#endif
-
-/*------------------------------------------------------------------------*
- * ARM extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_ARM_rgba8 */
-/* No new tokens introduced by this extension. */
-
-/*------------------------------------------------------------------------*
- * EXT extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_EXT_blend_minmax */
-#ifndef GL_EXT_blend_minmax
-#define GL_MIN_EXT                                              0x8007
-#define GL_MAX_EXT                                              0x8008
-#endif
-
-/* GL_EXT_discard_framebuffer */
-#ifndef GL_EXT_discard_framebuffer
-#define GL_COLOR_EXT                                            0x1800
-#define GL_DEPTH_EXT                                            0x1801
-#define GL_STENCIL_EXT                                          0x1802
-#endif
-
-/* GL_EXT_map_buffer_range */
-#ifndef GL_EXT_map_buffer_range
-#define GL_MAP_READ_BIT_EXT                                     0x0001
-#define GL_MAP_WRITE_BIT_EXT                                    0x0002
-#define GL_MAP_INVALIDATE_RANGE_BIT_EXT                         0x0004
-#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT                        0x0008
-#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT                           0x0010
-#define GL_MAP_UNSYNCHRONIZED_BIT_EXT                           0x0020
-#endif
-
-/* GL_EXT_multisampled_render_to_texture */
-#ifndef GL_EXT_multisampled_render_to_texture
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
-/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */
-#define GL_RENDERBUFFER_SAMPLES_EXT                             0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x8D56
-#define GL_MAX_SAMPLES_EXT                                      0x8D57
-#endif
-
-/* GL_EXT_multi_draw_arrays */
-/* No new tokens introduced by this extension. */
-
-/* GL_EXT_read_format_bgra */
-#ifndef GL_EXT_read_format_bgra
-#define GL_BGRA_EXT                                             0x80E1
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
-#endif
-
-/* GL_EXT_robustness */
-#ifndef GL_EXT_robustness
-/* reuse GL_NO_ERROR */
-#define GL_GUILTY_CONTEXT_RESET_EXT                             0x8253
-#define GL_INNOCENT_CONTEXT_RESET_EXT                           0x8254
-#define GL_UNKNOWN_CONTEXT_RESET_EXT                            0x8255
-#define GL_CONTEXT_ROBUST_ACCESS_EXT                            0x90F3
-#define GL_RESET_NOTIFICATION_STRATEGY_EXT                      0x8256
-#define GL_LOSE_CONTEXT_ON_RESET_EXT                            0x8252
-#define GL_NO_RESET_NOTIFICATION_EXT                            0x8261
-#endif
-
-/* GL_EXT_sRGB */
-#ifndef GL_EXT_sRGB
-#define GL_SRGB_EXT                                             0x8C40
-#define GL_SRGB_ALPHA_EXT                                       0x8C42
-#define GL_SRGB8_ALPHA8_EXT                                     0x8C43
-#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT            0x8210
-#endif
-
-/* GL_EXT_texture_compression_dxt1 */
-#ifndef GL_EXT_texture_compression_dxt1
-#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT                         0x83F0
-#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT                        0x83F1
-#endif
-
-/* GL_EXT_texture_filter_anisotropic */
-#ifndef GL_EXT_texture_filter_anisotropic
-#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
-#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
-#endif
-
-/* GL_EXT_texture_format_BGRA8888 */
-#ifndef GL_EXT_texture_format_BGRA8888
-#define GL_BGRA_EXT                                             0x80E1
-#endif
-
-/* GL_EXT_texture_lod_bias */
-#ifndef GL_EXT_texture_lod_bias
-#define GL_MAX_TEXTURE_LOD_BIAS_EXT                             0x84FD
-#define GL_TEXTURE_FILTER_CONTROL_EXT                           0x8500
-#define GL_TEXTURE_LOD_BIAS_EXT                                 0x8501
-#endif
-
-/* GL_EXT_texture_storage */
-#ifndef GL_EXT_texture_storage
-#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT                         0x912F
-#define GL_ALPHA8_EXT                                           0x803C
-#define GL_LUMINANCE8_EXT                                       0x8040
-#define GL_LUMINANCE8_ALPHA8_EXT                                0x8045
-#define GL_RGBA32F_EXT                                          0x8814
-#define GL_RGB32F_EXT                                           0x8815
-#define GL_ALPHA32F_EXT                                         0x8816
-#define GL_LUMINANCE32F_EXT                                     0x8818
-#define GL_LUMINANCE_ALPHA32F_EXT                               0x8819
-/* reuse GL_RGBA16F_EXT */
-#define GL_RGB16F_EXT                                           0x881B
-#define GL_ALPHA16F_EXT                                         0x881C
-#define GL_LUMINANCE16F_EXT                                     0x881E
-#define GL_LUMINANCE_ALPHA16F_EXT                               0x881F
-#define GL_RGB10_A2_EXT                                         0x8059
-#define GL_RGB10_EXT                                            0x8052
-#define GL_BGRA8_EXT                                            0x93A1
-#endif
-
-/*------------------------------------------------------------------------*
- * IMG extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_IMG_read_format */
-#ifndef GL_IMG_read_format
-#define GL_BGRA_IMG                                             0x80E1
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG                       0x8365
-#endif
-
-/* GL_IMG_texture_compression_pvrtc */
-#ifndef GL_IMG_texture_compression_pvrtc
-#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
-#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
-#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
-#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
-#endif
-
-/* GL_IMG_texture_env_enhanced_fixed_function */
-#ifndef GL_IMG_texture_env_enhanced_fixed_function
-#define GL_MODULATE_COLOR_IMG                                   0x8C04
-#define GL_RECIP_ADD_SIGNED_ALPHA_IMG                           0x8C05
-#define GL_TEXTURE_ALPHA_MODULATE_IMG                           0x8C06
-#define GL_FACTOR_ALPHA_MODULATE_IMG                            0x8C07
-#define GL_FRAGMENT_ALPHA_MODULATE_IMG                          0x8C08
-#define GL_ADD_BLEND_IMG                                        0x8C09
-#define GL_DOT3_RGBA_IMG                                        0x86AF
-#endif
-
-/* GL_IMG_user_clip_plane */
-#ifndef GL_IMG_user_clip_plane
-#define GL_CLIP_PLANE0_IMG                                      0x3000
-#define GL_CLIP_PLANE1_IMG                                      0x3001
-#define GL_CLIP_PLANE2_IMG                                      0x3002
-#define GL_CLIP_PLANE3_IMG                                      0x3003
-#define GL_CLIP_PLANE4_IMG                                      0x3004
-#define GL_CLIP_PLANE5_IMG                                      0x3005
-#define GL_MAX_CLIP_PLANES_IMG                                  0x0D32
-#endif
-
-/* GL_IMG_multisampled_render_to_texture */
-#ifndef GL_IMG_multisampled_render_to_texture
-#define GL_RENDERBUFFER_SAMPLES_IMG                             0x9133
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG               0x9134
-#define GL_MAX_SAMPLES_IMG                                      0x9135
-#define GL_TEXTURE_SAMPLES_IMG                                  0x9136
-#endif
-
-/*------------------------------------------------------------------------*
- * NV extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_NV_fence */
-#ifndef GL_NV_fence
-#define GL_ALL_COMPLETED_NV                                     0x84F2
-#define GL_FENCE_STATUS_NV                                      0x84F3
-#define GL_FENCE_CONDITION_NV                                   0x84F4
-#endif
-
-/*------------------------------------------------------------------------*
- * QCOM extension tokens
- *------------------------------------------------------------------------*/
-
-/* GL_QCOM_driver_control */
-/* No new tokens introduced by this extension. */
-
-/* GL_QCOM_extended_get */
-#ifndef GL_QCOM_extended_get
-#define GL_TEXTURE_WIDTH_QCOM                                   0x8BD2
-#define GL_TEXTURE_HEIGHT_QCOM                                  0x8BD3
-#define GL_TEXTURE_DEPTH_QCOM                                   0x8BD4
-#define GL_TEXTURE_INTERNAL_FORMAT_QCOM                         0x8BD5
-#define GL_TEXTURE_FORMAT_QCOM                                  0x8BD6
-#define GL_TEXTURE_TYPE_QCOM                                    0x8BD7
-#define GL_TEXTURE_IMAGE_VALID_QCOM                             0x8BD8
-#define GL_TEXTURE_NUM_LEVELS_QCOM                              0x8BD9
-#define GL_TEXTURE_TARGET_QCOM                                  0x8BDA
-#define GL_TEXTURE_OBJECT_VALID_QCOM                            0x8BDB
-#define GL_STATE_RESTORE                                        0x8BDC
-#endif
-
-/* GL_QCOM_extended_get2 */
-/* No new tokens introduced by this extension. */
-
-/* GL_QCOM_perfmon_global_mode */
-#ifndef GL_QCOM_perfmon_global_mode
-#define GL_PERFMON_GLOBAL_MODE_QCOM                             0x8FA0
-#endif
-
-/* GL_QCOM_writeonly_rendering */
-#ifndef GL_QCOM_writeonly_rendering
-#define GL_WRITEONLY_RENDERING_QCOM                             0x8823
-#endif
-
-/* GL_QCOM_tiled_rendering */
-#ifndef GL_QCOM_tiled_rendering
-#define GL_COLOR_BUFFER_BIT0_QCOM                               0x00000001
-#define GL_COLOR_BUFFER_BIT1_QCOM                               0x00000002
-#define GL_COLOR_BUFFER_BIT2_QCOM                               0x00000004
-#define GL_COLOR_BUFFER_BIT3_QCOM                               0x00000008
-#define GL_COLOR_BUFFER_BIT4_QCOM                               0x00000010
-#define GL_COLOR_BUFFER_BIT5_QCOM                               0x00000020
-#define GL_COLOR_BUFFER_BIT6_QCOM                               0x00000040
-#define GL_COLOR_BUFFER_BIT7_QCOM                               0x00000080
-#define GL_DEPTH_BUFFER_BIT0_QCOM                               0x00000100
-#define GL_DEPTH_BUFFER_BIT1_QCOM                               0x00000200
-#define GL_DEPTH_BUFFER_BIT2_QCOM                               0x00000400
-#define GL_DEPTH_BUFFER_BIT3_QCOM                               0x00000800
-#define GL_DEPTH_BUFFER_BIT4_QCOM                               0x00001000
-#define GL_DEPTH_BUFFER_BIT5_QCOM                               0x00002000
-#define GL_DEPTH_BUFFER_BIT6_QCOM                               0x00004000
-#define GL_DEPTH_BUFFER_BIT7_QCOM                               0x00008000
-#define GL_STENCIL_BUFFER_BIT0_QCOM                             0x00010000
-#define GL_STENCIL_BUFFER_BIT1_QCOM                             0x00020000
-#define GL_STENCIL_BUFFER_BIT2_QCOM                             0x00040000
-#define GL_STENCIL_BUFFER_BIT3_QCOM                             0x00080000
-#define GL_STENCIL_BUFFER_BIT4_QCOM                             0x00100000
-#define GL_STENCIL_BUFFER_BIT5_QCOM                             0x00200000
-#define GL_STENCIL_BUFFER_BIT6_QCOM                             0x00400000
-#define GL_STENCIL_BUFFER_BIT7_QCOM                             0x00800000
-#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM                         0x01000000
-#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM                         0x02000000
-#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM                         0x04000000
-#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM                         0x08000000
-#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM                         0x10000000
-#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM                         0x20000000
-#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM                         0x40000000
-#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM                         0x80000000
-#endif
-
-/*------------------------------------------------------------------------*
- * End of extension tokens, start of corresponding extension functions
- *------------------------------------------------------------------------*/
-
-/*------------------------------------------------------------------------*
- * OES extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_OES_blend_equation_separate */
 #ifndef GL_OES_blend_equation_separate
 #define GL_OES_blend_equation_separate 1
+#define GL_BLEND_EQUATION_RGB_OES         0x8009
+#define GL_BLEND_EQUATION_ALPHA_OES       0x883D
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEOESPROC) (GLenum modeRGB, GLenum modeAlpha);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glBlendEquationSeparateOES (GLenum modeRGB, GLenum modeAlpha);
 #endif
-typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEOESPROC) (GLenum modeRGB, GLenum modeAlpha);
-#endif
+#endif /* GL_OES_blend_equation_separate */
 
-/* GL_OES_blend_func_separate */
 #ifndef GL_OES_blend_func_separate
 #define GL_OES_blend_func_separate 1
+#define GL_BLEND_DST_RGB_OES              0x80C8
+#define GL_BLEND_SRC_RGB_OES              0x80C9
+#define GL_BLEND_DST_ALPHA_OES            0x80CA
+#define GL_BLEND_SRC_ALPHA_OES            0x80CB
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glBlendFuncSeparateOES (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 #endif
-typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-#endif
+#endif /* GL_OES_blend_func_separate */
 
-/* GL_OES_blend_subtract */
 #ifndef GL_OES_blend_subtract
 #define GL_OES_blend_subtract 1
+#define GL_BLEND_EQUATION_OES             0x8009
+#define GL_FUNC_ADD_OES                   0x8006
+#define GL_FUNC_SUBTRACT_OES              0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_OES      0x800B
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONOESPROC) (GLenum mode);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glBlendEquationOES (GLenum mode);
 #endif
-typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONOESPROC) (GLenum mode);
-#endif
+#endif /* GL_OES_blend_subtract */
 
-/* GL_OES_byte_coordinates */
 #ifndef GL_OES_byte_coordinates
 #define GL_OES_byte_coordinates 1
-#endif
+typedef khronos_int8_t GLbyte;
+#endif /* GL_OES_byte_coordinates */
 
-/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */
+
 #ifndef GL_OES_compressed_ETC1_RGB8_texture
 #define GL_OES_compressed_ETC1_RGB8_texture 1
-#endif
+#define GL_ETC1_RGB8_OES                  0x8D64
+#endif /* GL_OES_compressed_ETC1_RGB8_texture */
 
-/* GL_OES_depth24 */
 #ifndef GL_OES_depth24
 #define GL_OES_depth24 1
-#endif
+#define GL_DEPTH_COMPONENT24_OES          0x81A6
+#endif /* GL_OES_depth24 */
 
-/* GL_OES_depth32 */
 #ifndef GL_OES_depth32
 #define GL_OES_depth32 1
-#endif
+#define GL_DEPTH_COMPONENT32_OES          0x81A7
+#endif /* GL_OES_depth32 */
 
-/* GL_OES_draw_texture */
 #ifndef GL_OES_draw_texture
 #define GL_OES_draw_texture 1
+typedef short GLshort;
+#define GL_TEXTURE_CROP_RECT_OES          0x8B9D
+typedef void (GL_APIENTRYP PFNGLDRAWTEXSOESPROC) (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXIOESPROC) (GLint x, GLint y, GLint z, GLint width, GLint height);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXXOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXSVOESPROC) (const GLshort *coords);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXIVOESPROC) (const GLint *coords);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXXVOESPROC) (const GLfixed *coords);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXFOESPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
+typedef void (GL_APIENTRYP PFNGLDRAWTEXFVOESPROC) (const GLfloat *coords);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glDrawTexsOES (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
 GL_API void GL_APIENTRY glDrawTexiOES (GLint x, GLint y, GLint z, GLint width, GLint height);
@@ -618,357 +148,426 @@
 GL_API void GL_APIENTRY glDrawTexfOES (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
 GL_API void GL_APIENTRY glDrawTexfvOES (const GLfloat *coords);
 #endif
-typedef void (GL_APIENTRYP PFNGLDRAWTEXSOESPROC) (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXIOESPROC) (GLint x, GLint y, GLint z, GLint width, GLint height);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXXOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXSVOESPROC) (const GLshort *coords);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXIVOESPROC) (const GLint *coords);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXXVOESPROC) (const GLfixed *coords);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXFOESPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
-typedef void (GL_APIENTRYP PFNGLDRAWTEXFVOESPROC) (const GLfloat *coords);
-#endif
+#endif /* GL_OES_draw_texture */
 
-/* GL_OES_EGL_image */
-#ifndef GL_OES_EGL_image
-#define GL_OES_EGL_image 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
-GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
-#endif
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
-#endif
-
-/* GL_OES_EGL_image_external */
-#ifndef GL_OES_EGL_image_external
-#define GL_OES_EGL_image_external 1
-/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
-#endif
-
-/* GL_OES_element_index_uint */
 #ifndef GL_OES_element_index_uint
 #define GL_OES_element_index_uint 1
-#endif
+#define GL_UNSIGNED_INT                   0x1405
+#endif /* GL_OES_element_index_uint */
 
-/* GL_OES_extended_matrix_palette */
 #ifndef GL_OES_extended_matrix_palette
 #define GL_OES_extended_matrix_palette 1
-#endif
+#endif /* GL_OES_extended_matrix_palette */
 
-/* GL_OES_fbo_render_mipmap */
 #ifndef GL_OES_fbo_render_mipmap
 #define GL_OES_fbo_render_mipmap 1
-#endif
+#endif /* GL_OES_fbo_render_mipmap */
 
-/* GL_OES_fixed_point */
 #ifndef GL_OES_fixed_point
 #define GL_OES_fixed_point 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glAlphaFuncxOES (GLenum func, GLclampx ref);
-GL_API void GL_APIENTRY glClearColorxOES (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
-GL_API void GL_APIENTRY glClearDepthxOES (GLclampx depth);
-GL_API void GL_APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation);
-GL_API void GL_APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-GL_API void GL_APIENTRY glDepthRangexOES (GLclampx zNear, GLclampx zFar);
-GL_API void GL_APIENTRY glFogxOES (GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glFogxvOES (GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glFrustumxOES (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
-GL_API void GL_APIENTRY glGetClipPlanexOES (GLenum pname, GLfixed eqn[4]);
-GL_API void GL_APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetLightxvOES (GLenum light, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetMaterialxvOES (GLenum face, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetTexEnvxvOES (GLenum env, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glLightModelxOES (GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glLineWidthxOES (GLfixed width);
-GL_API void GL_APIENTRY glLoadMatrixxOES (const GLfixed *m);
-GL_API void GL_APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glMultMatrixxOES (const GLfixed *m);
-GL_API void GL_APIENTRY glMultiTexCoord4xOES (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
-GL_API void GL_APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz);
-GL_API void GL_APIENTRY glOrthoxOES (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
-GL_API void GL_APIENTRY glPointParameterxOES (GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glPointSizexOES (GLfixed size);
-GL_API void GL_APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
-GL_API void GL_APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-GL_API void GL_APIENTRY glSampleCoveragexOES (GLclampx value, GLboolean invert);
-GL_API void GL_APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
-GL_API void GL_APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
-GL_API void GL_APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z);
-#endif
-typedef void (GL_APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLclampx ref);
-typedef void (GL_APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
-typedef void (GL_APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLclampx depth);
+#define GL_FIXED_OES                      0x140C
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLfixed depth);
 typedef void (GL_APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation);
 typedef void (GL_APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-typedef void (GL_APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLclampx zNear, GLclampx zFar);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f);
 typedef void (GL_APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param);
-typedef void (GL_APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *params);
-typedef void (GL_APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
-typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum pname, GLfixed eqn[4]);
+typedef void (GL_APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (GL_APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation);
 typedef void (GL_APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params);
-typedef void (GL_APIENTRYP PFNGLGETLIGHTXVOESPROC) (GLenum light, GLenum pname, GLfixed *params);
-typedef void (GL_APIENTRYP PFNGLGETMATERIALXVOESPROC) (GLenum face, GLenum pname, GLfixed *params);
-typedef void (GL_APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum env, GLenum pname, GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param);
-typedef void (GL_APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param);
 typedef void (GL_APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param);
 typedef void (GL_APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width);
 typedef void (GL_APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m);
 typedef void (GL_APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
-typedef void (GL_APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param);
 typedef void (GL_APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m);
-typedef void (GL_APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GL_APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
 typedef void (GL_APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
-typedef void (GL_APIENTRYP PFNGLORTHOXOESPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar);
-typedef void (GL_APIENTRYP PFNGLPOINTPARAMETERXOESPROC) (GLenum pname, GLfixed param);
+typedef void (GL_APIENTRYP PFNGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
 typedef void (GL_APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
 typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
 typedef void (GL_APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEXOESPROC) (GLclampx value, GLboolean invert);
 typedef void (GL_APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
 typedef void (GL_APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
 typedef void (GL_APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
 typedef void (GL_APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
 typedef void (GL_APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (GL_APIENTRYP PFNGLGETLIGHTXVOESPROC) (GLenum light, GLenum pname, GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLGETMATERIALXVOESPROC) (GLenum face, GLenum pname, GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLPOINTPARAMETERXOESPROC) (GLenum pname, GLfixed param);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEXOESPROC) (GLclampx value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params);
+typedef void (GL_APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (GL_APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glAlphaFuncxOES (GLenum func, GLfixed ref);
+GL_API void GL_APIENTRY glClearColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GL_API void GL_APIENTRY glClearDepthxOES (GLfixed depth);
+GL_API void GL_APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation);
+GL_API void GL_APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GL_API void GL_APIENTRY glDepthRangexOES (GLfixed n, GLfixed f);
+GL_API void GL_APIENTRY glFogxOES (GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glFogxvOES (GLenum pname, const GLfixed *param);
+GL_API void GL_APIENTRY glFrustumxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GL_API void GL_APIENTRY glGetClipPlanexOES (GLenum plane, GLfixed *equation);
+GL_API void GL_APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glGetTexEnvxvOES (GLenum target, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glLightModelxOES (GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *param);
+GL_API void GL_APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glLineWidthxOES (GLfixed width);
+GL_API void GL_APIENTRY glLoadMatrixxOES (const GLfixed *m);
+GL_API void GL_APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *param);
+GL_API void GL_APIENTRY glMultMatrixxOES (const GLfixed *m);
+GL_API void GL_APIENTRY glMultiTexCoord4xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GL_API void GL_APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz);
+GL_API void GL_APIENTRY glOrthoxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GL_API void GL_APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glPointSizexOES (GLfixed size);
+GL_API void GL_APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
+GL_API void GL_APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+GL_API void GL_APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
+GL_API void GL_APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GL_API void GL_APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z);
+GL_API void GL_APIENTRY glGetLightxvOES (GLenum light, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glGetMaterialxvOES (GLenum face, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glPointParameterxOES (GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glSampleCoveragexOES (GLclampx value, GLboolean invert);
+GL_API void GL_APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params);
+GL_API void GL_APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param);
+GL_API void GL_APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params);
 #endif
+#endif /* GL_OES_fixed_point */
 
-/* GL_OES_framebuffer_object */
 #ifndef GL_OES_framebuffer_object
 #define GL_OES_framebuffer_object 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API GLboolean GL_APIENTRY glIsRenderbufferOES (GLuint renderbuffer);
-GL_API void GL_APIENTRY glBindRenderbufferOES (GLenum target, GLuint renderbuffer);
-GL_API void GL_APIENTRY glDeleteRenderbuffersOES (GLsizei n, const GLuint* renderbuffers);
-GL_API void GL_APIENTRY glGenRenderbuffersOES (GLsizei n, GLuint* renderbuffers);
-GL_API void GL_APIENTRY glRenderbufferStorageOES (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-GL_API void GL_APIENTRY glGetRenderbufferParameterivOES (GLenum target, GLenum pname, GLint* params);
-GL_API GLboolean GL_APIENTRY glIsFramebufferOES (GLuint framebuffer);
-GL_API void GL_APIENTRY glBindFramebufferOES (GLenum target, GLuint framebuffer);
-GL_API void GL_APIENTRY glDeleteFramebuffersOES (GLsizei n, const GLuint* framebuffers);
-GL_API void GL_APIENTRY glGenFramebuffersOES (GLsizei n, GLuint* framebuffers);
-GL_API GLenum GL_APIENTRY glCheckFramebufferStatusOES (GLenum target);
-GL_API void GL_APIENTRY glFramebufferRenderbufferOES (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-GL_API void GL_APIENTRY glFramebufferTexture2DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-GL_API void GL_APIENTRY glGetFramebufferAttachmentParameterivOES (GLenum target, GLenum attachment, GLenum pname, GLint* params);
-GL_API void GL_APIENTRY glGenerateMipmapOES (GLenum target);
-#endif
+#define GL_NONE_OES                       0
+#define GL_FRAMEBUFFER_OES                0x8D40
+#define GL_RENDERBUFFER_OES               0x8D41
+#define GL_RGBA4_OES                      0x8056
+#define GL_RGB5_A1_OES                    0x8057
+#define GL_RGB565_OES                     0x8D62
+#define GL_DEPTH_COMPONENT16_OES          0x81A5
+#define GL_RENDERBUFFER_WIDTH_OES         0x8D42
+#define GL_RENDERBUFFER_HEIGHT_OES        0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE_OES      0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_OES    0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_OES     0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_OES    0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_OES    0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_OES  0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
+#define GL_COLOR_ATTACHMENT0_OES          0x8CE0
+#define GL_DEPTH_ATTACHMENT_OES           0x8D00
+#define GL_STENCIL_ATTACHMENT_OES         0x8D20
+#define GL_FRAMEBUFFER_COMPLETE_OES       0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA
+#define GL_FRAMEBUFFER_UNSUPPORTED_OES    0x8CDD
+#define GL_FRAMEBUFFER_BINDING_OES        0x8CA6
+#define GL_RENDERBUFFER_BINDING_OES       0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE_OES      0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506
 typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFEROESPROC) (GLuint renderbuffer);
 typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFEROESPROC) (GLenum target, GLuint renderbuffer);
-typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSOESPROC) (GLsizei n, const GLuint* renderbuffers);
-typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSOESPROC) (GLsizei n, GLuint* renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSOESPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSOESPROC) (GLsizei n, GLuint *renderbuffers);
 typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) (GLenum target, GLenum pname, GLint* params);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) (GLenum target, GLenum pname, GLint *params);
 typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFEROESPROC) (GLuint framebuffer);
 typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFEROESPROC) (GLenum target, GLuint framebuffer);
-typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSOESPROC) (GLsizei n, const GLuint* framebuffers);
-typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSOESPROC) (GLsizei n, GLuint* framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSOESPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSOESPROC) (GLsizei n, GLuint *framebuffers);
 typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) (GLenum target);
 typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
 typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
 typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPOESPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API GLboolean GL_APIENTRY glIsRenderbufferOES (GLuint renderbuffer);
+GL_API void GL_APIENTRY glBindRenderbufferOES (GLenum target, GLuint renderbuffer);
+GL_API void GL_APIENTRY glDeleteRenderbuffersOES (GLsizei n, const GLuint *renderbuffers);
+GL_API void GL_APIENTRY glGenRenderbuffersOES (GLsizei n, GLuint *renderbuffers);
+GL_API void GL_APIENTRY glRenderbufferStorageOES (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_API void GL_APIENTRY glGetRenderbufferParameterivOES (GLenum target, GLenum pname, GLint *params);
+GL_API GLboolean GL_APIENTRY glIsFramebufferOES (GLuint framebuffer);
+GL_API void GL_APIENTRY glBindFramebufferOES (GLenum target, GLuint framebuffer);
+GL_API void GL_APIENTRY glDeleteFramebuffersOES (GLsizei n, const GLuint *framebuffers);
+GL_API void GL_APIENTRY glGenFramebuffersOES (GLsizei n, GLuint *framebuffers);
+GL_API GLenum GL_APIENTRY glCheckFramebufferStatusOES (GLenum target);
+GL_API void GL_APIENTRY glFramebufferRenderbufferOES (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_API void GL_APIENTRY glFramebufferTexture2DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_API void GL_APIENTRY glGetFramebufferAttachmentParameterivOES (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glGenerateMipmapOES (GLenum target);
 #endif
+#endif /* GL_OES_framebuffer_object */
 
-/* GL_OES_mapbuffer */
 #ifndef GL_OES_mapbuffer
 #define GL_OES_mapbuffer 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
-GL_API GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
-GL_API void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid ** params);
-#endif
-typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+#define GL_WRITE_ONLY_OES                 0x88B9
+#define GL_BUFFER_ACCESS_OES              0x88BB
+#define GL_BUFFER_MAPPED_OES              0x88BC
+#define GL_BUFFER_MAP_POINTER_OES         0x88BD
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
 typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
-typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid ** params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void *GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_API GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_API void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void **params);
 #endif
+#endif /* GL_OES_mapbuffer */
 
-/* GL_OES_matrix_get */
 #ifndef GL_OES_matrix_get
 #define GL_OES_matrix_get 1
-#endif
+#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898D
+#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898E
+#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898F
+#endif /* GL_OES_matrix_get */
 
-/* GL_OES_matrix_palette */
 #ifndef GL_OES_matrix_palette
 #define GL_OES_matrix_palette 1
+#define GL_MAX_VERTEX_UNITS_OES           0x86A4
+#define GL_MAX_PALETTE_MATRICES_OES       0x8842
+#define GL_MATRIX_PALETTE_OES             0x8840
+#define GL_MATRIX_INDEX_ARRAY_OES         0x8844
+#define GL_WEIGHT_ARRAY_OES               0x86AD
+#define GL_CURRENT_PALETTE_MATRIX_OES     0x8843
+#define GL_MATRIX_INDEX_ARRAY_SIZE_OES    0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_OES    0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_OES  0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_OES 0x8849
+#define GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 0x8B9E
+#define GL_WEIGHT_ARRAY_SIZE_OES          0x86AB
+#define GL_WEIGHT_ARRAY_TYPE_OES          0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_OES        0x86AA
+#define GL_WEIGHT_ARRAY_POINTER_OES       0x86AC
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_OES 0x889E
+typedef void (GL_APIENTRYP PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint matrixpaletteindex);
+typedef void (GL_APIENTRYP PFNGLLOADPALETTEFROMMODELVIEWMATRIXOESPROC) (void);
+typedef void (GL_APIENTRYP PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glCurrentPaletteMatrixOES (GLuint matrixpaletteindex);
 GL_API void GL_APIENTRY glLoadPaletteFromModelViewMatrixOES (void);
-GL_API void GL_APIENTRY glMatrixIndexPointerOES (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-GL_API void GL_APIENTRY glWeightPointerOES (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+GL_API void GL_APIENTRY glMatrixIndexPointerOES (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_API void GL_APIENTRY glWeightPointerOES (GLint size, GLenum type, GLsizei stride, const void *pointer);
 #endif
-typedef void (GL_APIENTRYP PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint matrixpaletteindex);
-typedef void (GL_APIENTRYP PFNGLLOADPALETTEFROMMODELVIEWMATRIXOESPROC) (void);
-typedef void (GL_APIENTRYP PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-typedef void (GL_APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-#endif
+#endif /* GL_OES_matrix_palette */
 
-/* GL_OES_packed_depth_stencil */
 #ifndef GL_OES_packed_depth_stencil
 #define GL_OES_packed_depth_stencil 1
-#endif
+#define GL_DEPTH_STENCIL_OES              0x84F9
+#define GL_UNSIGNED_INT_24_8_OES          0x84FA
+#define GL_DEPTH24_STENCIL8_OES           0x88F0
+#endif /* GL_OES_packed_depth_stencil */
 
-/* GL_OES_required_internalformat */
-#ifndef GL_OES_required_internalformat
-#define GL_OES_required_internalformat 1
-#endif
-
-/* GL_OES_query_matrix */
 #ifndef GL_OES_query_matrix
 #define GL_OES_query_matrix 1
+typedef GLbitfield (GL_APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_API GLbitfield GL_APIENTRY glQueryMatrixxOES (GLfixed mantissa[16], GLint exponent[16]);
+GL_API GLbitfield GL_APIENTRY glQueryMatrixxOES (GLfixed *mantissa, GLint *exponent);
 #endif
-typedef GLbitfield (GL_APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed mantissa[16], GLint exponent[16]);
-#endif
+#endif /* GL_OES_query_matrix */
 
-/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#define GL_ALPHA8_OES                     0x803C
+#define GL_LUMINANCE4_ALPHA4_OES          0x8043
+#define GL_LUMINANCE8_ALPHA8_OES          0x8045
+#define GL_LUMINANCE8_OES                 0x8040
+#define GL_RGB8_OES                       0x8051
+#define GL_RGBA8_OES                      0x8058
+#define GL_RGB10_EXT                      0x8052
+#define GL_RGB10_A2_EXT                   0x8059
+#endif /* GL_OES_required_internalformat */
+
 #ifndef GL_OES_rgb8_rgba8
 #define GL_OES_rgb8_rgba8 1
-#endif
+#endif /* GL_OES_rgb8_rgba8 */
 
-/* GL_OES_single_precision */
 #ifndef GL_OES_single_precision
 #define GL_OES_single_precision 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glDepthRangefOES (GLclampf zNear, GLclampf zFar);
-GL_API void GL_APIENTRY glFrustumfOES (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
-GL_API void GL_APIENTRY glOrthofOES (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
-GL_API void GL_APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation);
-GL_API void GL_APIENTRY glGetClipPlanefOES (GLenum pname, GLfloat eqn[4]);
-GL_API void GL_APIENTRY glClearDepthfOES (GLclampf depth);
-#endif
-typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf zNear, GLclampf zFar);
-typedef void (GL_APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
-typedef void (GL_APIENTRYP PFNGLORTHOFOESPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
-typedef void (GL_APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation);
-typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum pname, GLfloat eqn[4]);
+typedef khronos_float_t GLclampf;
 typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth);
+typedef void (GL_APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (GL_APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation);
+typedef void (GL_APIENTRYP PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glClearDepthfOES (GLclampf depth);
+GL_API void GL_APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation);
+GL_API void GL_APIENTRY glDepthRangefOES (GLclampf n, GLclampf f);
+GL_API void GL_APIENTRY glFrustumfOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+GL_API void GL_APIENTRY glGetClipPlanefOES (GLenum plane, GLfloat *equation);
+GL_API void GL_APIENTRY glOrthofOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
 #endif
+#endif /* GL_OES_single_precision */
 
-/* GL_OES_stencil1 */
 #ifndef GL_OES_stencil1
 #define GL_OES_stencil1 1
-#endif
+#define GL_STENCIL_INDEX1_OES             0x8D46
+#endif /* GL_OES_stencil1 */
 
-/* GL_OES_stencil4 */
 #ifndef GL_OES_stencil4
 #define GL_OES_stencil4 1
-#endif
+#define GL_STENCIL_INDEX4_OES             0x8D47
+#endif /* GL_OES_stencil4 */
 
-/* GL_OES_stencil8 */
 #ifndef GL_OES_stencil8
 #define GL_OES_stencil8 1
-#endif
+#define GL_STENCIL_INDEX8_OES             0x8D48
+#endif /* GL_OES_stencil8 */
 
-/* GL_OES_stencil_wrap */
 #ifndef GL_OES_stencil_wrap
 #define GL_OES_stencil_wrap 1
-#endif
+#define GL_INCR_WRAP_OES                  0x8507
+#define GL_DECR_WRAP_OES                  0x8508
+#endif /* GL_OES_stencil_wrap */
 
-/* GL_OES_texture_cube_map */
 #ifndef GL_OES_texture_cube_map
 #define GL_OES_texture_cube_map 1
+#define GL_NORMAL_MAP_OES                 0x8511
+#define GL_REFLECTION_MAP_OES             0x8512
+#define GL_TEXTURE_CUBE_MAP_OES           0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_OES   0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES  0x851C
+#define GL_TEXTURE_GEN_MODE_OES           0x2500
+#define GL_TEXTURE_GEN_STR_OES            0x8D60
+typedef void (GL_APIENTRYP PFNGLTEXGENFOESPROC) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXGENFVOESPROC) (GLenum coord, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXGENIOESPROC) (GLenum coord, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXGENIVOESPROC) (GLenum coord, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXGENFVOESPROC) (GLenum coord, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXGENIVOESPROC) (GLenum coord, GLenum pname, GLint *params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glTexGenfOES (GLenum coord, GLenum pname, GLfloat param);
 GL_API void GL_APIENTRY glTexGenfvOES (GLenum coord, GLenum pname, const GLfloat *params);
 GL_API void GL_APIENTRY glTexGeniOES (GLenum coord, GLenum pname, GLint param);
 GL_API void GL_APIENTRY glTexGenivOES (GLenum coord, GLenum pname, const GLint *params);
-GL_API void GL_APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param);
-GL_API void GL_APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params);
 GL_API void GL_APIENTRY glGetTexGenfvOES (GLenum coord, GLenum pname, GLfloat *params);
 GL_API void GL_APIENTRY glGetTexGenivOES (GLenum coord, GLenum pname, GLint *params);
-GL_API void GL_APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params);
 #endif
-typedef void (GL_APIENTRYP PFNGLTEXGENFOESPROC) (GLenum coord, GLenum pname, GLfloat param);
-typedef void (GL_APIENTRYP PFNGLTEXGENFVOESPROC) (GLenum coord, GLenum pname, const GLfloat *params);
-typedef void (GL_APIENTRYP PFNGLTEXGENIOESPROC) (GLenum coord, GLenum pname, GLint param);
-typedef void (GL_APIENTRYP PFNGLTEXGENIVOESPROC) (GLenum coord, GLenum pname, const GLint *params);
-typedef void (GL_APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
-typedef void (GL_APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params);
-typedef void (GL_APIENTRYP PFNGLGETTEXGENFVOESPROC) (GLenum coord, GLenum pname, GLfloat *params);
-typedef void (GL_APIENTRYP PFNGLGETTEXGENIVOESPROC) (GLenum coord, GLenum pname, GLint *params);
-typedef void (GL_APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params);
-#endif
+#endif /* GL_OES_texture_cube_map */
 
-/* GL_OES_texture_env_crossbar */
 #ifndef GL_OES_texture_env_crossbar
 #define GL_OES_texture_env_crossbar 1
-#endif
+#endif /* GL_OES_texture_env_crossbar */
 
-/* GL_OES_texture_mirrored_repeat */
 #ifndef GL_OES_texture_mirrored_repeat
 #define GL_OES_texture_mirrored_repeat 1
-#endif
+#define GL_MIRRORED_REPEAT_OES            0x8370
+#endif /* GL_OES_texture_mirrored_repeat */
 
-/* GL_OES_vertex_array_object */
 #ifndef GL_OES_vertex_array_object
 #define GL_OES_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_OES       0x85B5
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glBindVertexArrayOES (GLuint array);
 GL_API void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
 GL_API void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
 GL_API GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
 #endif
-typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
-typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
-typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
-typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
-#endif
+#endif /* GL_OES_vertex_array_object */
 
-/*------------------------------------------------------------------------*
- * AMD extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_AMD_compressed_3DC_texture */
 #ifndef GL_AMD_compressed_3DC_texture
 #define GL_AMD_compressed_3DC_texture 1
-#endif
+#define GL_3DC_X_AMD                      0x87F9
+#define GL_3DC_XY_AMD                     0x87FA
+#endif /* GL_AMD_compressed_3DC_texture */
 
-/* GL_AMD_compressed_ATC_texture */
 #ifndef GL_AMD_compressed_ATC_texture
 #define GL_AMD_compressed_ATC_texture 1
-#endif
+#define GL_ATC_RGB_AMD                    0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD    0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif /* GL_AMD_compressed_ATC_texture */
 
-/*------------------------------------------------------------------------*
- * APPLE extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_APPLE_copy_texture_levels */
 #ifndef GL_APPLE_copy_texture_levels
 #define GL_APPLE_copy_texture_levels 1
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
 #endif
-typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
-#endif
+#endif /* GL_APPLE_copy_texture_levels */
 
-/* GL_APPLE_framebuffer_multisample */
 #ifndef GL_APPLE_framebuffer_multisample
 #define GL_APPLE_framebuffer_multisample 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_API void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
-#endif /* GL_GLEXT_PROTOTYPES */
+#define GL_RENDERBUFFER_SAMPLES_APPLE     0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE              0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE         0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE         0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
 typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_API void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
 #endif
+#endif /* GL_APPLE_framebuffer_multisample */
 
-/* GL_APPLE_sync */
 #ifndef GL_APPLE_sync
 #define GL_APPLE_sync 1
+typedef struct __GLsync *GLsync;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_int64_t GLint64;
+#define GL_SYNC_OBJECT_APPLE              0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE  0x9111
+#define GL_OBJECT_TYPE_APPLE              0x9112
+#define GL_SYNC_CONDITION_APPLE           0x9113
+#define GL_SYNC_STATUS_APPLE              0x9114
+#define GL_SYNC_FLAGS_APPLE               0x9115
+#define GL_SYNC_FENCE_APPLE               0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE               0x9118
+#define GL_SIGNALED_APPLE                 0x9119
+#define GL_ALREADY_SIGNALED_APPLE         0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE          0x911B
+#define GL_CONDITION_SATISFIED_APPLE      0x911C
+#define GL_WAIT_FAILED_APPLE              0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE  0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE          0xFFFFFFFFFFFFFFFFull
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
 GL_API GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
@@ -978,138 +577,170 @@
 GL_API void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
 GL_API void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
 #endif
-typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
-typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
-typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
-typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
-typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
-typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
-typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
-#endif
+#endif /* GL_APPLE_sync */
 
-/* GL_APPLE_texture_2D_limited_npot */
 #ifndef GL_APPLE_texture_2D_limited_npot
 #define GL_APPLE_texture_2D_limited_npot 1
-#endif
+#endif /* GL_APPLE_texture_2D_limited_npot */
 
-/* GL_APPLE_texture_format_BGRA8888 */
 #ifndef GL_APPLE_texture_format_BGRA8888
 #define GL_APPLE_texture_format_BGRA8888 1
-#endif
+#define GL_BGRA_EXT                       0x80E1
+#define GL_BGRA8_EXT                      0x93A1
+#endif /* GL_APPLE_texture_format_BGRA8888 */
 
-/* GL_APPLE_texture_max_level */
 #ifndef GL_APPLE_texture_max_level
 #define GL_APPLE_texture_max_level 1
-#endif
+#define GL_TEXTURE_MAX_LEVEL_APPLE        0x813D
+#endif /* GL_APPLE_texture_max_level */
 
-/*------------------------------------------------------------------------*
- * ARM extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_ARM_rgba8 */
 #ifndef GL_ARM_rgba8
 #define GL_ARM_rgba8 1
-#endif
+#endif /* GL_ARM_rgba8 */
 
-/*------------------------------------------------------------------------*
- * EXT extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_EXT_blend_minmax */
 #ifndef GL_EXT_blend_minmax
 #define GL_EXT_blend_minmax 1
-#endif
+#define GL_MIN_EXT                        0x8007
+#define GL_MAX_EXT                        0x8008
+#endif /* GL_EXT_blend_minmax */
 
-/* GL_EXT_discard_framebuffer */
 #ifndef GL_EXT_discard_framebuffer
 #define GL_EXT_discard_framebuffer 1
+#define GL_COLOR_EXT                      0x1800
+#define GL_DEPTH_EXT                      0x1801
+#define GL_STENCIL_EXT                    0x1802
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
 #endif
-typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
-#endif
+#endif /* GL_EXT_discard_framebuffer */
 
-/* GL_EXT_map_buffer_range */
 #ifndef GL_EXT_map_buffer_range
 #define GL_EXT_map_buffer_range 1
+#define GL_MAP_READ_BIT_EXT               0x0001
+#define GL_MAP_WRITE_BIT_EXT              0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT   0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT  0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT     0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT     0x0020
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
 #ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY *glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_API void *GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
 GL_API void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
 #endif
-typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
-#endif
+#endif /* GL_EXT_map_buffer_range */
 
-/* GL_EXT_multisampled_render_to_texture */
-#ifndef GL_EXT_multisampled_render_to_texture
-#define GL_EXT_multisampled_render_to_texture 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
-#endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
-#endif
-
-/* GL_EXT_multi_draw_arrays */
 #ifndef GL_EXT_multi_draw_arrays
 #define GL_EXT_multi_draw_arrays 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei);
-GL_API void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* const*, GLsizei);
-#endif /* GL_GLEXT_PROTOTYPES */
 typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const*indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GL_API void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
 #endif
+#endif /* GL_EXT_multi_draw_arrays */
 
-/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define GL_RENDERBUFFER_SAMPLES_EXT       0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT                0x8D57
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+#endif /* GL_EXT_multisampled_render_to_texture */
+
 #ifndef GL_EXT_read_format_bgra
 #define GL_EXT_read_format_bgra 1
-#endif
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif /* GL_EXT_read_format_bgra */
 
-/* GL_EXT_robustness */
 #ifndef GL_EXT_robustness
 #define GL_EXT_robustness 1
+#define GL_GUILTY_CONTEXT_RESET_EXT       0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT     0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT      0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT      0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT      0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT      0x8261
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
 GL_API void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
-GL_API void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, float *params);
+GL_API void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
 GL_API void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
 #endif
-typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
-typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
-typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, float *params);
-typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
-#endif
+#endif /* GL_EXT_robustness */
 
-/* GL_EXT_sRGB */
 #ifndef GL_EXT_sRGB
 #define GL_EXT_sRGB 1
-#endif
+#define GL_SRGB_EXT                       0x8C40
+#define GL_SRGB_ALPHA_EXT                 0x8C42
+#define GL_SRGB8_ALPHA8_EXT               0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif /* GL_EXT_sRGB */
 
-/* GL_EXT_texture_compression_dxt1 */
 #ifndef GL_EXT_texture_compression_dxt1
 #define GL_EXT_texture_compression_dxt1 1
-#endif
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#endif /* GL_EXT_texture_compression_dxt1 */
 
-/* GL_EXT_texture_filter_anisotropic */
 #ifndef GL_EXT_texture_filter_anisotropic
 #define GL_EXT_texture_filter_anisotropic 1
-#endif
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
 
-/* GL_EXT_texture_format_BGRA8888 */
 #ifndef GL_EXT_texture_format_BGRA8888
 #define GL_EXT_texture_format_BGRA8888 1
-#endif
+#endif /* GL_EXT_texture_format_BGRA8888 */
 
-/* GL_EXT_texture_lod_bias */
 #ifndef GL_EXT_texture_lod_bias
 #define GL_EXT_texture_lod_bias 1
-#endif
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT       0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT     0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT           0x8501
+#endif /* GL_EXT_texture_lod_bias */
 
-/* GL_EXT_texture_storage */
 #ifndef GL_EXT_texture_storage
 #define GL_EXT_texture_storage 1
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT   0x912F
+#define GL_ALPHA8_EXT                     0x803C
+#define GL_LUMINANCE8_EXT                 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT          0x8045
+#define GL_RGBA32F_EXT                    0x8814
+#define GL_RGB32F_EXT                     0x8815
+#define GL_ALPHA32F_EXT                   0x8816
+#define GL_LUMINANCE32F_EXT               0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT         0x8819
+#define GL_RGBA16F_EXT                    0x881A
+#define GL_RGB16F_EXT                     0x881B
+#define GL_ALPHA16F_EXT                   0x881C
+#define GL_LUMINANCE16F_EXT               0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT         0x881F
+#define GL_R8_EXT                         0x8229
+#define GL_RG8_EXT                        0x822B
+#define GL_R32F_EXT                       0x822E
+#define GL_RG32F_EXT                      0x8230
+#define GL_R16F_EXT                       0x822D
+#define GL_RG16F_EXT                      0x822F
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
 GL_API void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
@@ -1118,71 +749,69 @@
 GL_API void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 GL_API void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #endif
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-#endif
+#endif /* GL_EXT_texture_storage */
 
-/*------------------------------------------------------------------------*
- * IMG extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_IMG_read_format */
-#ifndef GL_IMG_read_format
-#define GL_IMG_read_format 1
-#endif
-
-/* GL_IMG_texture_compression_pvrtc */
-#ifndef GL_IMG_texture_compression_pvrtc
-#define GL_IMG_texture_compression_pvrtc 1
-#endif
-
-/* GL_IMG_texture_env_enhanced_fixed_function */
-#ifndef GL_IMG_texture_env_enhanced_fixed_function
-#define GL_IMG_texture_env_enhanced_fixed_function 1
-#endif
-
-/* GL_IMG_user_clip_plane */
-#ifndef GL_IMG_user_clip_plane
-#define GL_IMG_user_clip_plane 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glClipPlanefIMG (GLenum, const GLfloat *);
-GL_API void GL_APIENTRY glClipPlanexIMG (GLenum, const GLfixed *);
-#endif
-typedef void (GL_APIENTRYP PFNGLCLIPPLANEFIMGPROC) (GLenum p, const GLfloat *eqn);
-typedef void (GL_APIENTRYP PFNGLCLIPPLANEXIMGPROC) (GLenum p, const GLfixed *eqn);
-#endif
-
-/* GL_IMG_multisampled_render_to_texture */
 #ifndef GL_IMG_multisampled_render_to_texture
 #define GL_IMG_multisampled_render_to_texture 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
-GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
-#endif
+#define GL_RENDERBUFFER_SAMPLES_IMG       0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG                0x9135
+#define GL_TEXTURE_SAMPLES_IMG            0x9136
 typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #endif
+#endif /* GL_IMG_multisampled_render_to_texture */
 
-/*------------------------------------------------------------------------*
- * NV extension functions
- *------------------------------------------------------------------------*/
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#define GL_BGRA_IMG                       0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif /* GL_IMG_read_format */
 
-/* NV_fence */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif /* GL_IMG_texture_compression_pvrtc */
+
+#ifndef GL_IMG_texture_env_enhanced_fixed_function
+#define GL_IMG_texture_env_enhanced_fixed_function 1
+#define GL_MODULATE_COLOR_IMG             0x8C04
+#define GL_RECIP_ADD_SIGNED_ALPHA_IMG     0x8C05
+#define GL_TEXTURE_ALPHA_MODULATE_IMG     0x8C06
+#define GL_FACTOR_ALPHA_MODULATE_IMG      0x8C07
+#define GL_FRAGMENT_ALPHA_MODULATE_IMG    0x8C08
+#define GL_ADD_BLEND_IMG                  0x8C09
+#define GL_DOT3_RGBA_IMG                  0x86AF
+#endif /* GL_IMG_texture_env_enhanced_fixed_function */
+
+#ifndef GL_IMG_user_clip_plane
+#define GL_IMG_user_clip_plane 1
+#define GL_CLIP_PLANE0_IMG                0x3000
+#define GL_CLIP_PLANE1_IMG                0x3001
+#define GL_CLIP_PLANE2_IMG                0x3002
+#define GL_CLIP_PLANE3_IMG                0x3003
+#define GL_CLIP_PLANE4_IMG                0x3004
+#define GL_CLIP_PLANE5_IMG                0x3005
+#define GL_MAX_CLIP_PLANES_IMG            0x0D32
+typedef void (GL_APIENTRYP PFNGLCLIPPLANEFIMGPROC) (GLenum p, const GLfloat *eqn);
+typedef void (GL_APIENTRYP PFNGLCLIPPLANEXIMGPROC) (GLenum p, const GLfixed *eqn);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glClipPlanefIMG (GLenum p, const GLfloat *eqn);
+GL_API void GL_APIENTRY glClipPlanexIMG (GLenum p, const GLfixed *eqn);
+#endif
+#endif /* GL_IMG_user_clip_plane */
+
 #ifndef GL_NV_fence
 #define GL_NV_fence 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glDeleteFencesNV (GLsizei, const GLuint *);
-GL_API void GL_APIENTRY glGenFencesNV (GLsizei, GLuint *);
-GL_API GLboolean GL_APIENTRY glIsFenceNV (GLuint);
-GL_API GLboolean GL_APIENTRY glTestFenceNV (GLuint);
-GL_API void GL_APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *);
-GL_API void GL_APIENTRY glFinishFenceNV (GLuint);
-GL_API void GL_APIENTRY glSetFenceNV (GLuint, GLenum);
-#endif
+#define GL_ALL_COMPLETED_NV               0x84F2
+#define GL_FENCE_STATUS_NV                0x84F3
+#define GL_FENCE_CONDITION_NV             0x84F4
 typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
 typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
 typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
@@ -1190,30 +819,53 @@
 typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
 typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
 typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_API void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_API GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_API GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_API void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_API void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
 #endif
+#endif /* GL_NV_fence */
 
-/*------------------------------------------------------------------------*
- * QCOM extension functions
- *------------------------------------------------------------------------*/
-
-/* GL_QCOM_driver_control */
 #ifndef GL_QCOM_driver_control
 #define GL_QCOM_driver_control 1
+typedef char GLchar;
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
 GL_API void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
 GL_API void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
 GL_API void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
 #endif
-typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
-typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
-typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
-typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
-#endif
+#endif /* GL_QCOM_driver_control */
 
-/* GL_QCOM_extended_get */
 #ifndef GL_QCOM_extended_get
 #define GL_QCOM_extended_get 1
+#define GL_TEXTURE_WIDTH_QCOM             0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM            0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM             0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM   0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM            0x8BD6
+#define GL_TEXTURE_TYPE_QCOM              0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM       0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM        0x8BD9
+#define GL_TEXTURE_TARGET_QCOM            0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM      0x8BDB
+#define GL_STATE_RESTORE                  0x8BDC
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **params);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
 GL_API void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
@@ -1221,58 +873,79 @@
 GL_API void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
 GL_API void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
 GL_API void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
-GL_API void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
-GL_API void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+GL_API void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels);
+GL_API void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **params);
 #endif
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
-typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
-typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
-typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
-typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
-#endif
+#endif /* GL_QCOM_extended_get */
 
-/* GL_QCOM_extended_get2 */
 #ifndef GL_QCOM_extended_get2
 #define GL_QCOM_extended_get2 1
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
 GL_API void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
 GL_API GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
 GL_API void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
 #endif
-typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
-typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
-typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
-typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
-#endif
+#endif /* GL_QCOM_extended_get2 */
 
-/* GL_QCOM_perfmon_global_mode */
 #ifndef GL_QCOM_perfmon_global_mode
 #define GL_QCOM_perfmon_global_mode 1
-#endif
+#define GL_PERFMON_GLOBAL_MODE_QCOM       0x8FA0
+#endif /* GL_QCOM_perfmon_global_mode */
 
-/* GL_QCOM_writeonly_rendering */
-#ifndef GL_QCOM_writeonly_rendering
-#define GL_QCOM_writeonly_rendering 1
-#endif
-
-/* GL_QCOM_tiled_rendering */
 #ifndef GL_QCOM_tiled_rendering
 #define GL_QCOM_tiled_rendering 1
+#define GL_COLOR_BUFFER_BIT0_QCOM         0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM         0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM         0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM         0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM         0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM         0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM         0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM         0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM         0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM         0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM         0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM         0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM         0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM         0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM         0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM         0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM       0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM       0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM       0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM       0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM       0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM       0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM       0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM       0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM   0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM   0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM   0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM   0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM   0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM   0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM   0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM   0x80000000
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_API void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
 GL_API void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
 #endif
-typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
-typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
-#endif
+#endif /* GL_QCOM_tiled_rendering */
+
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#define GL_WRITEONLY_RENDERING_QCOM       0x8823
+#endif /* GL_QCOM_writeonly_rendering */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __glext_h_ */
-
+#endif
diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h
index 2db6ee2..16060a9 100644
--- a/opengl/include/GLES/glplatform.h
+++ b/opengl/include/GLES/glplatform.h
@@ -1,20 +1,28 @@
 #ifndef __glplatform_h_
 #define __glplatform_h_
 
-/* $Revision: 10601 $ on $Date:: 2010-03-04 22:15:27 -0800 #$ */
-
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
+** Copyright (c) 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.
+*/
 
 /* Platform-specific types and definitions for OpenGL ES 1.X  gl.h
  *
  * Adopters may modify khrplatform.h and this file to suit their platform.
- * You are encouraged to submit all modifications to the Khronos group so that
- * they can be included in future versions of this file.  Please submit changes
- * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
- * by filing a bug against product "OpenGL-ES" component "Registry".
+ * Please contribute modifications back to Khronos as pull requests on the
+ * public github repository:
+ *      https://github.com/KhronosGroup/OpenGL-Registry
  */
 
 #include <KHR/khrplatform.h>
diff --git a/opengl/include/GLES2/NOTICE b/opengl/include/GLES2/NOTICE
index 7a94373..710388f 100644
--- a/opengl/include/GLES2/NOTICE
+++ b/opengl/include/GLES2/NOTICE
@@ -1,4 +1,18 @@
-Copyright (c) 2013-2015 The Khronos Group Inc.
+Copyright (c) 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.
+
+Copyright (c) 2013-2017 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
@@ -18,3 +32,4 @@
 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.
+
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
index f64ec00..8819e30 100644
--- a/opengl/include/GLES2/gl2.h
+++ b/opengl/include/GLES2/gl2.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-2017 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
@@ -31,9 +31,7 @@
 ** This header is generated from the Khronos OpenGL / OpenGL ES XML
 ** API Registry. The current version of the Registry, generator scripts
 ** used to make the header, and the header can be found at
-**   http://www.opengl.org/registry/
-**
-** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+**   https://github.com/KhronosGroup/OpenGL-Registry
 */
 
 #include <GLES2/gl2platform.h>
@@ -42,11 +40,11 @@
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-#if !defined(GL_GLES_PROTOTYPES)
+#ifndef GL_GLES_PROTOTYPES
 #define GL_GLES_PROTOTYPES 1
 #endif
 
-/* Generated on date 20151015 */
+/* Generated on date 20170613 */
 
 /* Generated C header for:
  * API: gles2
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 2d05596..b5eb723 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-2017 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
@@ -31,16 +31,14 @@
 ** This header is generated from the Khronos OpenGL / OpenGL ES XML
 ** API Registry. The current version of the Registry, generator scripts
 ** used to make the header, and the header can be found at
-**   http://www.opengl.org/registry/
-**
-** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+**   https://github.com/KhronosGroup/OpenGL-Registry
 */
 
 #ifndef GL_APIENTRYP
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-/* Generated on date 20151015 */
+/* Generated on date 20170613 */
 
 /* Generated C header for:
  * API: gles2
@@ -752,6 +750,34 @@
 #define GL_INT_10_10_10_2_OES             0x8DF7
 #endif /* GL_OES_vertex_type_10_10_10_2 */
 
+#ifndef GL_OES_viewport_array
+#define GL_OES_viewport_array 1
+#define GL_MAX_VIEWPORTS_OES              0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_OES     0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_OES      0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFOESPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVOESPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVOESPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDOESPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVOESPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFOESPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VOESPROC) (GLenum target, GLuint index, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfOES (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvOES (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvOES (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedOES (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvOES (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfOES (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vOES (GLenum target, GLuint index, GLfloat *data);
+#endif
+#endif /* GL_OES_viewport_array */
+
 #ifndef GL_AMD_compressed_3DC_texture
 #define GL_AMD_compressed_3DC_texture 1
 #define GL_3DC_X_AMD                      0x87F9
@@ -1025,6 +1051,10 @@
 #define GL_SHADER_BINARY_DMP              0x9250
 #endif /* GL_DMP_shader_binary */
 
+#ifndef GL_EXT_EGL_image_array
+#define GL_EXT_EGL_image_array 1
+#endif /* GL_EXT_EGL_image_array */
+
 #ifndef GL_EXT_YUV_target
 #define GL_EXT_YUV_target 1
 #define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT    0x8BE7
@@ -1086,6 +1116,31 @@
 #endif
 #endif /* GL_EXT_buffer_storage */
 
+#ifndef GL_EXT_clear_texture
+#define GL_EXT_clear_texture 1
+typedef void (GL_APIENTRYP PFNGLCLEARTEXIMAGEEXTPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (GL_APIENTRYP PFNGLCLEARTEXSUBIMAGEEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glClearTexImageEXT (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GL_APICALL void GL_APIENTRY glClearTexSubImageEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#endif
+#endif /* GL_EXT_clear_texture */
+
+#ifndef GL_EXT_clip_cull_distance
+#define GL_EXT_clip_cull_distance 1
+#define GL_MAX_CLIP_DISTANCES_EXT         0x0D32
+#define GL_MAX_CULL_DISTANCES_EXT         0x82F9
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define GL_CLIP_DISTANCE0_EXT             0x3000
+#define GL_CLIP_DISTANCE1_EXT             0x3001
+#define GL_CLIP_DISTANCE2_EXT             0x3002
+#define GL_CLIP_DISTANCE3_EXT             0x3003
+#define GL_CLIP_DISTANCE4_EXT             0x3004
+#define GL_CLIP_DISTANCE5_EXT             0x3005
+#define GL_CLIP_DISTANCE6_EXT             0x3006
+#define GL_CLIP_DISTANCE7_EXT             0x3007
+#endif /* GL_EXT_clip_cull_distance */
+
 #ifndef GL_EXT_color_buffer_float
 #define GL_EXT_color_buffer_float 1
 #endif /* GL_EXT_color_buffer_float */
@@ -1100,6 +1155,10 @@
 #define GL_UNSIGNED_NORMALIZED_EXT        0x8C17
 #endif /* GL_EXT_color_buffer_half_float */
 
+#ifndef GL_EXT_conservative_depth
+#define GL_EXT_conservative_depth 1
+#endif /* GL_EXT_conservative_depth */
+
 #ifndef GL_EXT_copy_image
 #define GL_EXT_copy_image 1
 typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
@@ -1271,6 +1330,27 @@
 #endif
 #endif /* GL_EXT_draw_instanced */
 
+#ifndef GL_EXT_draw_transform_feedback
+#define GL_EXT_draw_transform_feedback 1
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKEXTPROC) (GLenum mode, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackEXT (GLenum mode, GLuint id);
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackInstancedEXT (GLenum mode, GLuint id, GLsizei instancecount);
+#endif
+#endif /* GL_EXT_draw_transform_feedback */
+
+#ifndef GL_EXT_external_buffer
+#define GL_EXT_external_buffer 1
+typedef void *GLeglClientBufferEXT;
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTERNALEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageExternalEXT (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#endif
+#endif /* GL_EXT_external_buffer */
+
 #ifndef GL_EXT_float_blend
 #define GL_EXT_float_blend 1
 #endif /* GL_EXT_float_blend */
@@ -1349,6 +1429,85 @@
 #endif
 #endif /* GL_EXT_map_buffer_range */
 
+#ifndef GL_EXT_memory_object
+#define GL_EXT_memory_object 1
+#define GL_TEXTURE_TILING_EXT             0x9580
+#define GL_DEDICATED_MEMORY_OBJECT_EXT    0x9581
+#define GL_PROTECTED_MEMORY_OBJECT_EXT    0x959B
+#define GL_NUM_TILING_TYPES_EXT           0x9582
+#define GL_TILING_TYPES_EXT               0x9583
+#define GL_OPTIMAL_TILING_EXT             0x9584
+#define GL_LINEAR_TILING_EXT              0x9585
+#define GL_NUM_DEVICE_UUIDS_EXT           0x9596
+#define GL_DEVICE_UUID_EXT                0x9597
+#define GL_DRIVER_UUID_EXT                0x9598
+#define GL_UUID_SIZE_EXT                  16
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEVEXTPROC) (GLenum pname, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEI_VEXTPROC) (GLenum target, GLuint index, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLDELETEMEMORYOBJECTSEXTPROC) (GLsizei n, const GLuint *memoryObjects);
+typedef GLboolean (GL_APIENTRYP PFNGLISMEMORYOBJECTEXTPROC) (GLuint memoryObject);
+typedef void (GL_APIENTRYP PFNGLCREATEMEMORYOBJECTSEXTPROC) (GLsizei n, GLuint *memoryObjects);
+typedef void (GL_APIENTRYP PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEMEMEXTPROC) (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetUnsignedBytevEXT (GLenum pname, GLubyte *data);
+GL_APICALL void GL_APIENTRY glGetUnsignedBytei_vEXT (GLenum target, GLuint index, GLubyte *data);
+GL_APICALL void GL_APIENTRY glDeleteMemoryObjectsEXT (GLsizei n, const GLuint *memoryObjects);
+GL_APICALL GLboolean GL_APIENTRY glIsMemoryObjectEXT (GLuint memoryObject);
+GL_APICALL void GL_APIENTRY glCreateMemoryObjectsEXT (GLsizei n, GLuint *memoryObjects);
+GL_APICALL void GL_APIENTRY glMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glGetMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glBufferStorageMemEXT (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageMemEXT (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_EXT_memory_object */
+
+#ifndef GL_EXT_memory_object_fd
+#define GL_EXT_memory_object_fd 1
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT      0x9586
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYFDEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryFdEXT (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_memory_object_fd */
+
+#ifndef GL_EXT_memory_object_win32
+#define GL_EXT_memory_object_win32 1
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT   0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_DEVICE_LUID_EXT                0x9599
+#define GL_DEVICE_NODE_MASK_EXT           0x959A
+#define GL_LUID_SIZE_EXT                  8
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT    0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryWin32HandleEXT (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_memory_object_win32 */
+
 #ifndef GL_EXT_multi_draw_arrays
 #define GL_EXT_multi_draw_arrays 1
 typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
@@ -1412,6 +1571,15 @@
 #define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
 #endif /* GL_EXT_occlusion_query_boolean */
 
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT       0x8E1B
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
 #ifndef GL_EXT_post_depth_coverage
 #define GL_EXT_post_depth_coverage 1
 #endif /* GL_EXT_post_depth_coverage */
@@ -1425,6 +1593,12 @@
 #endif
 #endif /* GL_EXT_primitive_bounding_box */
 
+#ifndef GL_EXT_protected_textures
+#define GL_EXT_protected_textures 1
+#define GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define GL_TEXTURE_PROTECTED_EXT          0x8BFA
+#endif /* GL_EXT_protected_textures */
+
 #ifndef GL_EXT_pvrtc_sRGB
 #define GL_EXT_pvrtc_sRGB 1
 #define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
@@ -1499,6 +1673,53 @@
 #define GL_FRAMEBUFFER_SRGB_EXT           0x8DB9
 #endif /* GL_EXT_sRGB_write_control */
 
+#ifndef GL_EXT_semaphore
+#define GL_EXT_semaphore 1
+#define GL_LAYOUT_GENERAL_EXT             0x958D
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT    0x958E
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT    0x9591
+#define GL_LAYOUT_TRANSFER_SRC_EXT        0x9592
+#define GL_LAYOUT_TRANSFER_DST_EXT        0x9593
+typedef void (GL_APIENTRYP PFNGLGENSEMAPHORESEXTPROC) (GLsizei n, GLuint *semaphores);
+typedef void (GL_APIENTRYP PFNGLDELETESEMAPHORESEXTPROC) (GLsizei n, const GLuint *semaphores);
+typedef GLboolean (GL_APIENTRYP PFNGLISSEMAPHOREEXTPROC) (GLuint semaphore);
+typedef void (GL_APIENTRYP PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, const GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLWAITSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+typedef void (GL_APIENTRYP PFNGLSIGNALSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenSemaphoresEXT (GLsizei n, GLuint *semaphores);
+GL_APICALL void GL_APIENTRY glDeleteSemaphoresEXT (GLsizei n, const GLuint *semaphores);
+GL_APICALL GLboolean GL_APIENTRY glIsSemaphoreEXT (GLuint semaphore);
+GL_APICALL void GL_APIENTRY glSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, const GLuint64 *params);
+GL_APICALL void GL_APIENTRY glGetSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, GLuint64 *params);
+GL_APICALL void GL_APIENTRY glWaitSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+GL_APICALL void GL_APIENTRY glSignalSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#endif
+#endif /* GL_EXT_semaphore */
+
+#ifndef GL_EXT_semaphore_fd
+#define GL_EXT_semaphore_fd 1
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREFDEXTPROC) (GLuint semaphore, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreFdEXT (GLuint semaphore, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_semaphore_fd */
+
+#ifndef GL_EXT_semaphore_win32
+#define GL_EXT_semaphore_win32 1
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT    0x9594
+#define GL_D3D12_FENCE_VALUE_EXT          0x9595
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) (GLuint semaphore, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) (GLuint semaphore, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32HandleEXT (GLuint semaphore, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_semaphore_win32 */
+
 #ifndef GL_EXT_separate_shader_objects
 #define GL_EXT_separate_shader_objects 1
 #define GL_ACTIVE_PROGRAM_EXT             0x8259
@@ -1604,6 +1825,10 @@
 #define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
 #endif /* GL_EXT_shader_framebuffer_fetch */
 
+#ifndef GL_EXT_shader_group_vote
+#define GL_EXT_shader_group_vote 1
+#endif /* GL_EXT_shader_group_vote */
+
 #ifndef GL_EXT_shader_implicit_conversions
 #define GL_EXT_shader_implicit_conversions 1
 #endif /* GL_EXT_shader_implicit_conversions */
@@ -1616,6 +1841,10 @@
 #define GL_EXT_shader_io_blocks 1
 #endif /* GL_EXT_shader_io_blocks */
 
+#ifndef GL_EXT_shader_non_constant_global_initializers
+#define GL_EXT_shader_non_constant_global_initializers 1
+#endif /* GL_EXT_shader_non_constant_global_initializers */
+
 #ifndef GL_EXT_shader_pixel_local_storage
 #define GL_EXT_shader_pixel_local_storage 1
 #define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
@@ -1623,6 +1852,21 @@
 #define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
 #endif /* GL_EXT_shader_pixel_local_storage */
 
+#ifndef GL_EXT_shader_pixel_local_storage2
+#define GL_EXT_shader_pixel_local_storage2 1
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target, GLsizei size);
+typedef GLsizei (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target);
+typedef void (GL_APIENTRYP PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) (GLsizei offset, GLsizei n, const GLuint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageSizeEXT (GLuint target, GLsizei size);
+GL_APICALL GLsizei GL_APIENTRY glGetFramebufferPixelLocalStorageSizeEXT (GLuint target);
+GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsizei n, const GLuint *values);
+#endif
+#endif /* GL_EXT_shader_pixel_local_storage2 */
+
 #ifndef GL_EXT_shader_texture_lod
 #define GL_EXT_shader_texture_lod 1
 #endif /* GL_EXT_shader_texture_lod */
@@ -1656,6 +1900,10 @@
 #endif
 #endif /* GL_EXT_sparse_texture */
 
+#ifndef GL_EXT_sparse_texture2
+#define GL_EXT_sparse_texture2 1
+#endif /* GL_EXT_sparse_texture2 */
+
 #ifndef GL_EXT_tessellation_point_size
 #define GL_EXT_tessellation_point_size 1
 #endif /* GL_EXT_tessellation_point_size */
@@ -1759,6 +2007,11 @@
 #endif
 #endif /* GL_EXT_texture_buffer */
 
+#ifndef GL_EXT_texture_compression_astc_decode_mode
+#define GL_EXT_texture_compression_astc_decode_mode 1
+#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
+#endif /* GL_EXT_texture_compression_astc_decode_mode */
+
 #ifndef GL_EXT_texture_compression_dxt1
 #define GL_EXT_texture_compression_dxt1 1
 #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
@@ -1888,11 +2141,67 @@
 #define GL_UNPACK_SKIP_PIXELS_EXT         0x0CF4
 #endif /* GL_EXT_unpack_subimage */
 
+#ifndef GL_EXT_win32_keyed_mutex
+#define GL_EXT_win32_keyed_mutex 1
+typedef GLboolean (GL_APIENTRYP PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key, GLuint timeout);
+typedef GLboolean (GL_APIENTRYP PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLboolean GL_APIENTRY glAcquireKeyedMutexWin32EXT (GLuint memory, GLuint64 key, GLuint timeout);
+GL_APICALL GLboolean GL_APIENTRY glReleaseKeyedMutexWin32EXT (GLuint memory, GLuint64 key);
+#endif
+#endif /* GL_EXT_win32_keyed_mutex */
+
+#ifndef GL_EXT_window_rectangles
+#define GL_EXT_window_rectangles 1
+#define GL_INCLUSIVE_EXT                  0x8F10
+#define GL_EXCLUSIVE_EXT                  0x8F11
+#define GL_WINDOW_RECTANGLE_EXT           0x8F12
+#define GL_WINDOW_RECTANGLE_MODE_EXT      0x8F13
+#define GL_MAX_WINDOW_RECTANGLES_EXT      0x8F14
+#define GL_NUM_WINDOW_RECTANGLES_EXT      0x8F15
+typedef void (GL_APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box);
+#endif
+#endif /* GL_EXT_window_rectangles */
+
 #ifndef GL_FJ_shader_binary_GCCSO
 #define GL_FJ_shader_binary_GCCSO 1
 #define GL_GCCSO_SHADER_BINARY_FJ         0x9260
 #endif /* GL_FJ_shader_binary_GCCSO */
 
+#ifndef GL_IMG_bindless_texture
+#define GL_IMG_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLEIMGPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEIMGPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64IMGPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VIMGPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64IMGPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VIMGPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleIMG (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleIMG (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glUniformHandleui64IMG (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vIMG (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64IMG (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vIMG (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+#endif
+#endif /* GL_IMG_bindless_texture */
+
+#ifndef GL_IMG_framebuffer_downsample
+#define GL_IMG_framebuffer_downsample 1
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
+#define GL_NUM_DOWNSAMPLE_SCALES_IMG      0x913D
+#define GL_DOWNSAMPLE_SCALES_IMG          0x913E
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DDownsampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayerDownsampleIMG (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#endif
+#endif /* GL_IMG_framebuffer_downsample */
+
 #ifndef GL_IMG_multisampled_render_to_texture
 #define GL_IMG_multisampled_render_to_texture 1
 #define GL_RENDERBUFFER_SAMPLES_IMG       0x9133
@@ -1944,6 +2253,11 @@
 #define GL_CUBIC_MIPMAP_LINEAR_IMG        0x913B
 #endif /* GL_IMG_texture_filter_cubic */
 
+#ifndef GL_INTEL_conservative_rasterization
+#define GL_INTEL_conservative_rasterization 1
+#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
+#endif /* GL_INTEL_conservative_rasterization */
+
 #ifndef GL_INTEL_framebuffer_CMAA
 #define GL_INTEL_framebuffer_CMAA 1
 typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
@@ -1998,6 +2312,14 @@
 #endif
 #endif /* GL_INTEL_performance_query */
 
+#ifndef GL_MESA_shader_integer_functions
+#define GL_MESA_shader_integer_functions 1
+#endif /* GL_MESA_shader_integer_functions */
+
+#ifndef GL_NVX_blend_equation_advanced_multi_draw_buffers
+#define GL_NVX_blend_equation_advanced_multi_draw_buffers 1
+#endif /* GL_NVX_blend_equation_advanced_multi_draw_buffers */
+
 #ifndef GL_NV_bindless_texture
 #define GL_NV_bindless_texture 1
 typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
@@ -2120,6 +2442,17 @@
 #endif
 #endif /* GL_NV_conservative_raster */
 
+#ifndef GL_NV_conservative_raster_pre_snap_triangles
+#define GL_NV_conservative_raster_pre_snap_triangles 1
+#define GL_CONSERVATIVE_RASTER_MODE_NV    0x954D
+#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E
+#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F
+typedef void (GL_APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param);
+#endif
+#endif /* GL_NV_conservative_raster_pre_snap_triangles */
+
 #ifndef GL_NV_copy_buffer
 #define GL_NV_copy_buffer 1
 #define GL_COPY_READ_BUFFER_NV            0x8F36
@@ -2205,6 +2538,23 @@
 #endif
 #endif /* GL_NV_draw_instanced */
 
+#ifndef GL_NV_draw_vulkan_image
+#define GL_NV_draw_vulkan_image 1
+typedef void (GL_APIENTRY  *GLVULKANPROCNV)(void);
+typedef void (GL_APIENTRYP PFNGLDRAWVKIMAGENVPROC) (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+typedef GLVULKANPROCNV (GL_APIENTRYP PFNGLGETVKPROCADDRNVPROC) (const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLWAITVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
+typedef void (GL_APIENTRYP PFNGLSIGNALVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
+typedef void (GL_APIENTRYP PFNGLSIGNALVKFENCENVPROC) (GLuint64 vkFence);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawVkImageNV (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+GL_APICALL GLVULKANPROCNV GL_APIENTRY glGetVkProcAddrNV (const GLchar *name);
+GL_APICALL void GL_APIENTRY glWaitVkSemaphoreNV (GLuint64 vkSemaphore);
+GL_APICALL void GL_APIENTRY glSignalVkSemaphoreNV (GLuint64 vkSemaphore);
+GL_APICALL void GL_APIENTRY glSignalVkFenceNV (GLuint64 vkFence);
+#endif
+#endif /* GL_NV_draw_vulkan_image */
+
 #ifndef GL_NV_explicit_attrib_location
 #define GL_NV_explicit_attrib_location 1
 #endif /* GL_NV_explicit_attrib_location */
@@ -2307,6 +2657,109 @@
 #define GL_NV_geometry_shader_passthrough 1
 #endif /* GL_NV_geometry_shader_passthrough */
 
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64EXT;
+#define GL_INT64_NV                       0x140E
+#define GL_UNSIGNED_INT64_NV              0x140F
+#define GL_INT8_NV                        0x8FE0
+#define GL_INT8_VEC2_NV                   0x8FE1
+#define GL_INT8_VEC3_NV                   0x8FE2
+#define GL_INT8_VEC4_NV                   0x8FE3
+#define GL_INT16_NV                       0x8FE4
+#define GL_INT16_VEC2_NV                  0x8FE5
+#define GL_INT16_VEC3_NV                  0x8FE6
+#define GL_INT16_VEC4_NV                  0x8FE7
+#define GL_INT64_VEC2_NV                  0x8FE9
+#define GL_INT64_VEC3_NV                  0x8FEA
+#define GL_INT64_VEC4_NV                  0x8FEB
+#define GL_UNSIGNED_INT8_NV               0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV          0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV          0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV          0x8FEF
+#define GL_UNSIGNED_INT16_NV              0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV         0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV         0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV         0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV         0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV         0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV         0x8FF7
+#define GL_FLOAT16_NV                     0x8FF8
+#define GL_FLOAT16_VEC2_NV                0x8FF9
+#define GL_FLOAT16_VEC3_NV                0x8FFA
+#define GL_FLOAT16_VEC4_NV                0x8FFB
+#define GL_PATCHES                        0x000E
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_gpu_shader5 */
+
 #ifndef GL_NV_image_formats
 #define GL_NV_image_formats 1
 #endif /* GL_NV_image_formats */
@@ -2713,6 +3166,10 @@
 #define GL_NV_sample_mask_override_coverage 1
 #endif /* GL_NV_sample_mask_override_coverage */
 
+#ifndef GL_NV_shader_atomic_fp16_vector
+#define GL_NV_shader_atomic_fp16_vector 1
+#endif /* GL_NV_shader_atomic_fp16_vector */
+
 #ifndef GL_NV_shader_noperspective_interpolation
 #define GL_NV_shader_noperspective_interpolation 1
 #endif /* GL_NV_shader_noperspective_interpolation */
@@ -2779,11 +3236,32 @@
 #define GL_NV_viewport_array2 1
 #endif /* GL_NV_viewport_array2 */
 
+#ifndef GL_NV_viewport_swizzle
+#define GL_NV_viewport_swizzle 1
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357
+#define GL_VIEWPORT_SWIZZLE_X_NV          0x9358
+#define GL_VIEWPORT_SWIZZLE_Y_NV          0x9359
+#define GL_VIEWPORT_SWIZZLE_Z_NV          0x935A
+#define GL_VIEWPORT_SWIZZLE_W_NV          0x935B
+typedef void (GL_APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#endif
+#endif /* GL_NV_viewport_swizzle */
+
 #ifndef GL_OVR_multiview
 #define GL_OVR_multiview 1
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
 #define GL_MAX_VIEWS_OVR                  0x9631
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
 typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
@@ -2882,11 +3360,32 @@
 #endif
 #endif /* GL_QCOM_extended_get2 */
 
+#ifndef GL_QCOM_framebuffer_foveated
+#define GL_QCOM_framebuffer_foveated 1
+#define GL_FOVEATION_ENABLE_BIT_QCOM      0x00000001
+#define GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM 0x00000002
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC) (GLuint framebuffer, GLuint numLayers, GLuint focalPointsPerLayer, GLuint requestedFeatures, GLuint *providedFeatures);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC) (GLuint framebuffer, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFoveationConfigQCOM (GLuint framebuffer, GLuint numLayers, GLuint focalPointsPerLayer, GLuint requestedFeatures, GLuint *providedFeatures);
+GL_APICALL void GL_APIENTRY glFramebufferFoveationParametersQCOM (GLuint framebuffer, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#endif
+#endif /* GL_QCOM_framebuffer_foveated */
+
 #ifndef GL_QCOM_perfmon_global_mode
 #define GL_QCOM_perfmon_global_mode 1
 #define GL_PERFMON_GLOBAL_MODE_QCOM       0x8FA0
 #endif /* GL_QCOM_perfmon_global_mode */
 
+#ifndef GL_QCOM_shader_framebuffer_fetch_noncoherent
+#define GL_QCOM_shader_framebuffer_fetch_noncoherent 1
+#define GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM 0x96A2
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIERQCOMPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFetchBarrierQCOM (void);
+#endif
+#endif /* GL_QCOM_shader_framebuffer_fetch_noncoherent */
+
 #ifndef GL_QCOM_tiled_rendering
 #define GL_QCOM_tiled_rendering 1
 #define GL_COLOR_BUFFER_BIT0_QCOM         0x00000001
diff --git a/opengl/include/GLES2/gl2platform.h b/opengl/include/GLES2/gl2platform.h
index 89d4d44..eb318dc 100644
--- a/opengl/include/GLES2/gl2platform.h
+++ b/opengl/include/GLES2/gl2platform.h
@@ -1,20 +1,28 @@
 #ifndef __gl2platform_h_
 #define __gl2platform_h_
 
-/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
-
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
+** Copyright (c) 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.
+*/
 
 /* Platform-specific types and definitions for OpenGL ES 2.X  gl2.h
  *
  * Adopters may modify khrplatform.h and this file to suit their platform.
- * You are encouraged to submit all modifications to the Khronos group so that
- * they can be included in future versions of this file.  Please submit changes
- * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
- * by filing a bug against product "OpenGL-ES" component "Registry".
+ * Please contribute modifications back to Khronos as pull requests on the
+ * public github repository:
+ *      https://github.com/KhronosGroup/OpenGL-Registry
  */
 
 #include <KHR/khrplatform.h>
diff --git a/opengl/include/GLES3/NOTICE b/opengl/include/GLES3/NOTICE
index 7a94373..73e9f18 100644
--- a/opengl/include/GLES3/NOTICE
+++ b/opengl/include/GLES3/NOTICE
@@ -1,4 +1,21 @@
-Copyright (c) 2013-2015 The Khronos Group Inc.
+This document is licensed under the SGI Free Software B License Version
+2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+
+Copyright (c) 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.
+
+Copyright (c) 2013-2017 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
@@ -18,3 +35,4 @@
 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.
+
diff --git a/opengl/include/GLES3/gl3.h b/opengl/include/GLES3/gl3.h
index d51d2e6..f1f3a65 100644
--- a/opengl/include/GLES3/gl3.h
+++ b/opengl/include/GLES3/gl3.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-2017 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
@@ -31,9 +31,7 @@
 ** This header is generated from the Khronos OpenGL / OpenGL ES XML
 ** API Registry. The current version of the Registry, generator scripts
 ** used to make the header, and the header can be found at
-**   http://www.opengl.org/registry/
-**
-** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
+**   https://github.com/KhronosGroup/OpenGL-Registry
 */
 
 #include <GLES3/gl3platform.h>
@@ -42,11 +40,11 @@
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-#if !defined(GL_GLES_PROTOTYPES)
+#ifndef GL_GLES_PROTOTYPES
 #define GL_GLES_PROTOTYPES 1
 #endif
 
-/* Generated on date 20151015 */
+/* Generated on date 20170613 */
 
 /* Generated C header for:
  * API: gles2
diff --git a/opengl/include/GLES3/gl31.h b/opengl/include/GLES3/gl31.h
index 9b89a0a..4806181 100644
--- a/opengl/include/GLES3/gl31.h
+++ b/opengl/include/GLES3/gl31.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -42,11 +42,11 @@
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-#if !defined(GL_GLES_PROTOTYPES)
+#ifndef GL_GLES_PROTOTYPES
 #define GL_GLES_PROTOTYPES 1
 #endif
 
-/* Generated on date 20151015 */
+/* Generated on date 20161024 */
 
 /* Generated C header for:
  * API: gles2
diff --git a/opengl/include/GLES3/gl32.h b/opengl/include/GLES3/gl32.h
index a2c3611..a1af7c6 100644
--- a/opengl/include/GLES3/gl32.h
+++ b/opengl/include/GLES3/gl32.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -42,11 +42,11 @@
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-#if !defined(GL_GLES_PROTOTYPES)
+#ifndef GL_GLES_PROTOTYPES
 #define GL_GLES_PROTOTYPES 1
 #endif
 
-/* Generated on date 20151015 */
+/* Generated on date 20161024 */
 
 /* Generated C header for:
  * API: gles2
diff --git a/opengl/include/GLES3/gl3platform.h b/opengl/include/GLES3/gl3platform.h
index b1e869d..ca9d7a6 100644
--- a/opengl/include/GLES3/gl3platform.h
+++ b/opengl/include/GLES3/gl3platform.h
@@ -1,20 +1,28 @@
 #ifndef __gl3platform_h_
 #define __gl3platform_h_
 
-/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
-
 /*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
+** Copyright (c) 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.
+*/
 
 /* Platform-specific types and definitions for OpenGL ES 3.X  gl3.h
  *
  * Adopters may modify khrplatform.h and this file to suit their platform.
- * You are encouraged to submit all modifications to the Khronos group so that
- * they can be included in future versions of this file.  Please submit changes
- * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
- * by filing a bug against product "OpenGL-ES" component "Registry".
+ * Please contribute modifications back to Khronos as pull requests on the
+ * public github repository:
+ *      https://github.com/KhronosGroup/OpenGL-Registry
  */
 
 #include <KHR/khrplatform.h>
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 4b08749..c7635e2 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -26,7 +26,7 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui libnativewindow
 
 LOCAL_SRC_FILES_arm += fixed_asm.S iterators.S
 LOCAL_CFLAGS_arm += -fstrict-aliasing
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 04f6d6d..b79051c 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -56,6 +56,24 @@
 EGLBoolean EGLAPI eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
         EGLint left, EGLint top, EGLint width, EGLint height);
 
+
+typedef struct egl_native_pixmap_t
+{
+    int32_t     version;    /* must be 32 */
+    int32_t     width;
+    int32_t     height;
+    int32_t     stride;
+    uint8_t*    data;
+    uint8_t     format;
+    uint8_t     rfu[3];
+    union {
+        uint32_t    compressedFormat;
+        int32_t     vstride;
+    };
+    int32_t     reserved;
+} egl_native_pixmap_t;
+
+
 // ----------------------------------------------------------------------------
 namespace android {
 
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index d6bdc81..802b3b4 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -64,6 +64,16 @@
         "liblog",
         "libdl",
     ],
+    static_libs: [
+        "libarect",
+    ],
+    header_libs: [
+        "gl_headers",
+        "libsystem_headers",
+        "libhardware_headers",
+        "libnativebase_headers",
+    ],
+    export_header_lib_headers: ["gl_headers"],
 
     // we need to access the private Bionic header <bionic_tls.h>
     include_dirs: ["bionic/libc/private"],
@@ -81,10 +91,15 @@
     shared_libs: [
         // ***** DO NOT ADD NEW DEPENDENCIES HERE *****
         // In particular, DO NOT add libutils nor anything "above" libui
-        "libui",
+        "libgraphicsenv",
         "libnativewindow",
         "libbacktrace",
     ],
+    target: {
+        vendor: {
+            exclude_shared_libs: ["libgraphicsenv"],
+        },
+    },
 }
 
 cc_library_static {
@@ -111,7 +126,14 @@
         "EGL/Loader.cpp",
         "EGL/BlobCache.cpp",
     ],
-    shared_libs: ["libvndksupport"],
+    shared_libs: [
+        "libvndksupport",
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore-utils",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+    ],
     static_libs: ["libEGL_getProcAddress"],
     ldflags: ["-Wl,--exclude-libs=ALL"],
     export_include_dirs: ["EGL/include"],
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 823b502..371239d 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -28,7 +28,9 @@
 #include <cutils/properties.h>
 #include <log/log.h>
 
-#include <ui/GraphicsEnv.h>
+#ifndef __ANDROID_VNDK__
+#include <graphicsenv/GraphicsEnv.h>
+#endif
 #include <vndksupport/linker.h>
 
 #include "egl_trace.h"
@@ -325,17 +327,17 @@
             switch (emulationStatus) {
                 case 0:
 #if defined(__LP64__)
-                    result = "/system/lib64/egl/libGLES_android.so";
+                    result = "/vendor/lib64/egl/libGLES_android.so";
 #else
-                    result = "/system/lib/egl/libGLES_android.so";
+                    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("/system/lib64/egl/lib") + kind + "_emulation.so";
+                    result = std::string("/vendor/lib64/egl/lib") + kind + "_emulation.so";
 #else
-                    result = std::string("/system/lib/egl/lib") + kind + "_emulation.so";
+                    result = std::string("/vendor/lib/egl/lib") + kind + "_emulation.so";
 #endif
                     return result;
                 default:
@@ -477,10 +479,12 @@
     ATRACE_CALL();
 
     void* dso = nullptr;
+#ifndef __ANDROID_VNDK__
     android_namespace_t* ns = android_getDriverNamespace();
     if (ns) {
         dso = load_updated_driver(kind, ns);
     }
+#endif
     if (!dso) {
         dso = load_system_driver(kind);
         if (!dso)
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index ba3a5f9..94dfe6a 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -79,6 +79,7 @@
 extern char const * const gBuiltinExtensionString;
 extern char const * const gExtensionString;
 
+// clang-format off
 char const * const gBuiltinExtensionString =
         "EGL_KHR_get_all_proc_addresses "
         "EGL_ANDROID_presentation_time "
@@ -123,6 +124,7 @@
         "EGL_IMG_context_priority "
         "EGL_KHR_no_config_context "
         ;
+// clang-format on
 
 // extensions not exposed to applications but used by the ANDROID system
 //      "EGL_ANDROID_blob_cache "               // strongly recommended
@@ -452,16 +454,216 @@
 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
 // the modification isn't possible, the original dataSpace is returned.
-static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
-                                                EGLint colorspace) {
+static android_dataspace modifyBufferDataspace(android_dataspace dataSpace,
+                                               EGLint colorspace) {
     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
         return HAL_DATASPACE_SRGB_LINEAR;
     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
         return HAL_DATASPACE_SRGB;
+    } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
+        return HAL_DATASPACE_DISPLAY_P3_LINEAR;
+    } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
+        return HAL_DATASPACE_V0_SCRGB;
+    } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
+        return HAL_DATASPACE_V0_SCRGB_LINEAR;
     }
     return dataSpace;
 }
 
+// Return true if we stripped any EGL_GL_COLORSPACE_KHR attributes.
+static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
+                                           EGLint format,
+                                           std::vector<EGLint>& stripped_attrib_list) {
+    std::vector<EGLint> allowedColorSpaces;
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+            // driver okay with linear & sRGB for 8888, but can't handle
+            // Display-P3 or other spaces.
+            allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
+            allowedColorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
+            break;
+
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        default:
+            // driver does not want to see colorspace attributes for 1010102 or fp16.
+            // Future: if driver supports XXXX extension, we can pass down that colorspace
+            break;
+    }
+
+    bool stripped = false;
+    if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+        for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
+            if (attr[0] == EGL_GL_COLORSPACE_KHR) {
+                EGLint colorSpace = attr[1];
+                bool found = false;
+                // Verify that color space is allowed
+                for (auto it : allowedColorSpaces) {
+                    if (colorSpace == it) {
+                        found = true;
+                    }
+                }
+                if (!found) {
+                    stripped = true;
+                } else {
+                    stripped_attrib_list.push_back(attr[0]);
+                    stripped_attrib_list.push_back(attr[1]);
+                }
+            } else {
+                stripped_attrib_list.push_back(attr[0]);
+                stripped_attrib_list.push_back(attr[1]);
+            }
+        }
+    }
+    if (stripped) {
+        stripped_attrib_list.push_back(EGL_NONE);
+        stripped_attrib_list.push_back(EGL_NONE);
+    }
+    return stripped;
+}
+
+static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, NativeWindowType window,
+                                         const EGLint* attrib_list, EGLint& colorSpace,
+                                         android_dataspace& dataSpace) {
+    colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+    dataSpace = HAL_DATASPACE_UNKNOWN;
+
+    if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+        for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+            if (*attr == EGL_GL_COLORSPACE_KHR) {
+                colorSpace = attr[1];
+                bool found = false;
+                bool verify = true;
+                // Verify that color space is allowed
+                if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
+                    colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
+                    // SRGB and LINEAR are always supported when EGL_KHR_gl_colorspace
+                    // is available, so no need to verify.
+                    found = true;
+                    verify = false;
+                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_scrgb")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
+                    found = true;
+                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
+                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
+                    found = true;
+                }
+                if (!found) {
+                    return false;
+                }
+                if (verify && window) {
+                    bool wide_color_support = true;
+                    // Ordinarily we'd put a call to native_window_get_wide_color_support
+                    // at the beginning of the function so that we'll have the
+                    // result when needed elsewhere in the function.
+                    // However, because eglCreateWindowSurface is called by SurfaceFlinger and
+                    // SurfaceFlinger is required to answer the call below we would
+                    // end up in a deadlock situation. By moving the call to only happen
+                    // if the application has specifically asked for wide-color we avoid
+                    // the deadlock with SurfaceFlinger since it will not ask for a
+                    // wide-color surface.
+                    int err = native_window_get_wide_color_support(window, &wide_color_support);
+
+                    if (err) {
+                        ALOGE("getColorSpaceAttribute: invalid window (win=%p) "
+                              "failed (%#x) (already connected to another API?)",
+                              window, err);
+                        return false;
+                    }
+                    if (!wide_color_support) {
+                        // Application has asked for a wide-color colorspace but
+                        // wide-color support isn't available on the display the window is on.
+                        return false;
+                    }
+                }
+                // Only change the dataSpace from default if the application
+                // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute.
+                dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
+            }
+        }
+    }
+    return true;
+}
+
+static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
+                                         EGLint& colorSpace, android_dataspace& dataSpace) {
+    return getColorSpaceAttribute(dp, NULL, attrib_list, colorSpace, dataSpace);
+}
+
+void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, EGLint& format) {
+    // Set the native window's buffers format to match what this config requests.
+    // Whether to use sRGB gamma is not part of the EGLconfig, but is part
+    // of our native format. So if sRGB gamma is requested, we have to
+    // modify the EGLconfig's format before setting the native window's
+    // format.
+
+    EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+    cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType);
+
+    EGLint a = 0;
+    EGLint r, g, b;
+    r = g = b = 0;
+    cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r);
+    cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
+    cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b);
+    cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
+    EGLint colorDepth = r + g + b;
+
+    // Today, the driver only understands sRGB and linear on 888X
+    // formats. Strip other colorspaces from the attribute list and
+    // only use them to set the dataspace via
+    // native_window_set_buffers_dataspace
+    // if pixel format is RGBX 8888
+    //    TBD: Can test for future extensions that indicate that driver
+    //    handles requested color space and we can let it through.
+    //    allow SRGB and LINEAR. All others need to be stripped.
+    // else if 565, 4444
+    //    TBD: Can we assume these are supported if 8888 is?
+    // else if FP16 or 1010102
+    //    strip colorspace from attribs.
+    // endif
+    if (a == 0) {
+        if (colorDepth <= 16) {
+            format = HAL_PIXEL_FORMAT_RGB_565;
+        } else {
+            if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
+                if (colorDepth > 24) {
+                    format = HAL_PIXEL_FORMAT_RGBA_1010102;
+                } else {
+                    format = HAL_PIXEL_FORMAT_RGBX_8888;
+                }
+            } else {
+                format = HAL_PIXEL_FORMAT_RGBA_FP16;
+            }
+        }
+    } else {
+        if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
+            if (colorDepth > 24) {
+                format = HAL_PIXEL_FORMAT_RGBA_1010102;
+            } else {
+                format = HAL_PIXEL_FORMAT_RGBA_8888;
+            }
+        } else {
+            format = HAL_PIXEL_FORMAT_RGBA_FP16;
+        }
+    }
+}
+
 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                                     NativeWindowType window,
                                     const EGLint *attrib_list)
@@ -491,60 +693,22 @@
             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
         }
 
-        // Set the native window's buffers format to match what this config requests.
-        // Whether to use sRGB gamma is not part of the EGLconfig, but is part
-        // of our native format. So if sRGB gamma is requested, we have to
-        // modify the EGLconfig's format before setting the native window's
-        // format.
-
-        EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
-        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_COMPONENT_TYPE_EXT,
-                                    &componentType);
-
         EGLint format;
-        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
-        EGLint a = 0;
-        EGLint r, g, b;
-        r = g = b = 0;
-        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
-        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
-        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
-        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
-        EGLint colorDepth = r + g + b;
+        getNativePixelFormat(iDpy, cnx, config, format);
 
-        if (a == 0) {
-            if (colorDepth <= 16) {
-                format = HAL_PIXEL_FORMAT_RGB_565;
-            } else {
-                if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
-                    if (colorDepth > 24) {
-                        format = HAL_PIXEL_FORMAT_RGBA_1010102;
-                    } else {
-                        format = HAL_PIXEL_FORMAT_RGBX_8888;
-                    }
-                } else {
-                    format = HAL_PIXEL_FORMAT_RGBA_FP16;
-                }
-            }
-        } else {
-            if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
-                if (colorDepth > 24) {
-                    format = HAL_PIXEL_FORMAT_RGBA_1010102;
-                } else {
-                    format = HAL_PIXEL_FORMAT_RGBA_8888;
-                }
-            } else {
-                format = HAL_PIXEL_FORMAT_RGBA_FP16;
-            }
+        // now select correct colorspace and dataspace based on user's attribute list
+        EGLint colorSpace;
+        android_dataspace dataSpace;
+        if (!getColorSpaceAttribute(dp, window, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
         }
 
-        // now select a corresponding sRGB format if needed
-        if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
-            for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
-                if (*attr == EGL_GL_COLORSPACE_KHR) {
-                    dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
-                }
-            }
+        std::vector<EGLint> strippedAttribList;
+        if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
+            // Had to modify the attribute list due to use of color space.
+            // Use modified list from here on.
+            attrib_list = strippedAttribList.data();
         }
 
         if (format != 0) {
@@ -575,8 +739,8 @@
         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                 iDpy, config, window, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
-                    surface, cnx);
+            egl_surface_t* s =
+                    new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
             return s;
         }
 
@@ -595,12 +759,19 @@
 
     egl_connection_t* cnx = NULL;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
+    EGLint colorSpace;
+    android_dataspace dataSpace;
     if (dp) {
+        // now select a corresponding sRGB format if needed
+        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        }
+
         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                 dp->disp.dpy, config, pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
@@ -615,11 +786,32 @@
     egl_connection_t* cnx = NULL;
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (dp) {
+        EGLDisplay iDpy = dp->disp.dpy;
+        EGLint format;
+        getNativePixelFormat(iDpy, cnx, config, format);
+
+        // now select correct colorspace and dataspace based on user's attribute list
+        EGLint colorSpace;
+        android_dataspace dataSpace;
+        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+            ALOGE("error invalid colorspace: %d", colorSpace);
+            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        }
+
+        // Pbuffers are not displayed so we don't need to store the
+        // colorspace. We do need to filter out color spaces the
+        // driver doesn't know how to process.
+        std::vector<EGLint> strippedAttribList;
+        if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
+            // Had to modify the attribute list due to use of color space.
+            // Use modified list from here on.
+            attrib_list = strippedAttribList.data();
+        }
+
         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                 dp->disp.dpy, config, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
@@ -658,6 +850,10 @@
         return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
 
     egl_surface_t const * const s = get_surface(surface);
+    if (attribute == EGL_GL_COLORSPACE_KHR) {
+        *value = s->getColorSpace();
+        return EGL_TRUE;
+    }
     return s->cnx->egl.eglQuerySurface(
             dp->disp.dpy, s->surface, attribute, value);
 }
@@ -1251,7 +1447,7 @@
     return setError(EGL_BAD_PARAMETER, (const char *)0);
 }
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
 {
     clearError();
 
@@ -1729,13 +1925,22 @@
     egl_display_ptr dp = validate_display(dpy);
     if (!dp) return EGL_NO_SURFACE;
 
+    EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
+    android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+    // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to
+    // indicate support for EGL_GL_COLORSPACE_KHR.
+    // now select a corresponding sRGB format if needed
+    if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
+        ALOGE("error invalid colorspace: %d", colorSpace);
+        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+    }
+
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
         EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
                 dp->disp.dpy, config, stream, attrib_list);
         if (surface != EGL_NO_SURFACE) {
-            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
-                    surface, cnx);
+            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
             return s;
         }
     }
@@ -1886,8 +2091,15 @@
 
 EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
     clearError();
+    // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
+    // this function cannot be implemented when this libEGL is built for
+    // vendors.
+#ifndef __ANDROID_VNDK__
     if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
     return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
+#else
+    return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+#endif
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index dc1a4af..579e422 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -26,6 +26,7 @@
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include <thread>
 
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index b696920..4e5833a 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -30,6 +30,12 @@
 #include "Loader.h"
 #include <cutils/properties.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -192,6 +198,18 @@
         mClientApiString = sClientApiString;
 
         mExtensionString = gBuiltinExtensionString;
+
+        bool wideColorBoardConfig =
+                getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(
+                        false);
+
+        // Add wide-color extensions if device can support wide-color
+        if (wideColorBoardConfig) {
+            mExtensionString.append(
+                    "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
+                    "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 ");
+        }
+
         char const* start = gExtensionString;
         do {
             // length of the extension name
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 6238780..837cfa9 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -55,12 +55,15 @@
 
 // ----------------------------------------------------------------------------
 
-egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
-        EGLNativeWindowType win, EGLSurface surface,
-        egl_connection_t const* cnx) :
-    egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
-    connected(true)
-{
+egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win,
+                             EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx)
+      : egl_object_t(dpy),
+        surface(surface),
+        config(config),
+        win(win),
+        cnx(cnx),
+        connected(true),
+        colorSpace(colorSpace) {
     if (win) {
         win->incStrong(this);
     }
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 8988905..7c3075c 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -131,12 +131,12 @@
 public:
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
-    egl_surface_t(egl_display_t* dpy, EGLConfig config,
-            EGLNativeWindowType win, EGLSurface surface,
-            egl_connection_t const* cnx);
+    egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
+                  EGLint colorSpace, egl_connection_t const* cnx);
 
     ANativeWindow* getNativeWindow() { return win; }
     ANativeWindow* getNativeWindow() const { return win; }
+    EGLint getColorSpace() const { return colorSpace; }
 
     // Try to keep the order of these fields and size unchanged. It's not public API, but
     // it's not hard to imagine native games accessing them.
@@ -149,6 +149,7 @@
 private:
     bool connected;
     void disconnect();
+    EGLint colorSpace;
 };
 
 class egl_context_t: public egl_object_t {
diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt
index 89269a0..fa26e33 100644
--- a/opengl/libs/libEGL.map.txt
+++ b/opengl/libs/libEGL.map.txt
@@ -21,6 +21,7 @@
     eglDestroyStreamKHR; # introduced=23
     eglDestroySurface;
     eglDestroySyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
+    eglDupNativeFenceFDANDROID; # vndk
     eglGetConfigAttrib;
     eglGetConfigs;
     eglGetCurrentContext;
@@ -44,6 +45,7 @@
     eglQueryStreamTimeKHR; # introduced=23
     eglQueryStreamu64KHR; # introduced=23
     eglQueryString;
+    eglQueryStringImplementationANDROID; # vndk
     eglQuerySurface;
     eglReleaseTexImage;
     eglReleaseThread;
diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp
new file mode 100644
index 0000000..639f351
--- /dev/null
+++ b/opengl/tests/Android.bp
@@ -0,0 +1,19 @@
+
+subdirs = [
+    "angeles",
+    "configdump",
+    "EGLTest",
+    "fillrate",
+    "filter",
+    "finish",
+    "gl2_basic",
+    "gl2_copyTexImage",
+    "gl2_yuvtex",
+    "gl_basic",
+    "gl_perf",
+    "gl_yuvtex", // just renders magenta frame, broken?
+    "gralloc",
+    "hwc",
+    "lib",
+]
+
diff --git a/opengl/tests/Android.mk b/opengl/tests/Android.mk
index 3ae3b4e..134854a 100644
--- a/opengl/tests/Android.mk
+++ b/opengl/tests/Android.mk
@@ -1,20 +1,4 @@
 dirs := \
-	angeles \
-	configdump \
-	EGLTest \
-	fillrate \
-	filter \
-	finish \
-	gl2_basic \
-	gl2_copyTexImage \
-	gl2_yuvtex \
-	gl_basic \
-	gl_perf \
-	gl_yuvtex \
-	gralloc \
-	hwc \
-	include \
-	lib \
 	linetex \
 	swapinterval \
 	textures \
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
new file mode 100644
index 0000000..d85af81
--- /dev/null
+++ b/opengl/tests/EGLTest/Android.bp
@@ -0,0 +1,31 @@
+
+cc_test {
+
+    name: "EGL_test",
+
+    srcs: [
+        "egl_cache_test.cpp",
+        "EGL_test.cpp",
+    ],
+
+    shared_libs: [
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore-utils",
+        "libEGL",
+        "libbase",
+        "libcutils",
+        "libbinder",
+        "libgui",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+
+    include_dirs: [
+        "bionic/libc/private",
+        "frameworks/native/opengl/libs",
+        "frameworks/native/opengl/libs/EGL",
+    ],
+
+}
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
deleted file mode 100644
index 5620496..0000000
--- a/opengl/tests/EGLTest/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := EGL_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    egl_cache_test.cpp \
-    EGL_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	android.hardware.configstore@1.0 \
-	android.hardware.configstore-utils \
-	libEGL \
-	libcutils \
-	libbinder \
-	libhidlbase \
-	libhidltransport \
-	libutils \
-	libgui \
-	libbase \
-	liblog \
-
-LOCAL_C_INCLUDES := \
-    bionic/libc/private \
-    frameworks/native/opengl/libs \
-    frameworks/native/opengl/libs/EGL \
-
-# gold in binutils 2.22 will warn about the usage of mktemp
-LOCAL_LDFLAGS += -Wl,--no-fatal-warnings
-
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 24b1315..b67a053 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -28,18 +28,17 @@
 #include <gui/IGraphicBufferConsumer.h>
 #include <gui/BufferQueue.h>
 
-#define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"
-
-bool hasEglPixelFormatFloat() {
-    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
-    size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+    size_t cropExtLen = strlen(extensionName);
     size_t extsLen = strlen(exts);
-    bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
-    bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+    bool equal = !strcmp(extensionName, exts);
+    android::String8 extString(extensionName);
+    android::String8 space(" ");
+    bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
     bool atEnd = (cropExtLen + 1) < extsLen &&
-            !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
-    bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+            !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, space + extString + space);
     return equal || atStart || atEnd || inMiddle;
 }
 
@@ -194,6 +193,178 @@
     EXPECT_GE(components[3], 8);
 }
 
+TEST_F(EGLTest, EGLDisplayP3) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
+        return;
+    }
+
+    // Test that display-p3 extensions exist
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+    // Use 8-bit to keep forcus on Display-P3 aspect
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 8,
+            EGL_GREEN_SIZE,               8,
+            EGL_BLUE_SIZE,                8,
+            EGL_ALPHA_SIZE,               8,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 8);
+    EXPECT_EQ(components[1], 8);
+    EXPECT_EQ(components[2], 8);
+    EXPECT_EQ(components[3], 8);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+    EGLint winAttrs[] = {
+            // clang-format off
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+            EGL_NONE,              EGL_NONE
+            // clang-format on
+    };
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLDisplayP31010102) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
+        return;
+    }
+
+    // Test that display-p3 extensions exist
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+
+    // Use 8-bit to keep forcus on Display-P3 aspect
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 10,
+            EGL_GREEN_SIZE,               10,
+            EGL_BLUE_SIZE,                10,
+            EGL_ALPHA_SIZE,               2,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 10);
+    EXPECT_EQ(components[1], 10);
+    EXPECT_EQ(components[2], 10);
+    EXPECT_EQ(components[3], 2);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+    EGLint winAttrs[] = {
+            // clang-format off
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+            EGL_NONE,              EGL_NONE
+            // clang-format on
+    };
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
 TEST_F(EGLTest, EGLConfigFP16) {
     EGLint numConfigs;
     EGLConfig config;
@@ -201,26 +372,24 @@
 
     if (!hasWideColorDisplay) {
         // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
         return;
     }
 
-    ASSERT_TRUE(hasEglPixelFormatFloat());
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
 
-    EGLint attrs[] = {EGL_SURFACE_TYPE,
-                      EGL_WINDOW_BIT,
-                      EGL_RENDERABLE_TYPE,
-                      EGL_OPENGL_ES2_BIT,
-                      EGL_RED_SIZE,
-                      16,
-                      EGL_GREEN_SIZE,
-                      16,
-                      EGL_BLUE_SIZE,
-                      16,
-                      EGL_ALPHA_SIZE,
-                      16,
-                      EGL_COLOR_COMPONENT_TYPE_EXT,
-                      EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
-                      EGL_NONE};
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE,                 16,
+            EGL_GREEN_SIZE,               16,
+            EGL_BLUE_SIZE,                16,
+            EGL_ALPHA_SIZE,               16,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
     success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
     ASSERT_EQ(1, numConfigs);
@@ -251,6 +420,110 @@
         void onSidebandStreamChanged() override {}
     };
 
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLNoConfigContext) {
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
+        return;
+    }
+
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    std::vector<EGLint> contextAttributes;
+    contextAttributes.reserve(4);
+    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+    contextAttributes.push_back(2);
+    contextAttributes.push_back(EGL_NONE);
+    contextAttributes.push_back(EGL_NONE);
+
+    EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
+                                             contextAttributes.data());
+    EXPECT_NE(EGL_NO_CONTEXT, eglContext);
+    EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+    if (eglContext != EGL_NO_CONTEXT) {
+        eglDestroyContext(mEglDisplay, eglContext);
+    }
+}
+
+// Emulate what a native application would do to create a
+// 10:10:10:2 surface.
+TEST_F(EGLTest, EGLConfig1010102) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
+        return;
+    }
+
+    EGLint attrs[] = {
+            // clang-format off
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
+            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+            EGL_RED_SIZE,                 10,
+            EGL_GREEN_SIZE,               10,
+            EGL_BLUE_SIZE,                10,
+            EGL_ALPHA_SIZE,               2,
+            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+            EGL_NONE,                     EGL_NONE
+            // clang-format on
+    };
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+    EGLint value;
+    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_EQ(components[0], 10);
+    EXPECT_EQ(components[1], 10);
+    EXPECT_EQ(components[2], 10);
+    EXPECT_EQ(components[3], 2);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
     // Create a EGLSurface
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
diff --git a/opengl/tests/angeles/Android.bp b/opengl/tests/angeles/Android.bp
new file mode 100644
index 0000000..bbbc447
--- /dev/null
+++ b/opengl/tests/angeles/Android.bp
@@ -0,0 +1,22 @@
+// Copyright 2006 The Android Open Source Project
+
+cc_test {
+    name: "angeles",
+
+    srcs: [
+        "app-linux.cpp",
+        "demo.c",
+    ],
+
+    gtest: false,
+
+    shared_libs: [
+        "libEGL",
+        "libGLESv1_CM",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
deleted file mode 100644
index c78224e..0000000
--- a/opengl/tests/angeles/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2006 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= app-linux.cpp demo.c.arm
-LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui libgui libutils
-LOCAL_STATIC_LIBRARIES += libglTest
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-LOCAL_MODULE:= angeles
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/angeles/demo.c b/opengl/tests/angeles/demo.c
index 39d871e..30c3202 100644
--- a/opengl/tests/angeles/demo.c
+++ b/opengl/tests/angeles/demo.c
@@ -462,7 +462,7 @@
 // Called from the app framework.
 void appInit()
 {
-    int a;
+    unsigned int a;
 
     glEnable(GL_NORMALIZE);
     glEnable(GL_DEPTH_TEST);
@@ -492,7 +492,7 @@
 // Called from the app framework.
 void appDeinit()
 {
-    int a;
+    unsigned int a;
     for (a = 0; a < SUPERSHAPE_COUNT; ++a)
         freeGLObject(sSuperShapeObjects[a]);
     freeGLObject(sGroundPlane);
diff --git a/opengl/tests/configdump/Android.bp b/opengl/tests/configdump/Android.bp
new file mode 100644
index 0000000..c46477c
--- /dev/null
+++ b/opengl/tests/configdump/Android.bp
@@ -0,0 +1,13 @@
+cc_test {
+    name: "test-opengl-configdump",
+
+    gtest: false,
+
+    srcs: ["configdump.cpp"],
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+    ],
+}
diff --git a/opengl/tests/configdump/Android.mk b/opengl/tests/configdump/Android.mk
deleted file mode 100644
index 3f7c915..0000000
--- a/opengl/tests/configdump/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	configdump.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-    libEGL \
-    libGLESv1_CM
-
-LOCAL_MODULE:= test-opengl-configdump
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/configdump/configdump.cpp b/opengl/tests/configdump/configdump.cpp
index 2a94598..a4bb879 100644
--- a/opengl/tests/configdump/configdump.cpp
+++ b/opengl/tests/configdump/configdump.cpp
@@ -66,8 +66,7 @@
 };
 // clang-format on
 
-int main(int argc, char** argv)
-{
+int main(int /*argc*/, char** /*argv*/) {
     EGLConfig* configs;
     EGLint n;
 
@@ -79,7 +78,7 @@
 
     for (EGLint i=0 ; i<n ; i++) {
         printf("EGLConfig[%d]\n", i);
-        for (int attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
+        for (unsigned attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
             EGLint value;
             eglGetConfigAttrib(dpy, configs[i], attributes[attr].attribute, &value);
             printf("\t%-32s: %10d (0x%08x)\n", attributes[attr].name, value, value);
diff --git a/opengl/tests/fillrate/Android.bp b/opengl/tests/fillrate/Android.bp
new file mode 100644
index 0000000..543f1e3
--- /dev/null
+++ b/opengl/tests/fillrate/Android.bp
@@ -0,0 +1,18 @@
+cc_test {
+    name: "test-opengl-fillrate",
+
+    srcs: ["fillrate.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libui",
+        "libgui",
+    ],
+
+    static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/fillrate/Android.mk b/opengl/tests/fillrate/Android.mk
deleted file mode 100644
index 21ff52a..0000000
--- a/opengl/tests/fillrate/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	fillrate.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-    libEGL \
-    libGLESv1_CM \
-    libui \
-    libgui
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-fillrate
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/fillrate/fillrate.cpp b/opengl/tests/fillrate/fillrate.cpp
index 2db63d7..a42f3f2 100644
--- a/opengl/tests/fillrate/fillrate.cpp
+++ b/opengl/tests/fillrate/fillrate.cpp
@@ -30,7 +30,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     EGLint configAttribs[] = {
          EGL_DEPTH_SIZE, 0,
@@ -153,7 +153,7 @@
 
      for (int c=1, j=0 ; c<32 ; c++, j++) {
          nsecs_t t = times[j];
-         printf("%lld\t%d\t%f\n", t, c, (double(t)/c)/1000000.0);
+         printf("%ld\t%d\t%f\n", t, c, (double(t)/c)/1000000.0);
      }
 
 
diff --git a/opengl/tests/filter/Android.bp b/opengl/tests/filter/Android.bp
new file mode 100644
index 0000000..5f925c8
--- /dev/null
+++ b/opengl/tests/filter/Android.bp
@@ -0,0 +1,20 @@
+cc_test {
+    name: "test-opengl-filter",
+
+    srcs: ["filter.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+
+    cflags: ["-DGL_GLEXT_PROTOTYPES"],
+}
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
deleted file mode 100644
index 4cf9c96..0000000
--- a/opengl/tests/filter/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	filter.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-    libEGL \
-    libGLESv1_CM \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-filter
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/Android.bp b/opengl/tests/finish/Android.bp
new file mode 100644
index 0000000..fb5671d
--- /dev/null
+++ b/opengl/tests/finish/Android.bp
@@ -0,0 +1,20 @@
+cc_test {
+    name: "test-opengl-finish",
+
+    srcs: ["finish.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libui",
+        "libgui",
+    ],
+
+    static_libs: ["libglTest"],
+
+    cflags: ["-DGL_GLEXT_PROTOTYPES"],
+}
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
deleted file mode 100644
index 0b9b7ea..0000000
--- a/opengl/tests/finish/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	finish.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-    libEGL \
-    libGLESv1_CM \
-    libui \
-    libgui
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-finish
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/finish.cpp b/opengl/tests/finish/finish.cpp
index ea3a60f..ab955fe 100644
--- a/opengl/tests/finish/finish.cpp
+++ b/opengl/tests/finish/finish.cpp
@@ -31,7 +31,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     EGLint configAttribs[] = {
          EGL_DEPTH_SIZE, 0,
diff --git a/opengl/tests/gl2_basic/Android.bp b/opengl/tests/gl2_basic/Android.bp
new file mode 100644
index 0000000..7403271
--- /dev/null
+++ b/opengl/tests/gl2_basic/Android.bp
@@ -0,0 +1,20 @@
+cc_test {
+    name: "test-opengl-gl2_basic",
+
+    srcs: ["gl2_basic.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+
+    cflags: ["-DGL_GLEXT_PROTOTYPES"],
+}
diff --git a/opengl/tests/gl2_basic/Android.mk b/opengl/tests/gl2_basic/Android.mk
deleted file mode 100644
index 520395c..0000000
--- a/opengl/tests/gl2_basic/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl2_basic.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-    libEGL \
-    libGLESv2 \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl2_basic
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 9f8d166..67c0969 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -30,6 +30,7 @@
 #include <EGLUtils.h>
 
 using namespace android;
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 static void printGLString(const char *name, GLenum s) {
     // fprintf(stderr, "printGLString %s, %d\n", name, s);
@@ -46,7 +47,8 @@
 
 static void printEGLString(EGLDisplay dpy, const char *name, GLenum s) {
     const char *v = (const char *) eglQueryString(dpy, s);
-    fprintf(stderr, "GL %s = %s\n", name, v);
+    const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
+    fprintf(stderr, "GL %s = %s\nImplementationANDROID: %s\n", name, v, va);
 }
 
 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
@@ -263,7 +265,7 @@
     return true;
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl2_copyTexImage/Android.bp b/opengl/tests/gl2_copyTexImage/Android.bp
new file mode 100644
index 0000000..51e269c
--- /dev/null
+++ b/opengl/tests/gl2_copyTexImage/Android.bp
@@ -0,0 +1,20 @@
+cc_test {
+    name: "test-opengl-gl2_copyTexImage",
+
+    srcs: ["gl2_copyTexImage.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+
+    cflags: ["-DGL_GLEXT_PROTOTYPES"],
+}
diff --git a/opengl/tests/gl2_copyTexImage/Android.mk b/opengl/tests/gl2_copyTexImage/Android.mk
deleted file mode 100644
index ff43558..0000000
--- a/opengl/tests/gl2_copyTexImage/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl2_copyTexImage.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-    libEGL \
-    libGLESv2 \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl2_copyTexImage
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
index 405a3f0..e0aafa2 100644
--- a/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
+++ b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
@@ -362,7 +362,7 @@
     return true;
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl2_jni/jni/gl_code.cpp b/opengl/tests/gl2_jni/jni/gl_code.cpp
index ed896a4..5af4f6b 100644
--- a/opengl/tests/gl2_jni/jni/gl_code.cpp
+++ b/opengl/tests/gl2_jni/jni/gl_code.cpp
@@ -1,6 +1,6 @@
 // OpenGL ES 2.0 code
 
-#include <nativehelper/jni.h>
+#include <jni.h>
 #define LOG_TAG "GL2JNI gl_code.cpp"
 #include <utils/Log.h>
 
@@ -153,12 +153,12 @@
     JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj);
 };
 
-JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)
+JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * /*env*/, jobject /*obj*/,  jint width, jint height)
 {
     setupGraphics(width, height);
 }
 
-JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * /*env*/, jobject /*obj*/)
 {
     renderFrame();
 }
diff --git a/opengl/tests/gl2_yuvtex/Android.bp b/opengl/tests/gl2_yuvtex/Android.bp
new file mode 100644
index 0000000..613d678
--- /dev/null
+++ b/opengl/tests/gl2_yuvtex/Android.bp
@@ -0,0 +1,24 @@
+cc_test {
+    name: "test-opengl-gl2_yuvtex",
+
+    srcs: ["gl2_yuvtex.cpp"],
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libutils",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    gtest: false,
+
+    static_libs: ["libglTest"],
+
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+    ],
+}
diff --git a/opengl/tests/gl2_yuvtex/Android.mk b/opengl/tests/gl2_yuvtex/Android.mk
deleted file mode 100644
index 42cf771..0000000
--- a/opengl/tests/gl2_yuvtex/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl2_yuvtex.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv2 \
-    libutils \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl2_yuvtex
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
index 98d8aa8..22128ab 100644
--- a/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
+++ b/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
@@ -331,7 +331,7 @@
     printf("\n");
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl_basic/Android.bp b/opengl/tests/gl_basic/Android.bp
new file mode 100644
index 0000000..881d8ce
--- /dev/null
+++ b/opengl/tests/gl_basic/Android.bp
@@ -0,0 +1,18 @@
+cc_test {
+    name: "test-opengl-gl_basic",
+
+    srcs: ["gl_basic.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+}
diff --git a/opengl/tests/gl_basic/Android.mk b/opengl/tests/gl_basic/Android.mk
deleted file mode 100644
index 7f2259e..0000000
--- a/opengl/tests/gl_basic/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl_basic.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-    libEGL \
-    libGLESv1_CM \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl_basic
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl_basic/gl_basic.cpp b/opengl/tests/gl_basic/gl_basic.cpp
index e50d88f..0b663f7 100644
--- a/opengl/tests/gl_basic/gl_basic.cpp
+++ b/opengl/tests/gl_basic/gl_basic.cpp
@@ -189,7 +189,7 @@
     return true;
 }
 
-int main(int argc, char **argv)
+int main(int /*argc*/, char **/*argv*/)
 {
     int q;
     int start, end;
diff --git a/opengl/tests/gl_jni/jni/gl_code.cpp b/opengl/tests/gl_jni/jni/gl_code.cpp
index cf86020..3aa8adb 100644
--- a/opengl/tests/gl_jni/jni/gl_code.cpp
+++ b/opengl/tests/gl_jni/jni/gl_code.cpp
@@ -1,6 +1,6 @@
 // OpenGL ES 1.0 code
 
-#include <nativehelper/jni.h>
+#include <jni.h>
 #define LOG_TAG "GLJNI gl_code.cpp"
 #include <utils/Log.h>
 
@@ -140,13 +140,13 @@
     JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * env, jobject obj);
 };
 
-JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_init(JNIEnv * /*env*/, jobject /*obj*/,  jint width, jint height)
 {
     init_scene(width, height);
     create_texture();
 }
 
-JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_step(JNIEnv * /*env*/, jobject /*obj*/)
 {
     const GLfloat vertices[] = {
             -1,  -1,  0,
@@ -177,7 +177,7 @@
     glDrawElements(GL_TRIANGLES, nelem, GL_UNSIGNED_SHORT, quadIndices);
 }
 
-JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_com_android_gljni_GLJNILib_changeBackground(JNIEnv * /*env*/, jobject /*obj*/)
 {
     background = 1.0f - background;
 }
diff --git a/opengl/tests/gl_perf/Android.bp b/opengl/tests/gl_perf/Android.bp
new file mode 100644
index 0000000..0ffb121
--- /dev/null
+++ b/opengl/tests/gl_perf/Android.bp
@@ -0,0 +1,24 @@
+cc_test {
+    name: "test-opengl-gl2_perf",
+
+    srcs: [
+        "gl2_perf.cpp",
+        "filltest.cpp",
+    ],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libEGL",
+        "libGLESv2",
+        "libui",
+        "libgui",
+        "libutils",
+    ],
+
+    static_libs: ["libglTest"],
+
+    cflags: ["-DGL_GLEXT_PROTOTYPES"],
+}
diff --git a/opengl/tests/gl_perf/Android.mk b/opengl/tests/gl_perf/Android.mk
deleted file mode 100644
index 9a93fab..0000000
--- a/opengl/tests/gl_perf/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl2_perf.cpp \
-	filltest.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    liblog \
-    libEGL \
-    libGLESv2 \
-    libui \
-    libgui \
-    libutils
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl2_perf
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl_perf/filltest.cpp b/opengl/tests/gl_perf/filltest.cpp
index 3f8faca..4135c62 100644
--- a/opengl/tests/gl_perf/filltest.cpp
+++ b/opengl/tests/gl_perf/filltest.cpp
@@ -27,10 +27,6 @@
 #include <EGL/egl.h>
 #include <utils/Log.h>
 
-
-using namespace android;
-
-
 #include "fill_common.cpp"
 
 
diff --git a/opengl/tests/gl_perf/gl2_perf.cpp b/opengl/tests/gl_perf/gl2_perf.cpp
index 35df84f..2998864 100644
--- a/opengl/tests/gl_perf/gl2_perf.cpp
+++ b/opengl/tests/gl_perf/gl2_perf.cpp
@@ -56,7 +56,7 @@
 static EGLDisplay dpy;
 static EGLSurface surface;
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
diff --git a/opengl/tests/gl_perfapp/jni/gl_code.cpp b/opengl/tests/gl_perfapp/jni/gl_code.cpp
index 378c8e8..0cb594a 100644
--- a/opengl/tests/gl_perfapp/jni/gl_code.cpp
+++ b/opengl/tests/gl_perfapp/jni/gl_code.cpp
@@ -1,6 +1,6 @@
 // OpenGL ES 2.0 code
 
-#include <nativehelper/jni.h>
+#include <jni.h>
 #define LOG_TAG "GLPerf gl_code.cpp"
 #include <utils/Log.h>
 
@@ -61,7 +61,7 @@
     JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj);
 };
 
-JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * env, jobject obj,  jint width, jint height)
+JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_init(JNIEnv * /*env*/, jobject /*obj*/,  jint width, jint height)
 {
     gWidth = width;
     gHeight = height;
@@ -87,7 +87,7 @@
     }
 }
 
-JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_com_android_glperf_GLPerfLib_step(JNIEnv * /*env*/, jobject /*obj*/)
 {
     if (! done) {
         if (stateClock > 0 && ((stateClock & 1) == 0)) {
diff --git a/opengl/tests/gl_yuvtex/Android.bp b/opengl/tests/gl_yuvtex/Android.bp
new file mode 100644
index 0000000..b6be327
--- /dev/null
+++ b/opengl/tests/gl_yuvtex/Android.bp
@@ -0,0 +1,23 @@
+cc_test {
+    name: "test-opengl-gl_yuvtex",
+
+    srcs: ["gl_yuvtex.cpp"],
+
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libutils",
+        "libui",
+        "libgui",
+    ],
+
+    gtest: false,
+
+    static_libs: ["libglTest"],
+
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+    ],
+}
diff --git a/opengl/tests/gl_yuvtex/Android.mk b/opengl/tests/gl_yuvtex/Android.mk
deleted file mode 100644
index 7f2020a..0000000
--- a/opengl/tests/gl_yuvtex/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	gl_yuvtex.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv1_CM \
-    libutils \
-    libui \
-    libgui
-
-LOCAL_STATIC_LIBRARIES += libglTest
-
-LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= test-opengl-gl_yuvtex
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
index c923b07..7ef3f4e 100644
--- a/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
+++ b/opengl/tests/gl_yuvtex/gl_yuvtex.cpp
@@ -90,7 +90,7 @@
 static sp<GraphicBuffer> yuvTexBuffer;
 static GLuint yuvTex;
 
-bool setupYuvTexSurface(EGLDisplay dpy, EGLContext context) {
+static bool setupYuvTexSurface(EGLDisplay dpy) {
     int blockWidth = yuvTexWidth > 16 ? yuvTexWidth / 16 : 1;
     int blockHeight = yuvTexHeight > 16 ? yuvTexHeight / 16 : 1;
     yuvTexBuffer = new GraphicBuffer(yuvTexWidth, yuvTexHeight, yuvTexFormat,
@@ -221,7 +221,7 @@
     printf("\n");
 }
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     EGLBoolean returnValue;
     EGLConfig myConfig = {0};
 
@@ -298,7 +298,7 @@
     printGLString("Renderer", GL_RENDERER);
     printGLString("Extensions", GL_EXTENSIONS);
 
-    if(!setupYuvTexSurface(dpy, context)) {
+    if(!setupYuvTexSurface(dpy)) {
         fprintf(stderr, "Could not set up texture surface.\n");
         return 1;
     }
diff --git a/opengl/tests/gldual/jni/gl_code.cpp b/opengl/tests/gldual/jni/gl_code.cpp
index 22867ed..90d150b 100644
--- a/opengl/tests/gldual/jni/gl_code.cpp
+++ b/opengl/tests/gldual/jni/gl_code.cpp
@@ -1,6 +1,6 @@
 // OpenGL ES 2.0 code
 
-#include <nativehelper/jni.h>
+#include <jni.h>
 #define LOG_TAG "GL2JNI gl_code.cpp"
 #include <utils/Log.h>
 
@@ -153,12 +153,12 @@
     JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj);
 };
 
-JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * env, jobject obj, jint width, jint height)

+JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_init(JNIEnv * /*env*/, jobject /*obj*/, jint width, jint height)

 {
     setupGraphics(width, height);
 }
 
-JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * env, jobject obj)
+JNIEXPORT void JNICALL Java_com_android_gldual_GLDualLib_step(JNIEnv * /*env*/, jobject /*obj*/)
 {
     renderFrame();
 }
diff --git a/opengl/tests/gralloc/Android.bp b/opengl/tests/gralloc/Android.bp
new file mode 100644
index 0000000..414c804
--- /dev/null
+++ b/opengl/tests/gralloc/Android.bp
@@ -0,0 +1,13 @@
+cc_test {
+    name: "test-opengl-gralloc",
+
+    srcs: ["gralloc.cpp"],
+
+    gtest: false,
+
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "libui",
+    ],
+}
diff --git a/opengl/tests/gralloc/Android.mk b/opengl/tests/gralloc/Android.mk
deleted file mode 100644
index d43c39a..0000000
--- a/opengl/tests/gralloc/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    gralloc.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libutils \
-    libui
-
-LOCAL_MODULE:= test-opengl-gralloc
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gralloc/gralloc.cpp b/opengl/tests/gralloc/gralloc.cpp
index 8987040..29e0882 100644
--- a/opengl/tests/gralloc/gralloc.cpp
+++ b/opengl/tests/gralloc/gralloc.cpp
@@ -37,7 +37,7 @@
     return d;
 }
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     size_t size = 128*256*4;
     void* temp = malloc(size);
diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp
new file mode 100644
index 0000000..55f058f
--- /dev/null
+++ b/opengl/tests/hwc/Android.bp
@@ -0,0 +1,109 @@
+// 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.
+
+cc_defaults {
+
+    name: "hwc_tests_defaults",
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
+
+cc_library_static {
+
+    name: "libhwcTest",
+    srcs: ["hwcTestLib.cpp"],
+
+    static_libs: [
+        "libarect",
+        "libglTest",
+        "libtestUtil",
+    ],
+    shared_libs: [
+        "libui",
+        "libnativewindow"
+    ],
+    defaults: ["hwc_tests_defaults"],
+}
+
+cc_defaults {
+
+    name: "hwc_lib_defaults",
+    shared_libs: [
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libhardware",
+        "liblog",
+        "libui",
+        "libutils",
+        "libnativewindow"
+    ],
+
+    gtest: false,
+
+    static_libs: [
+        "libglTest",
+        "libhwcTest",
+        "libtestUtil",
+    ],
+}
+
+cc_test {
+
+    name: "hwcStress",
+    srcs: ["hwcStress.cpp"],
+
+    defaults: [
+        "hwc_lib_defaults",
+        "hwc_tests_defaults",
+    ],
+}
+
+cc_test {
+
+    name: "hwcRects",
+    srcs: ["hwcRects.cpp"],
+
+    defaults: [
+        "hwc_lib_defaults",
+        "hwc_tests_defaults",
+    ],
+}
+
+cc_test {
+
+    name: "hwcColorEquiv",
+    srcs: ["hwcColorEquiv.cpp"],
+
+    defaults: [
+        "hwc_lib_defaults",
+        "hwc_tests_defaults",
+    ],
+}
+
+cc_test {
+
+    name: "hwcCommit",
+    srcs: ["hwcCommit.cpp"],
+
+    defaults: [
+        "hwc_lib_defaults",
+        "hwc_tests_defaults",
+    ],
+}
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
deleted file mode 100644
index 13337c2..0000000
--- a/opengl/tests/hwc/Android.mk
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE:= libhwcTest
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcTestLib.cpp
-LOCAL_C_INCLUDES += system/extras/tests/include \
-    $(call include-path-for, opengl-tests-includes) \
-
-LOCAL_STATIC_LIBRARIES := libarect
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcStress
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcStress.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv2 \
-    libutils \
-    liblog \
-    libui \
-    libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtestUtil \
-    libglTest \
-    libhwcTest \
-
-LOCAL_C_INCLUDES += \
-    system/extras/tests/include \
-    hardware/libhardware/include \
-    $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcRects
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcRects.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv2 \
-    libutils \
-    liblog \
-    libui \
-    libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtestUtil \
-    libglTest \
-    libhwcTest \
-
-LOCAL_C_INCLUDES += \
-    system/extras/tests/include \
-    hardware/libhardware/include \
-    $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcColorEquiv
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcColorEquiv.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv2 \
-    libutils \
-    liblog \
-    libui \
-    libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtestUtil \
-    libglTest \
-    libhwcTest \
-
-LOCAL_C_INCLUDES += \
-    system/extras/tests/include \
-    hardware/libhardware/include \
-    $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE:= hwcCommit
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-LOCAL_CXX_STL := libc++
-LOCAL_SRC_FILES:= hwcCommit.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libEGL \
-    libGLESv2 \
-    libutils \
-    liblog \
-    libui \
-    libhardware \
-
-LOCAL_STATIC_LIBRARIES := \
-    libtestUtil \
-    libglTest \
-    libhwcTest \
-
-LOCAL_C_INCLUDES += \
-    system/extras/tests/include \
-    hardware/libhardware/include \
-    $(call include-path-for, opengl-tests-includes) \
-
-include $(BUILD_NATIVE_TEST)
diff --git a/opengl/tests/include/EGLUtils.h b/opengl/tests/include/EGLUtils.h
deleted file mode 100644
index 014c261..0000000
--- a/opengl/tests/include/EGLUtils.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2009 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_UI_EGLUTILS_H
-#define ANDROID_UI_EGLUTILS_H
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <system/window.h>
-#include <utils/Errors.h>
-#include <EGL/egl.h>
-
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-class EGLUtils
-{
-public:
-
-    static inline const char *strerror(EGLint err);
-
-    static inline status_t selectConfigForPixelFormat(
-            EGLDisplay dpy,
-            EGLint const* attrs,
-            int32_t format,
-            EGLConfig* outConfig);
-
-    static inline status_t selectConfigForNativeWindow(
-            EGLDisplay dpy,
-            EGLint const* attrs,
-            EGLNativeWindowType window,
-            EGLConfig* outConfig);
-};
-
-// ----------------------------------------------------------------------------
-
-const char *EGLUtils::strerror(EGLint err)
-{
-    switch (err){
-        case EGL_SUCCESS:           return "EGL_SUCCESS";
-        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
-        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
-        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
-        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
-        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
-        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
-        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
-        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
-        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
-        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
-        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
-        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
-        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
-        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
-        default: return "UNKNOWN";
-    }
-}
-
-status_t EGLUtils::selectConfigForPixelFormat(
-        EGLDisplay dpy,
-        EGLint const* attrs,
-        int32_t format,
-        EGLConfig* outConfig)
-{
-    EGLint numConfigs = -1, n=0;
-
-    if (!attrs)
-        return BAD_VALUE;
-
-    if (outConfig == NULL)
-        return BAD_VALUE;
-
-    // Get all the "potential match" configs...
-    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
-        return BAD_VALUE;
-
-    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
-    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
-        free(configs);
-        return BAD_VALUE;
-    }
-
-    int i;
-    EGLConfig config = NULL;
-    for (i=0 ; i<n ; i++) {
-        EGLint nativeVisualId = 0;
-        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
-        if (nativeVisualId>0 && format == nativeVisualId) {
-            config = configs[i];
-            break;
-        }
-    }
-
-    free(configs);
-
-    if (i<n) {
-        *outConfig = config;
-        return NO_ERROR;
-    }
-
-    return NAME_NOT_FOUND;
-}
-
-status_t EGLUtils::selectConfigForNativeWindow(
-        EGLDisplay dpy,
-        EGLint const* attrs,
-        EGLNativeWindowType window,
-        EGLConfig* outConfig)
-{
-    int err;
-    int format;
-
-    if (!window)
-        return BAD_VALUE;
-
-    if ((err = window->query(window, NATIVE_WINDOW_FORMAT, &format)) < 0) {
-        return err;
-    }
-
-    return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
-
-#endif /* ANDROID_UI_EGLUTILS_H */
diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp
new file mode 100644
index 0000000..2f6095d
--- /dev/null
+++ b/opengl/tests/lib/Android.bp
@@ -0,0 +1,38 @@
+// 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.
+
+cc_library_static {
+
+    name: "libglTest",
+    srcs: [
+        "glTestLib.cpp",
+        "WindowSurface.cpp",
+    ],
+    export_include_dirs: ["include"],
+
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    shared_libs: ["libgui"],
+    static_libs: [
+        "libarect",
+        "libtestUtil",
+    ],
+
+}
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
deleted file mode 100644
index ea94bc1..0000000
--- a/opengl/tests/lib/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE:= libglTest
-LOCAL_SRC_FILES:= glTestLib.cpp WindowSurface.cpp
-LOCAL_C_INCLUDES += system/extras/tests/include \
-	$(call include-path-for, opengl-tests-includes)
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
-
-LOCAL_SHARED_LIBRARIES += libgui
-LOCAL_STATIC_LIBRARIES := libarect
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h
new file mode 100644
index 0000000..9dc6bcf
--- /dev/null
+++ b/opengl/tests/lib/include/EGLUtils.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2009 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_UI_EGLUTILS_H
+#define ANDROID_UI_EGLUTILS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <vector>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <system/window.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class EGLUtils
+{
+public:
+
+    static inline const char *strerror(EGLint err);
+
+    static inline status_t selectConfigForPixelFormat(
+            EGLDisplay dpy,
+            EGLint const* attrs,
+            int32_t format,
+            EGLConfig* outConfig);
+
+    static inline status_t selectConfigForNativeWindow(
+            EGLDisplay dpy,
+            EGLint const* attrs,
+            EGLNativeWindowType window,
+            EGLConfig* outConfig);
+
+    static inline String8 printGLString(const char* name, GLenum s);
+    static inline String8 printEGLString(EGLDisplay dpy, const char* name, GLenum s);
+    static inline String8 checkEglError(const char* op, EGLBoolean returnVal);
+    static inline String8 checkGlError(const char* op);
+    static inline String8 printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
+    static inline bool printEGLConfigurations(EGLDisplay dpy, String8& msg);
+    static inline bool printEGLConfigurations(FILE* output, EGLDisplay dpy);
+    static inline String8 decodeColorSpace(EGLint colorSpace);
+    static inline bool hasEglExtension(EGLDisplay dpy, const char* name);
+    static inline bool hasExtension(const char* exts, const char* name);
+};
+
+// ----------------------------------------------------------------------------
+
+const char *EGLUtils::strerror(EGLint err)
+{
+    switch (err){
+        case EGL_SUCCESS:           return "EGL_SUCCESS";
+        case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
+        case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
+        case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
+        case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
+        case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+        case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
+        case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
+        case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+        case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
+        case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
+        case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
+        default: return "UNKNOWN";
+    }
+}
+
+status_t EGLUtils::selectConfigForPixelFormat(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        int32_t format,
+        EGLConfig* outConfig)
+{
+    EGLint numConfigs = -1, n=0;
+
+    if (!attrs)
+        return BAD_VALUE;
+
+    if (outConfig == NULL)
+        return BAD_VALUE;
+
+    // Get all the "potential match" configs...
+    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
+        return BAD_VALUE;
+
+    std::vector<EGLConfig> configs(numConfigs);
+    if (eglChooseConfig(dpy, attrs, configs.data(), numConfigs, &n) == EGL_FALSE) {
+        return BAD_VALUE;
+    }
+
+    int i;
+    EGLConfig config = NULL;
+    for (i=0 ; i<n ; i++) {
+        EGLint nativeVisualId = 0;
+        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+        if (nativeVisualId>0 && format == nativeVisualId) {
+            config = configs[i];
+            break;
+        }
+    }
+
+    if (i<n) {
+        *outConfig = config;
+        return NO_ERROR;
+    }
+
+    return NAME_NOT_FOUND;
+}
+
+status_t EGLUtils::selectConfigForNativeWindow(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        EGLNativeWindowType window,
+        EGLConfig* outConfig)
+{
+    int err;
+    int format;
+
+    if (!window)
+        return BAD_VALUE;
+
+    if ((err = window->query(window, NATIVE_WINDOW_FORMAT, &format)) < 0) {
+        return err;
+    }
+
+    return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
+}
+
+String8 EGLUtils::printGLString(const char* name, GLenum s) {
+    String8 msg;
+    const char* v = reinterpret_cast<const char*>(glGetString(s));
+    msg.appendFormat("GL %s = %s\n", name, v);
+    return msg;
+}
+
+String8 EGLUtils::printEGLString(EGLDisplay dpy, const char* name, GLenum s) {
+    String8 msg;
+    const char* v = static_cast<const char*>(eglQueryString(dpy, s));
+    msg.appendFormat("GL %s = %s\n", name, v);
+    const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
+    msg.appendFormat("ImplementationANDROID: %s = %s\n", name, va);
+    return msg;
+}
+
+String8 EGLUtils::checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    String8 msg;
+    if (returnVal != EGL_TRUE) {
+        msg.appendFormat("%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) {
+        msg.appendFormat("after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), error);
+    }
+    return msg;
+}
+
+String8 EGLUtils::checkGlError(const char* op) {
+    String8 msg;
+    for (GLint error = glGetError(); error != GL_NO_ERROR; error = glGetError()) {
+        msg.appendFormat("after %s() glError (0x%x)\n", op, error);
+    }
+    return msg;
+}
+
+String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+#define X(VAL) \
+    { VAL, #VAL }
+    struct {
+        EGLint attribute;
+        const char* name;
+    } names[] = {
+            X(EGL_BUFFER_SIZE),
+            X(EGL_ALPHA_SIZE),
+            X(EGL_BLUE_SIZE),
+            X(EGL_GREEN_SIZE),
+            X(EGL_RED_SIZE),
+            X(EGL_DEPTH_SIZE),
+            X(EGL_STENCIL_SIZE),
+            X(EGL_CONFIG_CAVEAT),
+            X(EGL_CONFIG_ID),
+            X(EGL_LEVEL),
+            X(EGL_MAX_PBUFFER_HEIGHT),
+            X(EGL_MAX_PBUFFER_PIXELS),
+            X(EGL_MAX_PBUFFER_WIDTH),
+            X(EGL_NATIVE_RENDERABLE),
+            X(EGL_NATIVE_VISUAL_ID),
+            X(EGL_NATIVE_VISUAL_TYPE),
+            X(EGL_SAMPLES),
+            X(EGL_SAMPLE_BUFFERS),
+            X(EGL_SURFACE_TYPE),
+            X(EGL_TRANSPARENT_TYPE),
+            X(EGL_TRANSPARENT_RED_VALUE),
+            X(EGL_TRANSPARENT_GREEN_VALUE),
+            X(EGL_TRANSPARENT_BLUE_VALUE),
+            X(EGL_BIND_TO_TEXTURE_RGB),
+            X(EGL_BIND_TO_TEXTURE_RGBA),
+            X(EGL_MIN_SWAP_INTERVAL),
+            X(EGL_MAX_SWAP_INTERVAL),
+            X(EGL_LUMINANCE_SIZE),
+            X(EGL_ALPHA_MASK_SIZE),
+            X(EGL_COLOR_BUFFER_TYPE),
+            X(EGL_RENDERABLE_TYPE),
+            X(EGL_CONFORMANT),
+    };
+#undef X
+
+    String8 msg;
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            msg.appendFormat(" %s: %d (0x%x)", names[j].name, value, value);
+        }
+    }
+    msg.append("\n");
+    return msg;
+}
+
+bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) {
+    EGLint numConfig = 0;
+    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+    msg.append(checkEglError("eglGetConfigs", returnVal));
+    if (!returnVal) {
+        return false;
+    }
+
+    msg.appendFormat("Number of EGL configuration: %d\n", numConfig);
+
+    std::vector<EGLConfig> configs(numConfig);
+
+    returnVal = eglGetConfigs(dpy, configs.data(), numConfig, &numConfig);
+    msg.append(checkEglError("eglGetConfigs", returnVal));
+    if (!returnVal) {
+        return false;
+    }
+
+    for (int i = 0; i < numConfig; i++) {
+        msg.appendFormat("Configuration %d\n", i);
+        msg.append(printEGLConfiguration(dpy, configs[i]));
+    }
+
+    return true;
+}
+
+bool EGLUtils::printEGLConfigurations(FILE* output, EGLDisplay dpy) {
+    String8 msg;
+    bool status = printEGLConfigurations(dpy, msg);
+    fprintf(output, "%s", msg.c_str());
+    return status;
+}
+
+String8 EGLUtils::decodeColorSpace(EGLint colorSpace) {
+    switch (colorSpace) {
+        case EGL_GL_COLORSPACE_SRGB_KHR:
+            return String8("EGL_GL_COLORSPACE_SRGB_KHR");
+        case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+            return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT");
+        case  EGL_GL_COLORSPACE_LINEAR_KHR:
+            return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
+        default:
+            return String8::format("UNKNOWN ColorSpace %d", colorSpace);
+    }
+}
+
+bool EGLUtils::hasExtension(const char* exts, const char* name) {
+    size_t nameLen = strlen(name);
+    if (exts) {
+        for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
+            if (match[nameLen] == '\0' || match[nameLen] == ' ') {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) {
+    return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+#endif /* ANDROID_UI_EGLUTILS_H */
diff --git a/opengl/tests/include/WindowSurface.h b/opengl/tests/lib/include/WindowSurface.h
similarity index 100%
rename from opengl/tests/include/WindowSurface.h
rename to opengl/tests/lib/include/WindowSurface.h
diff --git a/opengl/tests/include/glTestLib.h b/opengl/tests/lib/include/glTestLib.h
similarity index 100%
rename from opengl/tests/include/glTestLib.h
rename to opengl/tests/lib/include/glTestLib.h
diff --git a/opengl/tests/linetex/linetex.cpp b/opengl/tests/linetex/linetex.cpp
index 5ad695b..cdc051b 100644
--- a/opengl/tests/linetex/linetex.cpp
+++ b/opengl/tests/linetex/linetex.cpp
@@ -29,7 +29,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     EGLint configAttribs[] = {
          EGL_DEPTH_SIZE, 0,
diff --git a/opengl/tests/swapinterval/swapinterval.cpp b/opengl/tests/swapinterval/swapinterval.cpp
index 3a8a8a1..c4261e6 100644
--- a/opengl/tests/swapinterval/swapinterval.cpp
+++ b/opengl/tests/swapinterval/swapinterval.cpp
@@ -28,7 +28,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     EGLint configAttribs[] = {
             EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
diff --git a/opengl/tests/textures/textures.cpp b/opengl/tests/textures/textures.cpp
index 1e55db0..7be942a 100644
--- a/opengl/tests/textures/textures.cpp
+++ b/opengl/tests/textures/textures.cpp
@@ -27,7 +27,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     EGLint configAttribs[] = {
          EGL_DEPTH_SIZE, 0,
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index af13395..c2d3494 100755
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -191,6 +191,7 @@
         <enum value="((EGLSync)0)" name="EGL_NO_SYNC"/>
         <enum value="((EGLSyncKHR)0)" name="EGL_NO_SYNC_KHR" alias="EGL_NO_SYNC"/>
         <enum value="((EGLSyncNV)0)" name="EGL_NO_SYNC_NV" alias="EGL_NO_SYNC"/>
+        <enum value="EGL_CAST(EGLConfig,0)" name="EGL_NO_CONFIG_KHR"/>
         <enum value="10000" name="EGL_DISPLAY_SCALING"/>
         <enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER" type="ull"/>
         <enum value="0xFFFFFFFFFFFFFFFF" name="EGL_FOREVER_KHR" type="ull" alias="EGL_FOREVER"/>
@@ -739,7 +740,10 @@
         <enum value="50000"  name="EGL_METADATA_SCALING_EXT"/>
             <unused start="0x334B" end="0x334F"/>
         <enum value="0x3350" name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
-            <unused start="0x3351" end="0x339F"/>
+            <unused start="0x3351" end="0x3361"/>
+        <enum value="0x3362" name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+        <enum value="0x3363" name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+            <unused start="0x3364" end="0x339F"/>
     </enums>
 
     <enums namespace="EGL" start="0x33A0" end="0x33AF" vendor="ANGLE" comment="Reserved for Shannon Woods (Bug 13175)">
@@ -1891,6 +1895,16 @@
                 <enum name="EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_gl_colorspace_display_p3_linear" supported="egl">
+            <require>
+                <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_gl_colorspace_display_p3" supported="egl">
+            <require>
+                <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_image_dma_buf_import" supported="egl">
             <require>
                 <enum name="EGL_LINUX_DMA_BUF_EXT"/>
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index e441bda..4c7265b 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -1,3 +1,11 @@
+cc_library_headers {
+    name: "libbatteryservice_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+    header_libs: ["libbinder_headers"],
+    export_header_lib_headers: ["libbinder_headers"],
+}
+
 cc_library {
     name: "libbatteryservice",
 
@@ -8,6 +16,9 @@
         "IBatteryPropertiesRegistrar.cpp",
     ],
 
+    header_libs: ["libbatteryservice_headers"],
+    export_header_lib_headers: ["libbatteryservice_headers"],
+
     shared_libs: [
         "libutils",
         "libbinder",
@@ -19,4 +30,4 @@
         "-Wunused",
         "-Wunreachable-code",
     ],
-}
\ No newline at end of file
+}
diff --git a/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h
similarity index 100%
rename from include/batteryservice/BatteryService.h
rename to services/batteryservice/include/batteryservice/BatteryService.h
diff --git a/include/batteryservice/BatteryServiceConstants.h b/services/batteryservice/include/batteryservice/BatteryServiceConstants.h
similarity index 100%
rename from include/batteryservice/BatteryServiceConstants.h
rename to services/batteryservice/include/batteryservice/BatteryServiceConstants.h
diff --git a/include/batteryservice/IBatteryPropertiesListener.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
similarity index 100%
rename from include/batteryservice/IBatteryPropertiesListener.h
rename to services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
diff --git a/include/batteryservice/IBatteryPropertiesRegistrar.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
similarity index 100%
rename from include/batteryservice/IBatteryPropertiesRegistrar.h
rename to services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
new file mode 100644
index 0000000..4fd98e2
--- /dev/null
+++ b/services/inputflinger/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libinputflinger",
+
+    srcs: [
+        "EventHub.cpp",
+        "InputApplication.cpp",
+        "InputDispatcher.cpp",
+        "InputListener.cpp",
+        "InputManager.cpp",
+        "InputReader.cpp",
+        "InputWindow.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libutils",
+        "libui",
+        "libhardware_legacy",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        // TODO: Move inputflinger to its own process and mark it hidden
+        //-fvisibility=hidden
+    ],
+
+    export_include_dirs: ["."],
+}
+
+subdirs = [
+    "host",
+    "tests",
+]
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
deleted file mode 100644
index ed867d8..0000000
--- a/services/inputflinger/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    EventHub.cpp \
-    InputApplication.cpp \
-    InputDispatcher.cpp \
-    InputListener.cpp \
-    InputManager.cpp \
-    InputReader.cpp \
-    InputWindow.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libcrypto \
-    libcutils \
-    libinput \
-    liblog \
-    libutils \
-    libui \
-    libhardware_legacy
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflinger
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index d2f8995..50589b4 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -150,7 +150,8 @@
         fd(fd), id(id), path(path), identifier(identifier),
         classes(0), configuration(NULL), virtualKeyMap(NULL),
         ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
-        timestampOverrideSec(0), timestampOverrideUsec(0) {
+        timestampOverrideSec(0), timestampOverrideUsec(0), enabled(true),
+        isVirtual(fd < 0) {
     memset(keyBitmask, 0, sizeof(keyBitmask));
     memset(absBitmask, 0, sizeof(absBitmask));
     memset(relBitmask, 0, sizeof(relBitmask));
@@ -173,6 +174,25 @@
     }
 }
 
+status_t EventHub::Device::enable() {
+    fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+    if(fd < 0) {
+        ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
+        return -errno;
+    }
+    enabled = true;
+    return OK;
+}
+
+status_t EventHub::Device::disable() {
+    close();
+    enabled = false;
+    return OK;
+}
+
+bool EventHub::Device::hasValidFd() {
+    return !isVirtual && enabled;
+}
 
 // --- EventHub ---
 
@@ -286,7 +306,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -337,7 +357,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
+        if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) {
             uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
             memset(keyState, 0, sizeof(keyState));
             if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
@@ -352,7 +372,7 @@
     AutoMutex _l(mLock);
 
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
+    if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
         Vector<int32_t> scanCodes;
         device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
         if (scanCodes.size() != 0) {
@@ -377,7 +397,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
+        if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) {
             uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
             memset(swState, 0, sizeof(swState));
             if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
@@ -395,7 +415,7 @@
         AutoMutex _l(mLock);
 
         Device* device = getDeviceLocked(deviceId);
-        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
+        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -532,7 +552,7 @@
 
 void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
     int32_t sc;
-    if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
+    if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
         struct input_event ev;
         ev.time.tv_sec = 0;
         ev.time.tv_usec = 0;
@@ -636,7 +656,7 @@
 void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual()) {
+    if (device && device->hasValidFd()) {
         ff_effect effect;
         memset(&effect, 0, sizeof(effect));
         effect.type = FF_RUMBLE;
@@ -670,7 +690,7 @@
 void EventHub::cancelVibrate(int32_t deviceId) {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device && !device->isVirtual()) {
+    if (device && device->hasValidFd()) {
         if (device->ffEffectPlaying) {
             device->ffEffectPlaying = false;
 
@@ -1065,12 +1085,37 @@
         AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
 };
 
+status_t EventHub::registerDeviceForEpollLocked(Device* device) {
+    struct epoll_event eventItem;
+    memset(&eventItem, 0, sizeof(eventItem));
+    eventItem.events = EPOLLIN;
+    if (mUsingEpollWakeup) {
+        eventItem.events |= EPOLLWAKEUP;
+    }
+    eventItem.data.u32 = device->id;
+    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
+        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
+        return -errno;
+    }
+    return OK;
+}
+
+status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
+    if (device->hasValidFd()) {
+        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
+            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
+            return -errno;
+        }
+    }
+    return OK;
+}
+
 status_t EventHub::openDeviceLocked(const char *devicePath) {
     char buffer[80];
 
     ALOGV("Opening device: %s", devicePath);
 
-    int fd = open(devicePath, O_RDWR | O_CLOEXEC);
+    int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
     if(fd < 0) {
         ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
         return -1;
@@ -1135,13 +1180,6 @@
     // Fill in the descriptor.
     assignDescriptorLocked(identifier);
 
-    // Make file descriptor non-blocking for use with poll().
-    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
-        ALOGE("Error %d making device file descriptor non-blocking.", errno);
-        close(fd);
-        return -1;
-    }
-
     // Allocate device.  (The device object takes ownership of the fd at this point.)
     int32_t deviceId = mNextDeviceId++;
     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
@@ -1303,12 +1341,6 @@
                 break;
             }
         }
-
-        // Disable kernel key repeat since we handle it ourselves
-        unsigned int repeatRate[] = {0,0};
-        if (ioctl(fd, EVIOCSREP, repeatRate)) {
-            ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
-        }
     }
 
     // If the device isn't recognized as something we handle, don't monitor it.
@@ -1332,23 +1364,41 @@
     if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
             && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
         device->controllerNumber = getNextControllerNumberLocked(device);
-        setLedForController(device);
+        setLedForControllerLocked(device);
     }
 
-    // Register with epoll.
-    struct epoll_event eventItem;
-    memset(&eventItem, 0, sizeof(eventItem));
-    eventItem.events = EPOLLIN;
-    if (mUsingEpollWakeup) {
-        eventItem.events |= EPOLLWAKEUP;
-    }
-    eventItem.data.u32 = deviceId;
-    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
-        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
+
+    if (registerDeviceForEpollLocked(device) != OK) {
         delete device;
         return -1;
     }
 
+    configureFd(device);
+
+    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
+         deviceId, fd, devicePath, device->identifier.name.string(),
+         device->classes,
+         device->configurationFile.string(),
+         device->keyMap.keyLayoutFile.string(),
+         device->keyMap.keyCharacterMapFile.string(),
+         toString(mBuiltInKeyboardId == deviceId));
+
+    addDeviceLocked(device);
+    return OK;
+}
+
+void EventHub::configureFd(Device* device) {
+    // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
+    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+        // Disable kernel key repeat since we handle it ourselves
+        unsigned int repeatRate[] = {0, 0};
+        if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
+            ALOGW("Unable to disable kernel key repeat for %s: %s",
+                  device->path.string(), strerror(errno));
+        }
+    }
+
     String8 wakeMechanism("EPOLLWAKEUP");
     if (!mUsingEpollWakeup) {
 #ifndef EVIOCSSUSPENDBLOCK
@@ -1357,44 +1407,67 @@
         // this feature, we need to be prepared to define the ioctl ourselves.
 #define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
 #endif
-        if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
+        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.
-    //
-    // In older kernel, before Linux 3.4, there was no way to tell the kernel which
-    // clock to use to input event timestamps.  The standard kernel behavior was to
-    // record a real time timestamp, which isn't what we want.  Android kernels therefore
-    // contained a patch to the evdev_event() function in drivers/input/evdev.c to
-    // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
-    // clock to be used instead of the real time clock.
-    //
-    // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
-    // Therefore, we no longer require the Android-specific kernel patch described above
-    // as long as we make sure to set select the monotonic clock.  We do that here.
     int clockId = CLOCK_MONOTONIC;
-    bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
+    bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
+    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
+          toString(usingClockIoctl));
+}
 
-    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
-            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
-            "wakeMechanism=%s, usingClockIoctl=%s",
-         deviceId, fd, devicePath, device->identifier.name.string(),
-         device->classes,
-         device->configurationFile.string(),
-         device->keyMap.keyLayoutFile.string(),
-         device->keyMap.keyCharacterMapFile.string(),
-         toString(mBuiltInKeyboardId == deviceId),
-         wakeMechanism.string(), toString(usingClockIoctl));
+bool EventHub::isDeviceEnabled(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return false;
+    }
+    return device->enabled;
+}
 
-    addDeviceLocked(device);
-    return 0;
+status_t EventHub::enableDevice(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return BAD_VALUE;
+    }
+    if (device->enabled) {
+        ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
+        return OK;
+    }
+    status_t result = device->enable();
+    if (result != OK) {
+        ALOGE("Failed to enable device %" PRId32, deviceId);
+        return result;
+    }
+
+    configureFd(device);
+
+    return registerDeviceForEpollLocked(device);
+}
+
+status_t EventHub::disableDevice(int32_t deviceId) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) {
+        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
+        return BAD_VALUE;
+    }
+    if (!device->enabled) {
+        ALOGW("Duplicate call to %s, input device already disabled", __func__);
+        return OK;
+    }
+    unregisterDeviceFromEpollLocked(device);
+    return device->disable();
 }
 
 void EventHub::createVirtualKeyboardLocked() {
@@ -1490,7 +1563,7 @@
     mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
 }
 
-void EventHub::setLedForController(Device* device) {
+void EventHub::setLedForControllerLocked(Device* device) {
     for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
         setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
     }
@@ -1500,7 +1573,7 @@
     if (!device->keyMap.haveKeyLayout()) {
         return false;
     }
-    
+
     Vector<int32_t> scanCodes;
     device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
     const size_t N = scanCodes.size();
@@ -1510,7 +1583,7 @@
             return true;
         }
     }
-    
+
     return false;
 }
 
@@ -1556,11 +1629,7 @@
         mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
     }
 
-    if (!device->isVirtual()) {
-        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
-            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
-        }
-    }
+    unregisterDeviceFromEpollLocked(device);
 
     releaseControllerNumberLocked(device);
 
@@ -1691,6 +1760,7 @@
             }
             dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
             dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+            dump.appendFormat(INDENT3 "Enabled: %s\n", toString(device->enabled));
             dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
             dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
             dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 6869253..727b73a 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -25,9 +25,8 @@
 #include <input/KeyCharacterMap.h>
 #include <input/VirtualKeyMap.h>
 #include <utils/String8.h>
-#include <utils/threads.h>
+#include <utils/Mutex.h>
 #include <utils/Log.h>
-#include <utils/threads.h>
 #include <utils/List.h>
 #include <utils/Errors.h>
 #include <utils/PropertyMap.h>
@@ -267,6 +266,15 @@
 
     /* Called by the heatbeat to ensures that the reader has not deadlocked. */
     virtual void monitor() = 0;
+
+    /* Return true if the device is enabled. */
+    virtual bool isDeviceEnabled(int32_t deviceId) = 0;
+
+    /* Enable an input device */
+    virtual status_t enableDevice(int32_t deviceId) = 0;
+
+    /* Disable an input device. Closes file descriptor to that device. */
+    virtual status_t disableDevice(int32_t deviceId) = 0;
 };
 
 class EventHub : public EventHubInterface
@@ -335,7 +343,7 @@
     struct Device {
         Device* next;
 
-        int fd; // may be -1 if device is virtual
+        int fd; // may be -1 if device is closed
         const int32_t id;
         const String8 path;
         const InputDeviceIdentifier identifier;
@@ -371,7 +379,11 @@
 
         void close();
 
-        inline bool isVirtual() const { return fd < 0; }
+        bool enabled; // initially true
+        status_t enable();
+        status_t disable();
+        bool hasValidFd();
+        const bool isVirtual; // set if fd < 0 is passed to constructor
 
         const sp<KeyCharacterMap>& getKeyCharacterMap() const {
             if (combinedKeyMap != NULL) {
@@ -390,6 +402,14 @@
     void closeDeviceLocked(Device* device);
     void closeAllDevicesLocked();
 
+    void configureFd(Device* device);
+
+    bool isDeviceEnabled(int32_t deviceId);
+    status_t enableDevice(int32_t deviceId);
+    status_t disableDevice(int32_t deviceId);
+    status_t registerDeviceForEpollLocked(Device* device);
+    status_t unregisterDeviceFromEpollLocked(Device* device);
+
     status_t scanDirLocked(const char *dirname);
     void scanDevicesLocked();
     status_t readNotifyLocked();
@@ -409,7 +429,7 @@
 
     int32_t getNextControllerNumberLocked(Device* device);
     void releaseControllerNumberLocked(Device* device);
-    void setLedForController(Device* device);
+    void setLedForControllerLocked(Device* device);
 
     status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
     void setLedStateLocked(Device* device, int32_t led, bool on);
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2efb340..69067d2 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -869,10 +869,7 @@
         return true;
     }
 
-    // TODO: support sending secondary display events to input monitors
-    if (isMainDisplay(entry->displayId)) {
-        addMonitoringTargetsLocked(inputTargets);
-    }
+    addMonitoringTargetsLocked(inputTargets);
 
     // Dispatch the motion.
     if (conflictingPointerActions) {
@@ -2026,7 +2023,7 @@
 
             // Publish the motion event.
             status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
-                    motionEntry->deviceId, motionEntry->source,
+                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
                     dispatchEntry->resolvedAction, motionEntry->actionButton,
                     dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                     motionEntry->metaState, motionEntry->buttonState,
@@ -2600,8 +2597,9 @@
         uint32_t policyFlags) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
-            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x, displayId=%d",
+            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags,
+            displayId);
 #endif
 
     nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 73255dd..d4266f6 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -147,7 +147,33 @@
 static const size_t keyCodeRotationMapSize =
         sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
 
+static int32_t rotateStemKey(int32_t value, int32_t orientation,
+        const int32_t map[][2], size_t mapSize) {
+    if (orientation == DISPLAY_ORIENTATION_180) {
+        for (size_t i = 0; i < mapSize; i++) {
+            if (value == map[i][0]) {
+                return map[i][1];
+            }
+        }
+    }
+    return value;
+}
+
+// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
+static int32_t stemKeyRotationMap[][2] = {
+        // key codes enumerated with the original (unrotated) key first
+        // no rotation,           180 degree rotation
+        { AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY },
+        { AKEYCODE_STEM_1,       AKEYCODE_STEM_1 },
+        { AKEYCODE_STEM_2,       AKEYCODE_STEM_2 },
+        { AKEYCODE_STEM_3,       AKEYCODE_STEM_3 },
+};
+static const size_t stemKeyRotationMapSize =
+        sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
+
 static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+    keyCode = rotateStemKey(keyCode, orientation,
+            stemKeyRotationMap, stemKeyRotationMapSize);
     return rotateValueUsingRotationMap(keyCode, orientation,
             keyCodeRotationMap, keyCodeRotationMapSize);
 }
@@ -231,7 +257,7 @@
         const String8* uniqueDisplayId, DisplayViewport* outViewport) const {
     const DisplayViewport* viewport = NULL;
     if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != NULL) {
-        for (DisplayViewport currentViewport : mVirtualDisplays) {
+        for (const DisplayViewport& currentViewport : mVirtualDisplays) {
             if (currentViewport.uniqueId == *uniqueDisplayId) {
                 viewport = &currentViewport;
                 break;
@@ -835,6 +861,18 @@
     }
 }
 
+bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex >= 0) {
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        return device->isEnabled();
+    }
+    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
+    return false;
+}
+
 void InputReader::dump(String8& dump) {
     AutoMutex _l(mLock);
 
@@ -1011,6 +1049,26 @@
     mMappers.clear();
 }
 
+bool InputDevice::isEnabled() {
+    return getEventHub()->isDeviceEnabled(mId);
+}
+
+void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+    if (isEnabled() == enabled) {
+        return;
+    }
+
+    if (enabled) {
+        getEventHub()->enableDevice(mId);
+        reset(when);
+    } else {
+        reset(when);
+        getEventHub()->disableDevice(mId);
+    }
+    // Must change generation to flag this device as changed
+    bumpGeneration();
+}
+
 void InputDevice::dump(String8& dump) {
     InputDeviceInfo deviceInfo;
     getDeviceInfo(& deviceInfo);
@@ -1082,6 +1140,12 @@
             }
         }
 
+        if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
+            ssize_t index = config->disabledDevices.indexOf(mId);
+            bool enabled = index < 0;
+            setEnabled(enabled, when);
+        }
+
         size_t numMappers = mMappers.size();
         for (size_t i = 0; i < numMappers; i++) {
             InputMapper* mapper = mMappers[i];
@@ -2222,18 +2286,36 @@
     }
 }
 
+static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
+    int32_t mapped = 0;
+    if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
+        for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
+            if (stemKeyRotationMap[i][0] == keyCode) {
+                stemKeyRotationMap[i][1] = mapped;
+                return;
+            }
+        }
+    }
+}
+
 void KeyboardInputMapper::configureParameters() {
     mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
+    const PropertyMap& config = getDevice()->getConfiguration();
+    config.tryGetProperty(String8("keyboard.orientationAware"),
             mParameters.orientationAware);
 
     mParameters.hasAssociatedDisplay = false;
     if (mParameters.orientationAware) {
         mParameters.hasAssociatedDisplay = true;
+
+        mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
+        mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
+        mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
+        mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
     }
 
     mParameters.handlesKeyRepeat = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.handlesKeyRepeat"),
+    config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
             mParameters.handlesKeyRepeat);
 }
 
@@ -2291,6 +2373,35 @@
         || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
 }
 
+bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
+    switch (keyCode) {
+    case AKEYCODE_MEDIA_PLAY:
+    case AKEYCODE_MEDIA_PAUSE:
+    case AKEYCODE_MEDIA_PLAY_PAUSE:
+    case AKEYCODE_MUTE:
+    case AKEYCODE_HEADSETHOOK:
+    case AKEYCODE_MEDIA_STOP:
+    case AKEYCODE_MEDIA_NEXT:
+    case AKEYCODE_MEDIA_PREVIOUS:
+    case AKEYCODE_MEDIA_REWIND:
+    case AKEYCODE_MEDIA_RECORD:
+    case AKEYCODE_MEDIA_FAST_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_BACKWARD:
+    case AKEYCODE_MEDIA_STEP_FORWARD:
+    case AKEYCODE_MEDIA_STEP_BACKWARD:
+    case AKEYCODE_MEDIA_AUDIO_TRACK:
+    case AKEYCODE_VOLUME_UP:
+    case AKEYCODE_VOLUME_DOWN:
+    case AKEYCODE_VOLUME_MUTE:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
+        return true;
+    }
+    return false;
+}
+
 void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
         int32_t usageCode) {
     int32_t keyCode;
@@ -2364,7 +2475,7 @@
     // For internal keyboards, the key layout file should specify the policy flags for
     // each wake key individually.
     // TODO: Use the input device configuration to control this behavior more finely.
-    if (down && getDevice()->isExternal()) {
+    if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
         policyFlags |= POLICY_FLAG_WAKE;
     }
 
@@ -2859,7 +2970,7 @@
 // --- RotaryEncoderInputMapper ---
 
 RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
-        InputMapper(device) {
+        InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
     mSource = AINPUT_SOURCE_ROTARY_ENCODER;
 }
 
@@ -2901,6 +3012,14 @@
     if (!changes) {
         mRotaryEncoderScrollAccumulator.configure(getDevice());
     }
+    if (!changes || (InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+        DisplayViewport v;
+        if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
+            mOrientation = v.orientation;
+        } else {
+            mOrientation = DISPLAY_ORIENTATION_0;
+        }
+    }
 }
 
 void RotaryEncoderInputMapper::reset(nsecs_t when) {
@@ -2938,6 +3057,10 @@
         policyFlags |= POLICY_FLAG_WAKE;
     }
 
+    if (mOrientation == DISPLAY_ORIENTATION_180) {
+        scroll = -scroll;
+    }
+
     // Send motion event.
     if (scrolled) {
         int32_t metaState = mContext->getGlobalMetaState();
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index edb6fcc..a6b9798 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -27,11 +27,14 @@
 #include <input/VelocityTracker.h>
 #include <ui/DisplayInfo.h>
 #include <utils/KeyedVector.h>
-#include <utils/threads.h>
+#include <utils/Condition.h>
+#include <utils/Thread.h>
+#include <utils/Mutex.h>
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/BitSet.h>
+#include <utils/SortedVector.h>
 
 #include <stddef.h>
 #include <unistd.h>
@@ -84,6 +87,9 @@
         // The pointer capture mode has changed.
         CHANGE_POINTER_CAPTURE = 1 << 8,
 
+        // The set of disabled input devices (disabledDevices) has changed.
+        CHANGE_ENABLED_STATE = 1 << 9,
+
         // All devices must be reopened.
         CHANGE_MUST_REOPEN = 1 << 31,
     };
@@ -174,6 +180,9 @@
     // True if pointer capture is enabled.
     bool pointerCapture;
 
+    // The set of currently disabled input devices.
+    SortedVector<int32_t> disabledDevices;
+
     InputReaderConfiguration() :
             virtualKeyQuietTime(0),
             pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
@@ -288,6 +297,9 @@
     /* Called by the heatbeat to ensures that the reader has not deadlocked. */
     virtual void monitor() = 0;
 
+    /* Returns true if the input device is enabled. */
+    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
+
     /* Runs a single iteration of the processing loop.
      * Nominally reads and processes one incoming message from the EventHub.
      *
@@ -407,6 +419,8 @@
 
     virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
 
+    virtual bool isInputDeviceEnabled(int32_t deviceId);
+
     virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
             int32_t scanCode);
     virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
@@ -552,6 +566,9 @@
 
     inline bool isIgnored() { return mMappers.isEmpty(); }
 
+    bool isEnabled();
+    void setEnabled(bool enabled, nsecs_t when);
+
     void dump(String8& dump);
     void addMapper(InputMapper* mapper);
     void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
@@ -1111,6 +1128,7 @@
     void dumpParameters(String8& dump);
 
     bool isKeyboardOrGamepadKey(int32_t scanCode);
+    bool isMediaKey(int32_t keyCode);
 
     void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
 
@@ -1209,6 +1227,7 @@
 
     int32_t mSource;
     float mScalingFactor;
+    int32_t mOrientation;
 
     void sync(nsecs_t when);
 };
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index 5e82d75..3ae7972 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -46,8 +46,11 @@
             || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
             || layoutParamsType == TYPE_STATUS_BAR
             || layoutParamsType == TYPE_NAVIGATION_BAR
+            || layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
-            || layoutParamsType == TYPE_DOCK_DIVIDER;
+            || layoutParamsType == TYPE_DOCK_DIVIDER
+            || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
+            || layoutParamsType == TYPE_INPUT_CONSUMER;
 }
 
 bool InputWindowInfo::supportsSplitTouch() const {
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index feca6cf..9eb2798 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -101,7 +101,10 @@
         TYPE_NAVIGATION_BAR     = FIRST_SYSTEM_WINDOW+19,
         TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
         TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
-        TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+22,
+        TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22,
+        TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24,
+        TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27,
+        TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32,
         TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34,
         LAST_SYSTEM_WINDOW      = 2999,
     };
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
new file mode 100644
index 0000000..b8e9bce
--- /dev/null
+++ b/services/inputflinger/host/Android.bp
@@ -0,0 +1,57 @@
+// 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.
+
+cc_library_shared {
+    name: "libinputflingerhost",
+
+    srcs: [
+        "InputFlinger.cpp",
+        "InputDriver.cpp",
+        "InputHost.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libutils",
+        "libhardware",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        // TODO: Move inputflinger to its own process and mark it hidden
+        //-fvisibility=hidden
+    ],
+
+    export_include_dirs: ["."],
+}
+
+//#######################################################################
+// build input flinger executable
+cc_binary {
+    name: "inputflinger",
+
+    srcs: ["main.cpp"],
+
+    shared_libs: [
+        "libbinder",
+        "libinputflingerhost",
+        "libutils",
+    ],
+
+    init_rc: ["inputflinger.rc"],
+}
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
deleted file mode 100644
index 0a7fc27..0000000
--- a/services/inputflinger/host/Android.mk
+++ /dev/null
@@ -1,63 +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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
-    InputFlinger.cpp \
-    InputDriver.cpp \
-    InputHost.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libcrypto \
-    libcutils \
-    libinput \
-    liblog \
-    libutils \
-    libhardware
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflingerhost
-
-include $(BUILD_SHARED_LIBRARY)
-
-########################################################################
-# build input flinger executable
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
-	main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libbinder \
-	libinputflingerhost \
-	libutils
-
-LOCAL_MODULE := inputflinger
-LOCAL_INIT_RC := inputflinger.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
new file mode 100644
index 0000000..29d93f0
--- /dev/null
+++ b/services/inputflinger/tests/Android.bp
@@ -0,0 +1,23 @@
+// Build the unit tests.
+
+cc_test {
+    name: "inputflinger_tests",
+    srcs: [
+        "InputReader_test.cpp",
+        "InputDispatcher_test.cpp",
+    ],
+    test_per_src: true,
+    cflags: ["-Wno-unused-parameter"],
+    shared_libs = [
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libhardware",
+        "libhardware_legacy",
+        "libui",
+        "libskia",
+        "libinput",
+        "libinputflinger",
+        "libinputservice",
+    ],
+}
diff --git a/services/inputflinger/tests/Android.mk b/services/inputflinger/tests/Android.mk
deleted file mode 100644
index 4c43392..0000000
--- a/services/inputflinger/tests/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
-    InputReader_test.cpp \
-    InputDispatcher_test.cpp
-
-shared_libraries := \
-    libcutils \
-    liblog \
-    libutils \
-    libhardware \
-    libhardware_legacy \
-    libui \
-    libskia \
-    libinput \
-    libinputflinger \
-    libinputservice
-
-c_includes := \
-    external/skia/include/core
-
-
-module_tags := tests
-
-$(foreach file,$(test_src_files), \
-    $(eval include $(CLEAR_VARS)) \
-    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
-    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
-    $(eval LOCAL_CFLAGS += -Wno-unused-parameter) \
-    $(eval LOCAL_SRC_FILES := $(file)) \
-    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
-    $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
-    $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-# Build the manual test programs.
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index dcfe114..76291a5 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -16,6 +16,7 @@
 
 #include "../InputReader.h"
 
+#include <inttypes.h>
 #include <utils/List.h>
 #include <gtest/gtest.h>
 #include <math.h>
@@ -159,6 +160,22 @@
         mConfig.excludedDeviceNames.push(deviceName);
     }
 
+    void addDisabledDevice(int32_t deviceId) {
+        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+        bool currentlyEnabled = index < 0;
+        if (currentlyEnabled) {
+            mConfig.disabledDevices.add(deviceId);
+        }
+    }
+
+    void removeDisabledDevice(int32_t deviceId) {
+        ssize_t index = mConfig.disabledDevices.indexOf(deviceId);
+        bool currentlyEnabled = index < 0;
+        if (!currentlyEnabled) {
+            mConfig.disabledDevices.remove(deviceId);
+        }
+    }
+
     void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
         mPointerControllers.add(deviceId, controller);
     }
@@ -255,6 +272,11 @@
         mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin());
     }
 
+    void assertNotifyConfigurationChangedWasNotCalled() {
+        ASSERT_TRUE(mNotifyConfigurationChangedArgsQueue.empty())
+                << "Expected notifyConfigurationChanged() to not have been called.";
+    }
+
     void assertNotifyDeviceResetWasCalled(
             NotifyDeviceResetArgs* outEventArgs = NULL) {
         ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty())
@@ -265,6 +287,11 @@
         mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin());
     }
 
+    void assertNotifyDeviceResetWasNotCalled() {
+        ASSERT_TRUE(mNotifyDeviceResetArgsQueue.empty())
+                << "Expected notifyDeviceReset() to not have been called.";
+    }
+
     void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) {
         ASSERT_FALSE(mNotifyKeyArgsQueue.empty())
                 << "Expected notifyKey() to have been called.";
@@ -347,9 +374,20 @@
         KeyedVector<int32_t, KeyInfo> keysByUsageCode;
         KeyedVector<int32_t, bool> leds;
         Vector<VirtualKeyDefinition> virtualKeys;
+        bool enabled;
+
+        status_t enable() {
+            enabled = true;
+            return OK;
+        }
+
+        status_t disable() {
+            enabled = false;
+            return OK;
+        }
 
         explicit Device(uint32_t classes) :
-                classes(classes) {
+                classes(classes), enabled(true) {
         }
     };
 
@@ -382,6 +420,43 @@
         enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
     }
 
+    bool isDeviceEnabled(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return false;
+        }
+        return device->enabled;
+    }
+
+    status_t enableDevice(int32_t deviceId) {
+        status_t result;
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
+            return OK;
+        }
+        result = device->enable();
+        return result;
+    }
+
+    status_t disableDevice(int32_t deviceId) {
+        Device* device = getDevice(deviceId);
+        if (device == NULL) {
+            ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
+            return BAD_VALUE;
+        }
+        if (!device->enabled) {
+            ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
+            return OK;
+        }
+        return device->disable();
+    }
+
     void finishDeviceScan() {
         enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
     }
@@ -1039,6 +1114,20 @@
         mFakeEventHub->assertQueueIsEmpty();
     }
 
+    void disableDevice(int32_t deviceId, InputDevice* device) {
+        mFakePolicy->addDisabledDevice(deviceId);
+        configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+    }
+
+    void enableDevice(int32_t deviceId, InputDevice* device) {
+        mFakePolicy->removeDisabledDevice(deviceId);
+        configureDevice(InputReaderConfiguration::CHANGE_ENABLED_STATE, device);
+    }
+
+    void configureDevice(uint32_t changes, InputDevice* device) {
+        device->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
+    }
+
     FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
             const String8& name, uint32_t classes, uint32_t sources,
             const PropertyMap* configuration) {
@@ -1077,6 +1166,46 @@
     ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
 }
 
+TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
+    constexpr int32_t deviceId = 1;
+    constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+    InputDevice* device = mReader->newDevice(deviceId, 0, String8("fake"), deviceClass);
+    // Must add at least one mapper or the device will be ignored!
+    FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
+    device->addMapper(mapper);
+    mReader->setNextDevice(device);
+    addDevice(deviceId, String8("fake"), deviceClass, NULL);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(NULL));
+
+    NotifyDeviceResetArgs resetArgs;
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+
+    ASSERT_EQ(device->isEnabled(), true);
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_EQ(device->isEnabled(), false);
+
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasNotCalled();
+    mFakeListener->assertNotifyConfigurationChangedWasNotCalled();
+    ASSERT_EQ(device->isEnabled(), false);
+
+    enableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
+    ASSERT_EQ(deviceId, resetArgs.deviceId);
+    ASSERT_EQ(device->isEnabled(), true);
+}
+
 TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = NULL;
     ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
@@ -1274,6 +1403,10 @@
     ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
 }
 
+TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsTrue) {
+    ASSERT_EQ(mDevice->isEnabled(), true);
+}
+
 TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
     // Configuration.
     InputReaderConfiguration config;
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 1f1340c..ca91b8e 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -10,7 +10,6 @@
         "libmediautils",
         "liblog",
         "libutils",
-        "android.hidl.base@1.0",
         "android.frameworks.schedulerservice@1.0",
     ],
     header_libs: [
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 8c2300e..8d381b1 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,3 +1,73 @@
 subdirs = [
     "hidl"
 ]
+cc_library_shared {
+    name: "libsensorservice",
+
+    srcs: [
+        "BatteryService.cpp",
+        "CorrectedGyroSensor.cpp",
+        "Fusion.cpp",
+        "GravitySensor.cpp",
+        "LinearAccelerationSensor.cpp",
+        "OrientationSensor.cpp",
+        "RecentEventLogger.cpp",
+        "RotationVectorSensor.cpp",
+        "SensorDevice.cpp",
+        "SensorDirectConnection.cpp",
+        "SensorEventConnection.cpp",
+        "SensorFusion.cpp",
+        "SensorInterface.cpp",
+        "SensorList.cpp",
+        "SensorRecord.cpp",
+        "SensorService.cpp",
+        "SensorServiceUtils.cpp",
+    ],
+
+    cflags: [
+        "-DLOG_TAG=\"SensorService\"",
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+        "-fvisibility=hidden"
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "libhardware",
+        "libhardware_legacy",
+        "libutils",
+        "liblog",
+        "libbinder",
+        "libsensor",
+        "libcrypto",
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "android.hardware.sensors@1.0",
+    ],
+
+    static_libs: ["android.hardware.sensors@1.0-convert"],
+
+    // our public headers depend on libsensor
+    export_shared_lib_headers: ["libsensor"],
+}
+
+cc_binary {
+    name: "sensorservice",
+
+    srcs: ["main_sensorservice.cpp"],
+
+    shared_libs: [
+        "libsensorservice",
+        "libbinder",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
deleted file mode 100644
index cfb7231..0000000
--- a/services/sensorservice/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    BatteryService.cpp \
-    CorrectedGyroSensor.cpp \
-    Fusion.cpp \
-    GravitySensor.cpp \
-    LinearAccelerationSensor.cpp \
-    OrientationSensor.cpp \
-    RecentEventLogger.cpp \
-    RotationVectorSensor.cpp \
-    SensorDevice.cpp \
-    SensorDirectConnection.cpp \
-    SensorEventConnection.cpp \
-    SensorFusion.cpp \
-    SensorInterface.cpp \
-    SensorList.cpp \
-    SensorRecord.cpp \
-    SensorService.cpp \
-    SensorServiceUtils.cpp \
-
-LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-
-LOCAL_CFLAGS += -Wall -Werror -Wextra
-
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libhardware \
-    libhardware_legacy \
-    libutils \
-    liblog \
-    libbinder \
-    libsensor \
-    libcrypto \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    android.hardware.sensors@1.0
-
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.sensors@1.0-convert
-
-# our public headers depend on libsensor
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
-    libsensor \
-
-LOCAL_MODULE:= libsensorservice
-
-include $(BUILD_SHARED_LIBRARY)
-
-#####################################################################
-# build executable
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libsensorservice \
-    libbinder \
-    libutils
-
-LOCAL_CFLAGS := -Wall -Werror -Wextra
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index 870635b..538d728 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -27,12 +27,21 @@
         const String16& opPackageName)
         : mService(service), mUid(uid), mMem(*mem),
         mHalChannelHandle(halChannelHandle),
-        mOpPackageName(opPackageName) {
+        mOpPackageName(opPackageName), mDestroyed(false) {
     ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
 }
 
 SensorService::SensorDirectConnection::~SensorDirectConnection() {
     ALOGD_IF(DEBUG_CONNECTIONS, "~SensorDirectConnection %p", this);
+    destroy();
+}
+
+void SensorService::SensorDirectConnection::destroy() {
+    Mutex::Autolock _l(mDestroyLock);
+    // destroy once only
+    if (mDestroyed) {
+        return;
+    }
 
     stopAll();
     mService->cleanupConnection(this);
@@ -40,6 +49,7 @@
         native_handle_close(mMem.handle);
         native_handle_delete(const_cast<struct native_handle*>(mMem.handle));
     }
+    mDestroyed = true;
 }
 
 void SensorService::SensorDirectConnection::onFirstRef() {
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index 27458d4..5c398a8 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -47,7 +47,7 @@
     // stop all active sensor report. if backupRecord is set to false,
     // those report can be recovered by recoverAll
     // called by SensorService when enter restricted mode
-    void stopAll(bool clearRecord = false);
+    void stopAll(bool backupRecord = false);
 
     // recover sensor reports previously stopped by stopAll(true)
     // called by SensorService when return to NORMAL mode.
@@ -63,7 +63,7 @@
     virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
     virtual status_t flush();
     virtual int32_t configureChannel(int handle, int rateLevel);
-
+    virtual void destroy();
 private:
     const sp<SensorService> mService;
     const uid_t mUid;
@@ -74,6 +74,9 @@
     mutable Mutex mConnectionLock;
     std::unordered_map<int, int> mActivated;
     std::unordered_map<int, int> mActivatedBackup;
+
+    mutable Mutex mDestroyLock;
+    bool mDestroyed;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index fad046c..0a05dd1 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -32,7 +32,8 @@
         const String16& opPackageName)
     : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
       mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
-      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName) {
+      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName),
+      mDestroyed(false) {
     mChannel = new BitTube(mService->mSocketBufferSize);
 #if DEBUG_CONNECTIONS
     mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -42,10 +43,22 @@
 
 SensorService::SensorEventConnection::~SensorEventConnection() {
     ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
+    destroy();
+}
+
+void SensorService::SensorEventConnection::destroy() {
+    Mutex::Autolock _l(mDestroyLock);
+
+    // destroy once only
+    if (mDestroyed) {
+        return;
+    }
+
     mService->cleanupConnection(this);
     if (mEventCache != NULL) {
         delete mEventCache;
     }
+    mDestroyed = true;
 }
 
 void SensorService::SensorEventConnection::onFirstRef() {
@@ -477,7 +490,14 @@
     // separately before the next batch of events.
     for (int j = 0; j < numEventsDropped; ++j) {
         if (scratch[j].type == SENSOR_TYPE_META_DATA) {
-            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
+            ssize_t index = mSensorInfo.indexOfKey(scratch[j].meta_data.sensor);
+            if (index < 0) {
+                ALOGW("%s: sensor 0x%x is not found in connection",
+                      __func__, scratch[j].meta_data.sensor);
+                continue;
+            }
+
+            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
             flushInfo.mPendingFlushEventsToSend++;
             ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
                      flushInfo.mPendingFlushEventsToSend);
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index c81e015..6f282cd 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -75,6 +75,7 @@
     virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
     virtual status_t flush();
     virtual int32_t configureChannel(int handle, int rateLevel);
+    virtual void destroy();
 
     // Count the number of flush complete events which are about to be dropped in the buffer.
     // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be sent
@@ -164,6 +165,8 @@
     int mTotalAcksNeeded, mTotalAcksReceived;
 #endif
 
+    mutable Mutex mDestroyLock;
+    bool mDestroyed;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index ab08cac..aa306d8 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -124,14 +124,15 @@
     forEachSensor([&result] (const Sensor& s) -> bool {
             result.appendFormat(
                     "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
-                        ") | perm: %s\n",
+                        ") | perm: %s | flags: 0x%08x\n",
                     s.getHandle(),
                     s.getName().string(),
                     s.getVendor().string(),
                     s.getVersion(),
                     s.getStringType().string(),
                     s.getType(),
-                    s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
+                    s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a",
+                    static_cast<int>(s.getFlags()));
 
             result.append("\t");
             const int reportingMode = s.getReportingMode();
@@ -173,9 +174,14 @@
                 result.appendFormat("non-wakeUp | ");
             }
 
+            if (s.isDataInjectionSupported()) {
+                result.appendFormat("data-injection, ");
+            }
+
             if (s.isDynamicSensor()) {
                 result.appendFormat("dynamic, ");
             }
+
             if (s.hasAdditionalInfo()) {
                 result.appendFormat("has-additional-info, ");
             }
@@ -190,7 +196,6 @@
                 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
                     result.append("gralloc, ");
                 }
-                result.appendFormat("flag =0x%08x", static_cast<int>(s.getFlags()));
                 result.append("\n");
             }
             return true;
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index d60768c..dc491d9 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -394,6 +394,7 @@
             }
         } else if (!mSensors.hasAnySensor()) {
             result.append("No Sensors on the device\n");
+            result.appendFormat("devInitCheck : %d\n", SensorDevice::getInstance().initCheck());
         } else {
             // Default dump the sensor list and debugging information.
             //
@@ -932,8 +933,14 @@
     }
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
-    sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName,
-            requestedMode == DATA_INJECTION, opPackageName));
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+
+    String8 connPackageName =
+            (packageName == "") ? String8::format("unknown_package_pid_%d", pid) : packageName;
+    String16 connOpPackageName =
+            (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
+    sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
+            requestedMode == DATA_INJECTION, connOpPackageName));
     if (requestedMode == DATA_INJECTION) {
         if (mActiveConnections.indexOf(result) < 0) {
             mActiveConnections.add(result);
@@ -1032,17 +1039,16 @@
 }
 
 int SensorService::setOperationParameter(
-            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+            int32_t handle, int32_t type,
+            const Vector<float> &floats, const Vector<int32_t> &ints) {
     Mutex::Autolock _l(mLock);
 
-    // check permission
-    int32_t uid;
-    bool hasPermission = checkCallingPermission(sLocationHardwarePermission, nullptr, &uid);
-    if (!hasPermission || (uid != 1000 && uid != 0)) {
+    if (!checkCallingPermission(sLocationHardwarePermission, nullptr, nullptr)) {
         return PERMISSION_DENIED;
     }
 
     bool isFloat = true;
+    bool isCustom = false;
     size_t expectSize = INT32_MAX;
     switch (type) {
         case AINFO_LOCAL_GEOMAGNETIC_FIELD:
@@ -1060,7 +1066,21 @@
             expectSize = 1;
             break;
         default:
-            return BAD_VALUE;
+            // CUSTOM events must only contain float data; it may have variable size
+            if (type < AINFO_CUSTOM_START || type >= AINFO_DEBUGGING_START ||
+                    ints.size() ||
+                    sizeof(additional_info_event_t::data_float)/sizeof(float) < floats.size() ||
+                    handle < 0) {
+                return BAD_VALUE;
+            }
+            isFloat = true;
+            isCustom = true;
+            expectSize = floats.size();
+            break;
+    }
+
+    if (!isCustom && handle != -1) {
+        return BAD_VALUE;
     }
 
     // three events: first one is begin tag, last one is end tag, the one in the middle
@@ -1070,7 +1090,7 @@
     for (sensors_event_t* i = event; i < event + 3; i++) {
         *i = (sensors_event_t) {
             .version = sizeof(sensors_event_t),
-            .sensor = SENSORS_HANDLE_BASE - 1, // sensor that never exists
+            .sensor = handle,
             .type = SENSOR_TYPE_ADDITIONAL_INFO,
             .timestamp = timestamp++,
             .additional_info = (additional_info_event_t) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 2a9d6e8..3e18394 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -159,7 +159,7 @@
     virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
             uint32_t size, int32_t type, int32_t format, const native_handle *resource);
     virtual int setOperationParameter(
-            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
+            int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);
     virtual status_t dump(int fd, const Vector<String16>& args);
 
     String8 getSensorName(int handle) const;
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index 748dafc..02c13fa 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -14,11 +14,11 @@
         "libbase",
         "libhidlbase",
         "libhidltransport",
+        "libhwbinder",
         "libutils",
         "libsensor",
         "android.frameworks.sensorservice@1.0",
         "android.hardware.sensors@1.0",
-        "android.hidl.base@1.0",
     ],
     static_libs: [
         "android.hardware.sensors@1.0-convert",
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 25a3dc5..fee6da1 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -24,12 +24,14 @@
 
 #include <sched.h>
 
-#include <thread>
 
 #include "EventQueue.h"
 #include "DirectReportChannel.h"
 #include "utils.h"
 
+#include <hwbinder/IPCThreadState.h>
+#include <utils/String8.h>
+
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -40,20 +42,24 @@
 using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Void;
-using ::android::sp;
 
 static const char* POLL_THREAD_NAME = "hidl_ssvc_poll";
 
 SensorManager::SensorManager(JavaVM* vm)
-        : mJavaVm(vm) {
+        : mLooper(new Looper(false /*allowNonCallbacks*/)), mStopThread(true), mJavaVm(vm) {
 }
 
 SensorManager::~SensorManager() {
     // Stops pollAll inside the thread.
-    std::unique_lock<std::mutex> lock(mLooperMutex);
+    std::lock_guard<std::mutex> lock(mThreadMutex);
+
+    mStopThread = true;
     if (mLooper != nullptr) {
         mLooper->wake();
     }
+    if (mPollThread.joinable()) {
+        mPollThread.join();
+    }
 }
 
 // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
@@ -128,12 +134,13 @@
 }
 
 /* One global looper for all event queues created from this SensorManager. */
-sp<::android::Looper> SensorManager::getLooper() {
-    std::unique_lock<std::mutex> lock(mLooperMutex);
-    if (mLooper == nullptr) {
-        std::condition_variable looperSet;
+sp<Looper> SensorManager::getLooper() {
+    std::lock_guard<std::mutex> lock(mThreadMutex);
 
-        std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet, javaVm = mJavaVm] {
+    if (!mPollThread.joinable()) {
+        // if thread not initialized, start thread
+        mStopThread = false;
+        std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {
 
             struct sched_param p = {0};
             p.sched_priority = 10;
@@ -142,16 +149,11 @@
                         << strerror(errno);
             }
 
-            std::unique_lock<std::mutex> lock(mutex);
-            if (looper != nullptr) {
-                LOG(INFO) << "Another thread has already set the looper, exiting this one.";
-                return;
-            }
-            looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
-            lock.unlock();
+            // set looper
+            Looper::setForThread(looper);
 
-            // Attach the thread to JavaVM so that pollAll do not crash if the event
-            // is from Java.
+            // Attach the thread to JavaVM so that pollAll do not crash if the thread
+            // eventually calls into Java.
             JavaVMAttachArgs args{
                 .version = JNI_VERSION_1_2,
                 .name = POLL_THREAD_NAME,
@@ -162,19 +164,30 @@
                 LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
             }
 
-            looperSet.notify_one();
-            int pollResult = looper->pollAll(-1 /* timeout */);
-            if (pollResult != ALOOPER_POLL_WAKE) {
-                LOG(ERROR) << "Looper::pollAll returns unexpected " << pollResult;
+            LOG(INFO) << POLL_THREAD_NAME << " started.";
+            for (;;) {
+                int pollResult = looper->pollAll(-1 /* timeout */);
+                if (pollResult == Looper::POLL_WAKE) {
+                    if (stopThread == true) {
+                        LOG(INFO) << POLL_THREAD_NAME << ": requested to stop";
+                        break;
+                    } else {
+                        LOG(INFO) << POLL_THREAD_NAME << ": spurious wake up, back to work";
+                    }
+                } else {
+                    LOG(ERROR) << POLL_THREAD_NAME << ": Looper::pollAll returns unexpected "
+                               << pollResult;
+                    break;
+                }
             }
 
             if (javaVm->DetachCurrentThread() != JNI_OK) {
                 LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
             }
 
-            LOG(INFO) << "Looper thread is terminated.";
-        }}.detach();
-        looperSet.wait(lock, [this]{ return this->mLooper != nullptr; });
+            LOG(INFO) << POLL_THREAD_NAME << " is terminated.";
+        }};
+        mPollThread = std::move(pollThread);
     }
     return mLooper;
 }
@@ -196,7 +209,15 @@
     }
 
     sp<::android::Looper> looper = getLooper();
-    sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue();
+    if (looper == nullptr) {
+        LOG(ERROR) << "::android::SensorManager::createEventQueue cannot initialize looper";
+        _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
+        return Void();
+    }
+
+    String8 package(String8::format("hidl_client_pid_%d",
+                                    android::hardware::IPCThreadState::self()->getCallingPid()));
+    sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue(package);
     if (internalQueue == nullptr) {
         LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
         _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index e66c8e5..ddcee28 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -20,6 +20,7 @@
 #include <jni.h>
 
 #include <mutex>
+#include <thread>
 
 #include <android/frameworks/sensorservice/1.0/ISensorManager.h>
 #include <android/frameworks/sensorservice/1.0/types.h>
@@ -38,6 +39,7 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_memory;
 using ::android::hardware::Return;
+using ::android::sp;
 
 struct SensorManager final : public ISensorManager {
 
@@ -54,13 +56,15 @@
 private:
     // Block until ::android::SensorManager is initialized.
     ::android::SensorManager& getInternalManager();
-    sp<::android::Looper> getLooper();
+    sp<Looper> getLooper();
 
     std::mutex mInternalManagerMutex;
     ::android::SensorManager* mInternalManager = nullptr; // does not own
+    sp<Looper> mLooper;
 
-    std::mutex mLooperMutex;
-    sp<::android::Looper> mLooper;
+    volatile bool mStopThread;
+    std::mutex mThreadMutex; //protects mPollThread
+    std::thread mPollThread;
 
     JavaVM* mJavaVm;
 };
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 95a522d..38529b6 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -9,7 +9,7 @@
     DisplayDevice.cpp \
     DispSync.cpp \
     EventControlThread.cpp \
-    StartBootAnimThread.cpp \
+    StartPropertySetThread.cpp \
     EventThread.cpp \
     FrameTracker.cpp \
     GpuService.cpp \
@@ -104,7 +104,7 @@
     libhidltransport \
     libhwbinder
 
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index bd9b8aa..bef12ea 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -30,7 +30,7 @@
 #include <utils/Trace.h>
 #include <utils/Vector.h>
 
-#include <ui/Fence.h>
+#include <ui/FenceTime.h>
 
 #include "DispSync.h"
 #include "SurfaceFlinger.h"
@@ -377,11 +377,16 @@
 DispSync::DispSync(const char* name) :
         mName(name),
         mRefreshSkipCount(0),
-        mThread(new DispSyncThread(name)),
-        mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){
+        mThread(new DispSyncThread(name)) {
+}
 
-    mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset;
+DispSync::~DispSync() {}
+
+void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
+    mIgnorePresentFences = !hasSyncFramework;
+    mPresentTimeOffset = dispSyncPresentTimeOffset;
     mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
+
     // set DispSync to SCHED_FIFO to minimize jitter
     struct sched_param param = {0};
     param.sched_priority = 2;
@@ -389,7 +394,6 @@
         ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
     }
 
-
     reset();
     beginResync();
 
@@ -405,8 +409,6 @@
     }
 }
 
-DispSync::~DispSync() {}
-
 void DispSync::reset() {
     Mutex::Autolock lock(mMutex);
 
@@ -419,25 +421,13 @@
     resetErrorLocked();
 }
 
-bool DispSync::addPresentFence(const sp<Fence>& fence) {
+bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
     Mutex::Autolock lock(mMutex);
 
-    mPresentFences[mPresentSampleOffset] = fence;
-    mPresentTimes[mPresentSampleOffset] = 0;
+    mPresentFences[mPresentSampleOffset] = fenceTime;
     mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES;
     mNumResyncSamplesSincePresent = 0;
 
-    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
-        const sp<Fence>& f(mPresentFences[i]);
-        if (f != NULL) {
-            nsecs_t t = f->getSignalTime();
-            if (t < INT64_MAX) {
-                mPresentFences[i].clear();
-                mPresentTimes[i] = t + mPresentTimeOffset;
-            }
-        }
-    }
-
     updateErrorLocked();
 
     return !mModelUpdated || mError > kErrorThreshold;
@@ -602,21 +592,39 @@
     nsecs_t sqErrSum = 0;
 
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
-        nsecs_t sample = mPresentTimes[i] - mReferenceTime;
-        if (sample > mPhase) {
-            nsecs_t sampleErr = (sample - mPhase) % period;
-            if (sampleErr > period / 2) {
-                sampleErr -= period;
-            }
-            sqErrSum += sampleErr * sampleErr;
-            numErrSamples++;
+        // Only check for the cached value of signal time to avoid unecessary
+        // syscalls. It is the responsibility of the DispSync owner to
+        // call getSignalTime() periodically so the cache is updated when the
+        // fence signals.
+        nsecs_t time = mPresentFences[i]->getCachedSignalTime();
+        if (time == Fence::SIGNAL_TIME_PENDING ||
+                time == Fence::SIGNAL_TIME_INVALID) {
+            continue;
         }
+
+        nsecs_t sample = time - mReferenceTime;
+        if (sample <= mPhase) {
+            continue;
+        }
+
+        nsecs_t sampleErr = (sample - mPhase) % period;
+        if (sampleErr > period / 2) {
+            sampleErr -= period;
+        }
+        sqErrSum += sampleErr * sampleErr;
+        numErrSamples++;
     }
 
     if (numErrSamples > 0) {
         mError = sqErrSum / numErrSamples;
+        mZeroErrSamplesCount = 0;
     } else {
         mError = 0;
+        // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam.
+        mZeroErrSamplesCount++;
+        ALOGE_IF(
+                (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
+                "No present times for model error.");
     }
 
     if (kTraceDetailedInfo) {
@@ -627,9 +635,9 @@
 void DispSync::resetErrorLocked() {
     mPresentSampleOffset = 0;
     mError = 0;
+    mZeroErrSamplesCount = 0;
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
-        mPresentFences[i].clear();
-        mPresentTimes[i] = 0;
+        mPresentFences[i] = FenceTime::NO_FENCE;
     }
 }
 
@@ -668,19 +676,19 @@
         previous = sampleTime;
     }
 
-    result.appendFormat("mPresentFences / mPresentTimes [%d]:\n",
+    result.appendFormat("mPresentFences [%d]:\n",
             NUM_PRESENT_SAMPLES);
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    previous = 0;
+    previous = Fence::SIGNAL_TIME_INVALID;
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
         size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
-        bool signaled = mPresentFences[idx] == NULL;
-        nsecs_t presentTime = mPresentTimes[idx];
-        if (!signaled) {
+        nsecs_t presentTime = mPresentFences[idx]->getSignalTime();
+        if (presentTime == Fence::SIGNAL_TIME_PENDING) {
             result.appendFormat("  [unsignaled fence]\n");
-        } else if (presentTime == 0) {
-            result.appendFormat("  0\n");
-        } else if (previous == 0) {
+        } else if(presentTime == Fence::SIGNAL_TIME_INVALID) {
+            result.appendFormat("  [invalid fence]\n");
+        } else if (previous == Fence::SIGNAL_TIME_PENDING ||
+                previous == Fence::SIGNAL_TIME_INVALID) {
             result.appendFormat("  %" PRId64 "  (%.3f ms ago)\n", presentTime,
                     (now - presentTime) / 1000000.0);
         } else {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 82ae795..880a24d 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -23,10 +23,14 @@
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
 
+#include <ui/FenceTime.h>
+
+#include <memory>
+
 namespace android {
 
 class String8;
-class Fence;
+class FenceTime;
 class DispSyncThread;
 
 // DispSync maintains a model of the periodic hardware-based vsync events of a
@@ -55,6 +59,8 @@
     explicit DispSync(const char* name);
     ~DispSync();
 
+    void init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset);
+
     // reset clears the resync samples and error value.
     void reset();
 
@@ -67,7 +73,7 @@
     //
     // This method should be called with the retire fence from each HWComposer
     // set call that affects the display.
-    bool addPresentFence(const sp<Fence>& fence);
+    bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
 
     // The beginResync, addResyncSample, and endResync methods are used to re-
     // synchronize the DispSync's model to the hardware vsync events.  The re-
@@ -129,6 +135,7 @@
     enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
     enum { NUM_PRESENT_SAMPLES = 8 };
     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+    enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 };
 
     const char* const mName;
 
@@ -146,9 +153,14 @@
 
     // mError is the computed model error.  It is based on the difference
     // between the estimated vsync event times and those observed in the
-    // mPresentTimes array.
+    // mPresentFences array.
     nsecs_t mError;
 
+    // mZeroErrSamplesCount keeps track of how many times in a row there were
+    // zero timestamps available in the mPresentFences array.
+    // Used to sanity check that we are able to calculate the model error.
+    size_t mZeroErrSamplesCount;
+
     // Whether we have updated the vsync event model since the last resync.
     bool mModelUpdated;
 
@@ -162,8 +174,8 @@
 
     // These member variables store information about the present fences used
     // to validate the currently computed model.
-    sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES];
-    nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES];
+    std::shared_ptr<FenceTime>
+            mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE};
     size_t mPresentSampleOffset;
 
     int mRefreshSkipCount;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b5ffc60..b28c9ba 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -121,7 +121,7 @@
     ANativeWindow* const window = mNativeWindow.get();
 
 #ifdef USE_HWC2
-    mActiveColorMode = static_cast<android_color_mode_t>(-1);
+    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
     mDisplayHasWideColor = supportWideColor;
 #else
     (void) supportWideColor;
@@ -134,9 +134,11 @@
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     if (config == EGL_NO_CONFIG) {
 #ifdef USE_HWC2
-        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
+                                               /*logConfig*/ false);
 #else
-        config = RenderEngine::chooseEglConfig(display, format);
+        config = RenderEngine::chooseEglConfig(display, format,
+                                               /*logConfig*/ false);
 #endif
     }
     eglSurface = eglCreateWindowSurface(display, config, window, NULL);
@@ -442,6 +444,11 @@
 android_color_mode_t DisplayDevice::getActiveColorMode() const {
     return mActiveColorMode;
 }
+
+void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) {
+    ANativeWindow* const window = mNativeWindow.get();
+    native_window_set_buffers_data_space(window, dataspace);
+}
 #endif
 
 // ----------------------------------------------------------------------------
@@ -610,23 +617,25 @@
 
 void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
-    result.appendFormat(
-        "+ DisplayDevice: %s\n"
-        "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
-        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
-        "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
-        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
-        mDisplayName.string(), mType, mHwcDisplayId,
-        mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
-        mOrientation, tr.getType(), getPageFlipCount(),
-        mIsSecure, mPowerMode, mActiveConfig,
-        mVisibleLayersSortedByZ.size(),
-        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
-        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
-        mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
-        tr[0][0], tr[1][0], tr[2][0],
-        tr[0][1], tr[1][1], tr[2][1],
-        tr[0][2], tr[1][2], tr[2][2]);
+    EGLint redSize, greenSize, blueSize, alphaSize;
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &blueSize);
+    eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &alphaSize);
+    result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
+    result.appendFormat("   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
+                        "(%d:%d:%d:%d), orient=%2d (type=%08x), "
+                        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+                        mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight,
+                        mNativeWindow.get(), redSize, greenSize, blueSize, alphaSize, mOrientation,
+                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mVisibleLayersSortedByZ.size());
+    result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
+                        "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
+                        mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
+                        mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
+                        mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
+                        tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e2852a7..8636e2a 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -141,6 +141,7 @@
 
     uint32_t                getLayerStack() const { return mLayerStack; }
     int32_t                 getDisplayType() const { return mType; }
+    bool                    isPrimary() const { return mType == DISPLAY_PRIMARY; }
     int32_t                 getHwcDisplayId() const { return mHwcDisplayId; }
     const wp<IBinder>&      getDisplayToken() const { return mDisplayToken; }
 
@@ -189,6 +190,7 @@
 #ifdef USE_HWC2
     android_color_mode_t getActiveColorMode() const;
     void setActiveColorMode(android_color_mode_t mode);
+    void setCompositionDataSpace(android_dataspace dataspace);
 #endif
 
     /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 9d16044..cf01ad0 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -181,6 +181,13 @@
     if (mClient == nullptr) {
         LOG_ALWAYS_FATAL("failed to create composer client");
     }
+
+    if (mIsUsingVrComposer) {
+        sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);
+        if (vrClient == nullptr) {
+            LOG_ALWAYS_FATAL("failed to create vr composer client");
+        }
+    }
 }
 
 std::vector<IComposer::Capability> Composer::getCapabilities()
@@ -212,6 +219,10 @@
     }
 }
 
+bool Composer::isRemote() {
+    return mClient->isRemote();
+}
+
 void Composer::resetCommands() {
     mWriter.reset();
 }
@@ -744,7 +755,7 @@
     }
 
     Error error = kDefaultError;
-    mClient->executeCommands(commandLength, commandHandles,
+    auto ret = mClient->executeCommands(commandLength, commandHandles,
             [&](const auto& tmpError, const auto& tmpOutChanged,
                 const auto& tmpOutLength, const auto& tmpOutHandles)
             {
@@ -777,6 +788,11 @@
                     error = Error::NO_RESOURCES;
                 }
             });
+    // executeCommands can fail because of out-of-fd and we do not want to
+    // abort() in that case
+    if (!ret.isOk()) {
+        ALOGE("executeCommands failed because of %s", ret.description().c_str());
+    }
 
     if (error == Error::NONE) {
         std::vector<CommandReader::CommandError> commandErrors =
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 96dd833..533509b 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -143,6 +143,11 @@
 
     void registerCallback(const sp<IComposerCallback>& callback);
 
+    // Returns true if the connected composer service is running in a remote
+    // process, false otherwise. This will return false if the service is
+    // configured in passthrough mode, for example.
+    bool isRemote();
+
     // Reset all pending commands in the command buffer. Useful if you want to
     // skip a frame but have already queued some commands.
     void resetCommands();
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 5b869e1..1ac21c6 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -106,12 +106,6 @@
     if (result != NO_ERROR) {
         ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
                 strerror(-result), result);
-        return result;
-    }
-    result = mHwc.setClientTarget(mDisplayType, slot,
-            acquireFence, buf, dataspace);
-    if (result != NO_ERROR) {
-        ALOGE("error posting framebuffer: %d", result);
     }
     return result;
 #else
@@ -179,9 +173,16 @@
     mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
             &outSlot, &outBuffer);
     outDataspace = item.mDataSpace;
+    status_t result =
+            mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error posting framebuffer: %d", result);
+        return result;
+    }
 #else
     outBuffer = mCurrentBuffer;
 #endif
+
     return NO_ERROR;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index c48a28f..ae44ae0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -33,45 +33,6 @@
 #include <algorithm>
 #include <inttypes.h>
 
-extern "C" {
-    static void hotplug_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId, int32_t intConnected) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            auto connected = static_cast<HWC2::Connection>(intConnected);
-            device->callHotplug(std::move(display), connected);
-        } else {
-            ALOGE("Hotplug callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-
-    static void refresh_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            device->callRefresh(std::move(display));
-        } else {
-            ALOGE("Refresh callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-
-    static void vsync_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId, int64_t timestamp) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            device->callVsync(std::move(display), timestamp);
-        } else {
-            ALOGE("Vsync callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-}
-
 using android::Fence;
 using android::FloatRect;
 using android::GraphicBuffer;
@@ -86,51 +47,78 @@
 
 namespace Hwc2 = android::Hwc2;
 
+namespace {
+
+class ComposerCallbackBridge : public Hwc2::IComposerCallback {
+public:
+    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
+            : mCallback(callback), mSequenceId(sequenceId),
+              mHasPrimaryDisplay(false) {}
+
+    Return<void> onHotplug(Hwc2::Display display,
+                           IComposerCallback::Connection conn) override
+    {
+        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
+        if (!mHasPrimaryDisplay) {
+            LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
+                    "Initial onHotplug callback should be "
+                    "primary display connected");
+            mHasPrimaryDisplay = true;
+            mCallback->onHotplugReceived(mSequenceId, display,
+                                         connection, true);
+        } else {
+            mCallback->onHotplugReceived(mSequenceId, display,
+                                         connection, false);
+        }
+        return Void();
+    }
+
+    Return<void> onRefresh(Hwc2::Display display) override
+    {
+        mCallback->onRefreshReceived(mSequenceId, display);
+        return Void();
+    }
+
+    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
+    {
+        mCallback->onVsyncReceived(mSequenceId, display, timestamp);
+        return Void();
+    }
+
+    bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }
+
+private:
+    ComposerCallback* mCallback;
+    int32_t mSequenceId;
+    bool mHasPrimaryDisplay;
+};
+
+} // namespace anonymous
+
+
 // Device methods
 
 Device::Device(bool useVrComposer)
   : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
     mCapabilities(),
     mDisplays(),
-    mHotplug(),
-    mPendingHotplugs(),
-    mRefresh(),
-    mPendingRefreshes(),
-    mVsync(),
-    mPendingVsyncs()
+    mRegisteredCallback(false)
 {
     loadCapabilities();
-    registerCallbacks();
 }
 
-Device::~Device()
-{
-    for (auto element : mDisplays) {
-        auto display = element.second.lock();
-        if (!display) {
-            ALOGE("~Device: Found a display (%" PRId64 " that has already been"
-                    " destroyed", element.first);
-            continue;
-        }
-
-        DisplayType displayType = HWC2::DisplayType::Invalid;
-        auto error = display->getType(&displayType);
-        if (error != Error::None) {
-            ALOGE("~Device: Failed to determine type of display %" PRIu64
-                    ": %s (%d)", display->getId(), to_string(error).c_str(),
-                    static_cast<int32_t>(error));
-            continue;
-        }
-
-        if (displayType == HWC2::DisplayType::Physical) {
-            error = display->setVsyncEnabled(HWC2::Vsync::Disable);
-            if (error != Error::None) {
-                ALOGE("~Device: Failed to disable vsync for display %" PRIu64
-                        ": %s (%d)", display->getId(), to_string(error).c_str(),
-                        static_cast<int32_t>(error));
-            }
-        }
+void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
+    if (mRegisteredCallback) {
+        ALOGW("Callback already registered. Ignored extra registration "
+                "attempt.");
+        return;
     }
+    mRegisteredCallback = true;
+    sp<ComposerCallbackBridge> callbackBridge(
+            new ComposerCallbackBridge(callback, sequenceId));
+    mComposer->registerCallback(callbackBridge);
+    LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
+            "Registered composer callback but didn't get primary display");
 }
 
 // Required by HWC2 device
@@ -146,7 +134,7 @@
 }
 
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
-        android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
+        android_pixel_format_t* format, Display** outDisplay)
 {
     ALOGI("Creating virtual display");
 
@@ -159,104 +147,66 @@
         return error;
     }
 
-    ALOGI("Created virtual display");
+    auto display = std::make_unique<Display>(
+            *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+    *outDisplay = display.get();
     *format = static_cast<android_pixel_format_t>(intFormat);
-    *outDisplay = getDisplayById(displayId);
-    if (!*outDisplay) {
-        ALOGE("Failed to get display by id");
-        return Error::BadDisplay;
-    }
-    (*outDisplay)->setConnected(true);
+    mDisplays.emplace(displayId, std::move(display));
+    ALOGI("Created virtual display");
     return Error::None;
 }
 
-void Device::registerHotplugCallback(HotplugCallback hotplug)
+void Device::destroyDisplay(hwc2_display_t displayId)
 {
-    ALOGV("registerHotplugCallback");
-    mHotplug = hotplug;
-    for (auto& pending : mPendingHotplugs) {
-        auto& display = pending.first;
-        auto connected = pending.second;
-        ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
-                to_string(connected).c_str());
-        mHotplug(std::move(display), connected);
-    }
+    ALOGI("Destroying display %" PRIu64, displayId);
+    mDisplays.erase(displayId);
 }
 
-void Device::registerRefreshCallback(RefreshCallback refresh)
-{
-    mRefresh = refresh;
-    for (auto& pending : mPendingRefreshes) {
-        mRefresh(std::move(pending));
-    }
-}
+void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
+    if (connection == Connection::Connected) {
+        auto display = getDisplayById(displayId);
+        if (display) {
+            if (display->isConnected()) {
+                ALOGW("Attempt to hotplug connect display %" PRIu64
+                        " , which is already connected.", displayId);
+            } else {
+                display->setConnected(true);
+            }
+        } else {
+            DisplayType displayType;
+            auto intError = mComposer->getDisplayType(displayId,
+                    reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+                            &displayType));
+            auto error = static_cast<Error>(intError);
+            if (error != Error::None) {
+                ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+                        "Aborting hotplug attempt.",
+                        displayId, to_string(error).c_str(), intError);
+                return;
+            }
 
-void Device::registerVsyncCallback(VsyncCallback vsync)
-{
-    mVsync = vsync;
-    for (auto& pending : mPendingVsyncs) {
-        auto& display = pending.first;
-        auto timestamp = pending.second;
-        mVsync(std::move(display), timestamp);
-    }
-}
-
-// For use by Device callbacks
-
-void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
-{
-    if (connected == Connection::Connected) {
-        if (!display->isConnected()) {
-            mComposer->setClientTargetSlotCount(display->getId());
-            display->loadConfigs();
-            display->setConnected(true);
+            auto newDisplay = std::make_unique<Display>(
+                    *mComposer.get(), mCapabilities, displayId, displayType);
+            mDisplays.emplace(displayId, std::move(newDisplay));
         }
-    } else {
-        display->setConnected(false);
-        mDisplays.erase(display->getId());
-    }
-
-    if (mHotplug) {
-        mHotplug(std::move(display), connected);
-    } else {
-        ALOGV("callHotplug called, but no valid callback registered, storing");
-        mPendingHotplugs.emplace_back(std::move(display), connected);
-    }
-}
-
-void Device::callRefresh(std::shared_ptr<Display> display)
-{
-    if (mRefresh) {
-        mRefresh(std::move(display));
-    } else {
-        ALOGV("callRefresh called, but no valid callback registered, storing");
-        mPendingRefreshes.emplace_back(std::move(display));
-    }
-}
-
-void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
-{
-    if (mVsync) {
-        mVsync(std::move(display), timestamp);
-    } else {
-        ALOGV("callVsync called, but no valid callback registered, storing");
-        mPendingVsyncs.emplace_back(std::move(display), timestamp);
+    } else if (connection == Connection::Disconnected) {
+        // The display will later be destroyed by a call to
+        // destroyDisplay(). For now we just mark it disconnected.
+        auto display = getDisplayById(displayId);
+        if (display) {
+            display->setConnected(false);
+        } else {
+            ALOGW("Attempted to disconnect unknown display %" PRIu64,
+                  displayId);
+        }
     }
 }
 
 // Other Device methods
 
-std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
-    if (mDisplays.count(id) != 0) {
-        auto strongDisplay = mDisplays[id].lock();
-        ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
-                " longer alive", id);
-        return strongDisplay;
-    }
-
-    auto display = std::make_shared<Display>(*this, id);
-    mDisplays.emplace(id, display);
-    return display;
+Display* Device::getDisplayById(hwc2_display_t id) {
+    auto iter = mDisplays.find(id);
+    return iter == mDisplays.end() ? nullptr : iter->second.get();
 }
 
 // Device initialization methods
@@ -271,84 +221,37 @@
     }
 }
 
-bool Device::hasCapability(HWC2::Capability capability) const
-{
-    return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
-            capability) != mCapabilities.cend();
-}
-
-namespace {
-class ComposerCallback : public Hwc2::IComposerCallback {
-public:
-    ComposerCallback(Device* device) : mDevice(device) {}
-
-    Return<void> onHotplug(Hwc2::Display display,
-            Connection connected) override
-    {
-        hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
-        return Void();
-    }
-
-    Return<void> onRefresh(Hwc2::Display display) override
-    {
-        refresh_hook(mDevice, display);
-        return Void();
-    }
-
-    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
-    {
-        vsync_hook(mDevice, display, timestamp);
-        return Void();
-    }
-
-private:
-    Device* mDevice;
-};
-} // namespace anonymous
-
-void Device::registerCallbacks()
-{
-    sp<ComposerCallback> callback = new ComposerCallback(this);
-    mComposer->registerCallback(callback);
-}
-
-
-// For use by Display
-
-void Device::destroyVirtualDisplay(hwc2_display_t display)
-{
-    ALOGI("Destroying virtual display");
-    auto intError = mComposer->destroyVirtualDisplay(display);
-    auto error = static_cast<Error>(intError);
-    ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
-            " %s (%d)", display, to_string(error).c_str(), intError);
-    mDisplays.erase(display);
-}
-
 // Display methods
 
-Display::Display(Device& device, hwc2_display_t id)
-  : mDevice(device),
+Display::Display(android::Hwc2::Composer& composer,
+                 const std::unordered_set<Capability>& capabilities,
+                 hwc2_display_t id, DisplayType type)
+  : mComposer(composer),
+    mCapabilities(capabilities),
     mId(id),
     mIsConnected(false),
-    mType(DisplayType::Invalid)
+    mType(type)
 {
     ALOGV("Created display %" PRIu64, id);
-
-    auto intError = mDevice.mComposer->getDisplayType(mId,
-            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
-              id, to_string(error).c_str(), intError);
-    }
+    setConnected(true);
 }
 
-Display::~Display()
-{
-    ALOGV("Destroyed display %" PRIu64, mId);
+Display::~Display() {
+    mLayers.clear();
+
     if (mType == DisplayType::Virtual) {
-        mDevice.destroyVirtualDisplay(mId);
+        ALOGV("Destroying virtual display");
+        auto intError = mComposer.destroyVirtualDisplay(mId);
+        auto error = static_cast<Error>(intError);
+        ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64
+                ") failed: %s (%d)", mId, to_string(error).c_str(), intError);
+    } else if (mType == DisplayType::Physical) {
+        auto error = setVsyncEnabled(HWC2::Vsync::Disable);
+        if (error != Error::None) {
+            ALOGE("~Display: Failed to disable vsync for display %" PRIu64
+                    ": %s (%d)", mId, to_string(error).c_str(),
+                    static_cast<int32_t>(error));
+        }
     }
 }
 
@@ -383,22 +286,35 @@
 
 Error Display::acceptChanges()
 {
-    auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
+    auto intError = mComposer.acceptDisplayChanges(mId);
     return static_cast<Error>(intError);
 }
 
-Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
+Error Display::createLayer(Layer** outLayer)
 {
+    if (!outLayer) {
+        return Error::BadParameter;
+    }
     hwc2_layer_t layerId = 0;
-    auto intError = mDevice.mComposer->createLayer(mId, &layerId);
+    auto intError = mComposer.createLayer(mId, &layerId);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
     }
 
-    auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
-    mLayers.emplace(layerId, layer);
-    *outLayer = std::move(layer);
+    auto layer = std::make_unique<Layer>(
+            mComposer, mCapabilities, mId, layerId);
+    *outLayer = layer.get();
+    mLayers.emplace(layerId, std::move(layer));
+    return Error::None;
+}
+
+Error Display::destroyLayer(Layer* layer)
+{
+    if (!layer) {
+        return Error::BadParameter;
+    }
+    mLayers.erase(layer->getId());
     return Error::None;
 }
 
@@ -407,7 +323,7 @@
 {
     ALOGV("[%" PRIu64 "] getActiveConfig", mId);
     hwc2_config_t configId = 0;
-    auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
+    auto intError = mComposer.getActiveConfig(mId, &configId);
     auto error = static_cast<Error>(intError);
 
     if (error != Error::None) {
@@ -430,12 +346,12 @@
 }
 
 Error Display::getChangedCompositionTypes(
-        std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
+        std::unordered_map<Layer*, Composition>* outTypes)
 {
     std::vector<Hwc2::Layer> layerIds;
     std::vector<Hwc2::IComposerClient::Composition> types;
-    auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
-            &layerIds, &types);
+    auto intError = mComposer.getChangedCompositionTypes(
+            mId, &layerIds, &types);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
     error = static_cast<Error>(intError);
@@ -464,7 +380,7 @@
 Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
     std::vector<Hwc2::ColorMode> modes;
-    auto intError = mDevice.mComposer->getColorModes(mId, &modes);
+    auto intError = mComposer.getColorModes(mId, &modes);
     uint32_t numModes = modes.size();
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -489,19 +405,18 @@
 
 Error Display::getName(std::string* outName) const
 {
-    auto intError = mDevice.mComposer->getDisplayName(mId, outName);
+    auto intError = mComposer.getDisplayName(mId, outName);
     return static_cast<Error>(intError);
 }
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
-        std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
-                outLayerRequests)
+        std::unordered_map<Layer*, LayerRequest>* outLayerRequests)
 {
     uint32_t intDisplayRequests;
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
-    auto intError = mDevice.mComposer->getDisplayRequests(mId,
-            &intDisplayRequests, &layerIds, &layerRequests);
+    auto intError = mComposer.getDisplayRequests(
+            mId, &intDisplayRequests, &layerIds, &layerRequests);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -535,7 +450,7 @@
 Error Display::supportsDoze(bool* outSupport) const
 {
     bool intSupport = false;
-    auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
+    auto intError = mComposer.getDozeSupport(mId, &intSupport);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -552,7 +467,7 @@
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
     std::vector<Hwc2::Hdr> intTypes;
-    auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
+    auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
     auto error = static_cast<HWC2::Error>(intError);
 
@@ -571,25 +486,24 @@
 }
 
 Error Display::getReleaseFences(
-        std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
+        std::unordered_map<Layer*, sp<Fence>>* outFences) const
 {
     std::vector<Hwc2::Layer> layerIds;
     std::vector<int> fenceFds;
-    auto intError = mDevice.mComposer->getReleaseFences(mId,
-            &layerIds, &fenceFds);
+    auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
     auto error = static_cast<Error>(intError);
     uint32_t numElements = layerIds.size();
     if (error != Error::None) {
         return error;
     }
 
-    std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
+    std::unordered_map<Layer*, sp<Fence>> releaseFences;
     releaseFences.reserve(numElements);
     for (uint32_t element = 0; element < numElements; ++element) {
         auto layer = getLayerById(layerIds[element]);
         if (layer) {
             sp<Fence> fence(new Fence(fenceFds[element]));
-            releaseFences.emplace(std::move(layer), fence);
+            releaseFences.emplace(layer, fence);
         } else {
             ALOGE("getReleaseFences: invalid layer %" PRIu64
                     " found on display %" PRIu64, layerIds[element], mId);
@@ -607,7 +521,7 @@
 Error Display::present(sp<Fence>* outPresentFence)
 {
     int32_t presentFenceFd = -1;
-    auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
+    auto intError = mComposer.presentDisplay(mId, &presentFenceFd);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -625,7 +539,7 @@
                 config->getDisplayId(), mId);
         return Error::BadConfig;
     }
-    auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
+    auto intError = mComposer.setActiveConfig(mId, config->getId());
     return static_cast<Error>(intError);
 }
 
@@ -634,7 +548,7 @@
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
-    auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
+    auto intError = mComposer.setClientTarget(mId, slot, target,
             fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
             std::vector<Hwc2::IComposerClient::Rect>());
     return static_cast<Error>(intError);
@@ -642,15 +556,15 @@
 
 Error Display::setColorMode(android_color_mode_t mode)
 {
-    auto intError = mDevice.mComposer->setColorMode(mId,
-            static_cast<Hwc2::ColorMode>(mode));
+    auto intError = mComposer.setColorMode(
+            mId, static_cast<Hwc2::ColorMode>(mode));
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorTransform(const android::mat4& matrix,
         android_color_transform_t hint)
 {
-    auto intError = mDevice.mComposer->setColorTransform(mId,
+    auto intError = mComposer.setColorTransform(mId,
             matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
     return static_cast<Error>(intError);
 }
@@ -660,7 +574,7 @@
 {
     int32_t fenceFd = releaseFence->dup();
     auto handle = buffer->getNativeBuffer()->handle;
-    auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
+    auto intError = mComposer.setOutputBuffer(mId, handle, fenceFd);
     close(fenceFd);
     return static_cast<Error>(intError);
 }
@@ -668,14 +582,14 @@
 Error Display::setPowerMode(PowerMode mode)
 {
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
-    auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
+    auto intError = mComposer.setPowerMode(mId, intMode);
     return static_cast<Error>(intError);
 }
 
 Error Display::setVsyncEnabled(Vsync enabled)
 {
     auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
-    auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
+    auto intError = mComposer.setVsyncEnabled(mId, intEnabled);
     return static_cast<Error>(intError);
 }
 
@@ -683,8 +597,7 @@
 {
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
-    auto intError = mDevice.mComposer->validateDisplay(mId,
-            &numTypes, &numRequests);
+    auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -701,7 +614,8 @@
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
     int32_t presentFenceFd = -1;
-    auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+    auto intError = mComposer.presentOrValidateDisplay(
+            mId, &numTypes, &numRequests, &presentFenceFd, state);
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -720,15 +634,23 @@
 
 void Display::discardCommands()
 {
-    mDevice.mComposer->resetCommands();
+    mComposer.resetCommands();
 }
 
 // For use by Device
 
+void Display::setConnected(bool connected) {
+    if (!mIsConnected && connected && mType == DisplayType::Physical) {
+        mComposer.setClientTargetSlotCount(mId);
+        loadConfigs();
+    }
+    mIsConnected = connected;
+}
+
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
-    auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
+    auto intError = mComposer.getDisplayAttribute(mId, configId,
             static_cast<Hwc2::IComposerClient::Attribute>(attribute),
             &value);
     auto error = static_cast<Error>(intError);
@@ -760,7 +682,7 @@
     ALOGV("[%" PRIu64 "] loadConfigs", mId);
 
     std::vector<Hwc2::Config> configIds;
-    auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
+    auto intError = mComposer.getDisplayConfigs(mId, &configIds);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
@@ -773,54 +695,51 @@
     }
 }
 
-// For use by Layer
-
-void Display::destroyLayer(hwc2_layer_t layerId)
-{
-    auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-    auto error = static_cast<Error>(intError);
-    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
-            " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
-            intError);
-    mLayers.erase(layerId);
-}
-
 // Other Display methods
 
-std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
+Layer* Display::getLayerById(hwc2_layer_t id) const
 {
     if (mLayers.count(id) == 0) {
         return nullptr;
     }
 
-    auto layer = mLayers.at(id).lock();
-    return layer;
+    return mLayers.at(id).get();
 }
 
 // Layer methods
 
-Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
-  : mDisplay(display),
-    mDisplayId(display->getId()),
-    mDevice(display->getDevice()),
-    mId(id)
+Layer::Layer(android::Hwc2::Composer& composer,
+             const std::unordered_set<Capability>& capabilities,
+             hwc2_display_t displayId, hwc2_layer_t layerId)
+  : mComposer(composer),
+    mCapabilities(capabilities),
+    mDisplayId(displayId),
+    mId(layerId)
 {
-    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
-            display->getId());
+    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId);
 }
 
 Layer::~Layer()
 {
-    auto display = mDisplay.lock();
-    if (display) {
-        display->destroyLayer(mId);
+    auto intError = mComposer.destroyLayer(mDisplayId, mId);
+    auto error = static_cast<Error>(intError);
+    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+            " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
+            intError);
+    if (mLayerDestroyedListener) {
+        mLayerDestroyedListener(this);
     }
 }
 
+void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) {
+    LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener,
+            "Attempt to set layer destroyed listener multiple times");
+    mLayerDestroyedListener = listener;
+}
+
 Error Layer::setCursorPosition(int32_t x, int32_t y)
 {
-    auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
-            mId, x, y);
+    auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y);
     return static_cast<Error>(intError);
 }
 
@@ -828,8 +747,8 @@
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
-    auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
-            mId, slot, buffer, fenceFd);
+    auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer,
+                                             fenceFd);
     return static_cast<Error>(intError);
 }
 
@@ -839,7 +758,7 @@
     // rects for HWC
     Hwc2::Error intError = Hwc2::Error::NONE;
     if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+        intError = mComposer.setLayerSurfaceDamage(mDisplayId,
                 mId, std::vector<Hwc2::IComposerClient::Rect>());
     } else {
         size_t rectCount = 0;
@@ -851,8 +770,7 @@
                     rectArray[rect].right, rectArray[rect].bottom});
         }
 
-        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
-                mId, hwcRects);
+        intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects);
     }
 
     return static_cast<Error>(intError);
@@ -861,32 +779,33 @@
 Error Layer::setBlendMode(BlendMode mode)
 {
     auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
-    auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
-            mId, intMode);
+    auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setColor(hwc_color_t color)
 {
     Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
-    auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
-            mId, hwcColor);
+    auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setCompositionType(Composition type)
 {
     auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
-    auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
-            mId, intType);
+    auto intError = mComposer.setLayerCompositionType(
+            mDisplayId, mId, intType);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDataspace(android_dataspace_t dataspace)
 {
+    if (dataspace == mDataSpace) {
+        return Error::None;
+    }
+    mDataSpace = dataspace;
     auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
-    auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
-            mId, intDataspace);
+    auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace);
     return static_cast<Error>(intError);
 }
 
@@ -894,27 +813,24 @@
 {
     Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
         frame.right, frame.bottom};
-    auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
-            mId, hwcRect);
+    auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setPlaneAlpha(float alpha)
 {
-    auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
-            mId, alpha);
+    auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setSidebandStream(const native_handle_t* stream)
 {
-    if (!mDevice.hasCapability(Capability::SidebandStream)) {
+    if (mCapabilities.count(Capability::SidebandStream) == 0) {
         ALOGE("Attempted to call setSidebandStream without checking that the "
                 "device supports sideband streams");
         return Error::Unsupported;
     }
-    auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
-            mId, stream);
+    auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream);
     return static_cast<Error>(intError);
 }
 
@@ -922,16 +838,14 @@
 {
     Hwc2::IComposerClient::FRect hwcRect{
         crop.left, crop.top, crop.right, crop.bottom};
-    auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
-            mId, hwcRect);
+    auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setTransform(Transform transform)
 {
     auto intTransform = static_cast<Hwc2::Transform>(transform);
-    auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
-            mId, intTransform);
+    auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform);
     return static_cast<Error>(intError);
 }
 
@@ -946,20 +860,19 @@
                 rectArray[rect].right, rectArray[rect].bottom});
     }
 
-    auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
-            mId, hwcRects);
+    auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setZOrder(uint32_t z)
 {
-    auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
+    auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setInfo(uint32_t type, uint32_t appId)
 {
-  auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
+  auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId);
   return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 7463e3b..949f0e3 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -53,10 +53,26 @@
 class Display;
 class Layer;
 
-typedef std::function<void(std::shared_ptr<Display>, Connection)>
-        HotplugCallback;
-typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
-typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
+// Implement this interface to receive hardware composer events.
+//
+// These callback functions will generally be called on a hwbinder thread, but
+// when first registering the callback the onHotplugReceived() function will
+// immediately be called on the thread calling registerCallback().
+//
+// All calls receive a sequenceId, which will be the value that was supplied to
+// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
+// from different hardware composer instances.
+class ComposerCallback {
+ public:
+    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+                                   Connection connection,
+                                   bool primaryDisplay) = 0;
+    virtual void onRefreshReceived(int32_t sequenceId,
+                                   hwc2_display_t display) = 0;
+    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+                                 int64_t timestamp) = 0;
+    virtual ~ComposerCallback() = default;
+};
 
 // C++ Wrapper around hwc2_device_t. Load all functions pointers
 // and handle callback registration.
@@ -67,10 +83,8 @@
     // will use the vr composer service, otherwise it uses the real hardware
     // composer.
     Device(bool useVrComposer);
-    ~Device();
 
-    friend class HWC2::Display;
-    friend class HWC2::Layer;
+    void registerCallback(ComposerCallback* callback, int32_t sequenceId);
 
     // Required by HWC2
 
@@ -82,27 +96,14 @@
 
     uint32_t getMaxVirtualDisplayCount() const;
     Error createVirtualDisplay(uint32_t width, uint32_t height,
-            android_pixel_format_t* format,
-            std::shared_ptr<Display>* outDisplay);
+            android_pixel_format_t* format, Display** outDisplay);
+    void destroyDisplay(hwc2_display_t displayId);
 
-    void registerHotplugCallback(HotplugCallback hotplug);
-    void registerRefreshCallback(RefreshCallback refresh);
-    void registerVsyncCallback(VsyncCallback vsync);
-
-    // For use by callbacks
-
-    void callHotplug(std::shared_ptr<Display> display, Connection connected);
-    void callRefresh(std::shared_ptr<Display> display);
-    void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp);
+    void onHotplug(hwc2_display_t displayId, Connection connection);
 
     // Other Device methods
 
-    // This will create a Display if one is not found, but it will not be marked
-    // as connected. This Display may be null if the display has been torn down
-    // but has not been removed from the map yet.
-    std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
-
-    bool hasCapability(HWC2::Capability capability) const;
+    Display* getDisplayById(hwc2_display_t id);
 
     android::Hwc2::Composer* getComposer() { return mComposer.get(); }
 
@@ -110,37 +111,23 @@
     // Initialization methods
 
     void loadCapabilities();
-    void registerCallbacks();
-
-    // For use by Display
-
-    void destroyVirtualDisplay(hwc2_display_t display);
 
     // Member variables
     std::unique_ptr<android::Hwc2::Composer> mComposer;
-
     std::unordered_set<Capability> mCapabilities;
-    std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
-
-    HotplugCallback mHotplug;
-    std::vector<std::pair<std::shared_ptr<Display>, Connection>>
-            mPendingHotplugs;
-    RefreshCallback mRefresh;
-    std::vector<std::shared_ptr<Display>> mPendingRefreshes;
-    VsyncCallback mVsync;
-    std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
+    std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+    bool mRegisteredCallback;
 };
 
 // Convenience C++ class to access hwc2_device_t Display functions directly.
-class Display : public std::enable_shared_from_this<Display>
+class Display
 {
 public:
-    Display(Device& device, hwc2_display_t id);
+    Display(android::Hwc2::Composer& composer,
+            const std::unordered_set<Capability>& capabilities,
+            hwc2_display_t id, DisplayType type);
     ~Display();
 
-    friend class HWC2::Device;
-    friend class HWC2::Layer;
-
     class Config
     {
     public:
@@ -213,12 +200,12 @@
     // Required by HWC2
 
     [[clang::warn_unused_result]] Error acceptChanges();
-    [[clang::warn_unused_result]] Error createLayer(
-            std::shared_ptr<Layer>* outLayer);
+    [[clang::warn_unused_result]] Error createLayer(Layer** outLayer);
+    [[clang::warn_unused_result]] Error destroyLayer(Layer* layer);
     [[clang::warn_unused_result]] Error getActiveConfig(
             std::shared_ptr<const Config>* outConfig) const;
     [[clang::warn_unused_result]] Error getChangedCompositionTypes(
-            std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+            std::unordered_map<Layer*, Composition>* outTypes);
     [[clang::warn_unused_result]] Error getColorModes(
             std::vector<android_color_mode_t>* outModes) const;
 
@@ -228,14 +215,13 @@
     [[clang::warn_unused_result]] Error getName(std::string* outName) const;
     [[clang::warn_unused_result]] Error getRequests(
             DisplayRequest* outDisplayRequests,
-            std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
-                    outLayerRequests);
+            std::unordered_map<Layer*, LayerRequest>* outLayerRequests);
     [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
     [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
     [[clang::warn_unused_result]] Error getHdrCapabilities(
             std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
     [[clang::warn_unused_result]] Error getReleaseFences(
-            std::unordered_map<std::shared_ptr<Layer>,
+            std::unordered_map<Layer*,
                     android::sp<android::Fence>>* outFences) const;
     [[clang::warn_unused_result]] Error present(
             android::sp<android::Fence>* outPresentFence);
@@ -267,32 +253,31 @@
 
     // Other Display methods
 
-    Device& getDevice() const { return mDevice; }
     hwc2_display_t getId() const { return mId; }
     bool isConnected() const { return mIsConnected; }
+    void setConnected(bool connected);  // For use by Device only
 
 private:
-    // For use by Device
-
-    void setConnected(bool connected) { mIsConnected = connected; }
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
     void loadConfig(hwc2_config_t configId);
     void loadConfigs();
 
-    // For use by Layer
-    void destroyLayer(hwc2_layer_t layerId);
-
     // This may fail (and return a null pointer) if no layer with this ID exists
     // on this display
-    std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const;
+    Layer* getLayerById(hwc2_layer_t id) const;
 
     // Member variables
 
-    Device& mDevice;
+    // These are references to data owned by HWC2::Device, which will outlive
+    // this HWC2::Display, so these references are guaranteed to be valid for
+    // the lifetime of this object.
+    android::Hwc2::Composer& mComposer;
+    const std::unordered_set<Capability>& mCapabilities;
+
     hwc2_display_t mId;
     bool mIsConnected;
     DisplayType mType;
-    std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
+    std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
     // The ordering in this map matters, for getConfigs(), when it is
     // converted to a vector
     std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
@@ -302,12 +287,18 @@
 class Layer
 {
 public:
-    Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id);
+    Layer(android::Hwc2::Composer& composer,
+          const std::unordered_set<Capability>& capabilities,
+          hwc2_display_t displayId, hwc2_layer_t layerId);
     ~Layer();
 
-    bool isAbandoned() const { return mDisplay.expired(); }
     hwc2_layer_t getId() const { return mId; }
 
+    // Register a listener to be notified when the layer is destroyed. When the
+    // listener function is called, the Layer will be in the process of being
+    // destroyed, so it's not safe to call methods on it.
+    void setLayerDestroyedListener(std::function<void(Layer*)> listener);
+
     [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
     [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
             const android::sp<android::GraphicBuffer>& buffer,
@@ -334,10 +325,16 @@
     [[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId);
 
 private:
-    std::weak_ptr<Display> mDisplay;
+    // These are references to data owned by HWC2::Device, which will outlive
+    // this HWC2::Layer, so these references are guaranteed to be valid for
+    // the lifetime of this object.
+    android::Hwc2::Composer& mComposer;
+    const std::unordered_set<Capability>& mCapabilities;
+
     hwc2_display_t mDisplayId;
-    Device& mDevice;
     hwc2_layer_t mId;
+    android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
+    std::function<void(Layer*)> mLayerDestroyedListener;
 };
 
 } // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index ac2dde2..3f3c67b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -65,7 +65,6 @@
       mFreeDisplaySlots(),
       mHwcDisplaySlots(),
       mCBContext(),
-      mEventHandler(nullptr),
       mVSyncCounts(),
       mRemainingHwcVirtualDisplays(0)
 {
@@ -74,40 +73,15 @@
         mVSyncCounts[i] = 0;
     }
 
-    loadHwcModule(useVrComposer);
+    mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
+    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
 
 HWComposer::~HWComposer() {}
 
-void HWComposer::setEventHandler(EventHandler* handler)
-{
-    if (handler == nullptr) {
-        ALOGE("setEventHandler: Rejected attempt to clear handler");
-        return;
-    }
-
-    bool wasNull = (mEventHandler == nullptr);
-    mEventHandler = handler;
-
-    if (wasNull) {
-        auto hotplugHook = std::bind(&HWComposer::hotplug, this,
-                std::placeholders::_1, std::placeholders::_2);
-        mHwcDevice->registerHotplugCallback(hotplugHook);
-        auto invalidateHook = std::bind(&HWComposer::invalidate, this,
-                std::placeholders::_1);
-        mHwcDevice->registerRefreshCallback(invalidateHook);
-        auto vsyncHook = std::bind(&HWComposer::vsync, this,
-                std::placeholders::_1, std::placeholders::_2);
-        mHwcDevice->registerVsyncCallback(vsyncHook);
-    }
-}
-
-// Load and prepare the hardware composer module.  Sets mHwc.
-void HWComposer::loadHwcModule(bool useVrComposer)
-{
-    ALOGV("loadHwcModule");
-    mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);
-    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
+                                  int32_t sequenceId) {
+    mHwcDevice->registerCallback(callback, sequenceId);
 }
 
 bool HWComposer::hasCapability(HWC2::Capability capability) const
@@ -145,54 +119,51 @@
     }
 }
 
-void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
-        HWC2::Connection connected) {
-    ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
-            to_string(connected).c_str());
-    int32_t disp = 0;
+void HWComposer::onHotplug(hwc2_display_t displayId,
+                           HWC2::Connection connection) {
+    ALOGV("hotplug: %" PRIu64 ", %s", displayId,
+            to_string(connection).c_str());
+    mHwcDevice->onHotplug(displayId, connection);
     if (!mDisplayData[0].hwcDisplay) {
-        ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+        ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
                 " display would be connected");
-        mDisplayData[0].hwcDisplay = display;
-        mHwcDisplaySlots[display->getId()] = 0;
-        disp = DisplayDevice::DISPLAY_PRIMARY;
+        mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+        mHwcDisplaySlots[displayId] = 0;
     } else {
         // Disconnect is handled through HWComposer::disconnectDisplay via
         // SurfaceFlinger's onHotplugReceived callback handling
-        if (connected == HWC2::Connection::Connected) {
-            mDisplayData[1].hwcDisplay = display;
-            mHwcDisplaySlots[display->getId()] = 1;
+        if (connection == HWC2::Connection::Connected) {
+            mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+            mHwcDisplaySlots[displayId] = 1;
         }
-        disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-    mEventHandler->onHotplugReceived(this, disp,
-            connected == HWC2::Connection::Connected);
 }
 
-void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
-    mEventHandler->onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
-        int64_t timestamp) {
+bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
+                         int32_t* outDisplay) {
+    auto display = mHwcDevice->getDisplayById(displayId);
+    if (!display) {
+        ALOGE("onVsync Failed to find display %" PRIu64, displayId);
+        return false;
+    }
     auto displayType = HWC2::DisplayType::Invalid;
     auto error = display->getType(&displayType);
     if (error != HWC2::Error::None) {
-        ALOGE("vsync: Failed to determine type of display %" PRIu64,
+        ALOGE("onVsync: Failed to determine type of display %" PRIu64,
                 display->getId());
-        return;
+        return false;
     }
 
     if (displayType == HWC2::DisplayType::Virtual) {
         ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
                 display->getId());
-        return;
+        return false;
     }
 
     if (mHwcDisplaySlots.count(display->getId()) == 0) {
         ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
                 display->getId());
-        return;
+        return false;
     }
 
     int32_t disp = mHwcDisplaySlots[display->getId()];
@@ -206,17 +177,21 @@
         if (timestamp == mLastHwVSync[disp]) {
             ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
                     timestamp);
-            return;
+            return false;
         }
 
         mLastHwVSync[disp] = timestamp;
     }
 
+    if (outDisplay) {
+        *outDisplay = disp;
+    }
+
     char tag[16];
     snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
     ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
 
-    mEventHandler->onVSyncReceived(this, disp, timestamp);
+    return true;
 }
 
 status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -235,7 +210,7 @@
         return INVALID_OPERATION;
     }
 
-    std::shared_ptr<HWC2::Display> display;
+    HWC2::Display* display;
     auto error = mHwcDevice->createVirtualDisplay(width, height, format,
             &display);
     if (error != HWC2::Error::None) {
@@ -264,13 +239,13 @@
     return NO_ERROR;
 }
 
-std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
     if (!isValidDisplay(displayId)) {
         ALOGE("Failed to create layer on invalid display %d", displayId);
         return nullptr;
     }
     auto display = mDisplayData[displayId].hwcDisplay;
-    std::shared_ptr<HWC2::Layer> layer;
+    HWC2::Layer* layer;
     auto error = display->createLayer(&layer);
     if (error != HWC2::Error::None) {
         ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
@@ -280,6 +255,19 @@
     return layer;
 }
 
+void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("Failed to destroy layer on invalid display %d", displayId);
+        return;
+    }
+    auto display = mDisplayData[displayId].hwcDisplay;
+    auto error = display->destroyLayer(layer);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to destroy layer on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+}
+
 nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const {
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
@@ -347,10 +335,8 @@
                 displayId);
         return modes;
     }
-    const std::shared_ptr<HWC2::Display>& hwcDisplay =
-            mDisplayData[displayId].hwcDisplay;
 
-    auto error = hwcDisplay->getColorModes(&modes);
+    auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes);
     if (error != HWC2::Error::None) {
         ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
@@ -470,7 +456,7 @@
             return UNKNOWN_ERROR;
         }
         if (state == 1) { //Present Succeeded.
-            std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+            std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
             error = hwcDisplay->getReleaseFences(&releaseFences);
             displayData.releaseFences = std::move(releaseFences);
             displayData.lastPresentFence = outPresentFence;
@@ -489,8 +475,7 @@
         return BAD_INDEX;
     }
 
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
-        changedTypes;
+    std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
     changedTypes.reserve(numTypes);
     error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
     if (error != HWC2::Error::None) {
@@ -502,8 +487,7 @@
 
 
     displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
-        layerRequests;
+    std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
     layerRequests.reserve(numRequests);
     error = hwcDisplay->getRequests(&displayData.displayRequests,
             &layerRequests);
@@ -597,7 +581,7 @@
 }
 
 sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
-        const std::shared_ptr<HWC2::Layer>& layer) const {
+        HWC2::Layer* layer) const {
     if (!isValidDisplay(displayId)) {
         ALOGE("getLayerReleaseFence: Invalid display");
         return Fence::NO_FENCE;
@@ -638,7 +622,7 @@
         return UNKNOWN_ERROR;
     }
 
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+    std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
     error = hwcDisplay->getReleaseFences(&releaseFences);
     if (error != HWC2::Error::None) {
         ALOGE("presentAndGetReleaseFences: Failed to get release fences "
@@ -786,6 +770,8 @@
     auto hwcId = displayData.hwcDisplay->getId();
     mHwcDisplaySlots.erase(hwcId);
     displayData.reset();
+
+    mHwcDevice->destroyDisplay(hwcId);
 }
 
 status_t HWComposer::setOutputBuffer(int32_t displayId,
@@ -884,7 +870,7 @@
 HWComposer::DisplayData::DisplayData()
   : hasClientComposition(false),
     hasDeviceComposition(false),
-    hwcDisplay(),
+    hwcDisplay(nullptr),
     lastPresentFence(Fence::NO_FENCE),
     outbufHandle(nullptr),
     outbufAcquireFence(Fence::NO_FENCE),
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7463362..e25dee1 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -65,16 +65,6 @@
 class HWComposer
 {
 public:
-    class EventHandler {
-        friend class HWComposer;
-        virtual void onVSyncReceived(
-            HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
-        virtual void onInvalidateReceived(HWComposer* composer) = 0;
-    protected:
-        virtual ~EventHandler() {}
-    };
-
     // useVrComposer is passed to the composer HAL. When true, the composer HAL
     // will use the vr composer service, otherwise it uses the real hardware
     // composer.
@@ -82,7 +72,8 @@
 
     ~HWComposer();
 
-    void setEventHandler(EventHandler* handler);
+    void registerCallback(HWC2::ComposerCallback* callback,
+                          int32_t sequenceId);
 
     bool hasCapability(HWC2::Capability capability) const;
 
@@ -92,7 +83,9 @@
             android_pixel_format_t* format, int32_t* outId);
 
     // Attempts to create a new layer on this display
-    std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
+    HWC2::Layer* createLayer(int32_t displayId);
+    // Destroy a previously created layer
+    void destroyLayer(int32_t displayId, HWC2::Layer* layer);
 
     // Asks the HAL what it can do
     status_t prepare(DisplayDevice& displayDevice);
@@ -127,7 +120,7 @@
 
     // Get last release fence for the given layer
     sp<Fence> getLayerReleaseFence(int32_t displayId,
-            const std::shared_ptr<HWC2::Layer>& layer) const;
+            HWC2::Layer* layer) const;
 
     // Set the output buffer and acquire fence for a virtual display.
     // Returns INVALID_OPERATION if displayId is not a virtual display.
@@ -143,6 +136,12 @@
 
     // Events handling ---------------------------------------------------------
 
+    // Returns true if successful, false otherwise. The
+    // DisplayDevice::DisplayType of the display is returned as an output param.
+    bool onVsync(hwc2_display_t displayId, int64_t timestamp,
+                 int32_t* outDisplay);
+    void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
+
     void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
 
     // Query display parameters.  Pass in a display index (e.g.
@@ -170,19 +169,11 @@
 private:
     static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
-    void loadHwcModule(bool useVrComposer);
-
     bool isValidDisplay(int32_t displayId) const;
     static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
     struct cb_context;
 
-    void invalidate(const std::shared_ptr<HWC2::Display>& display);
-    void vsync(const std::shared_ptr<HWC2::Display>& display,
-            int64_t timestamp);
-    void hotplug(const std::shared_ptr<HWC2::Display>& display,
-            HWC2::Connection connected);
-
     struct DisplayData {
         DisplayData();
         ~DisplayData();
@@ -190,11 +181,10 @@
 
         bool hasClientComposition;
         bool hasDeviceComposition;
-        std::shared_ptr<HWC2::Display> hwcDisplay;
+        HWC2::Display* hwcDisplay;
         HWC2::DisplayRequest displayRequests;
         sp<Fence> lastPresentFence;  // signals when the last set op retires
-        std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
-                releaseFences;
+        std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
         buffer_handle_t outbufHandle;
         sp<Fence> outbufAcquireFence;
         mutable std::unordered_map<int32_t,
@@ -215,7 +205,6 @@
     mutable Mutex mDisplayLock;
 
     cb_context*                     mCBContext;
-    EventHandler*                   mEventHandler;
     size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
     uint32_t                        mRemainingHwcVirtualDisplays;
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 8217540..1de5e48 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -16,12 +16,16 @@
 
 // #define LOG_NDEBUG 0
 #include "VirtualDisplaySurface.h"
+
+#include <inttypes.h>
+
 #include "HWComposer.h"
 #include "SurfaceFlinger.h"
 
 #include <gui/BufferItem.h>
 #include <gui/BufferQueue.h>
 #include <gui/IProducerListener.h>
+#include <system/window.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -338,11 +342,12 @@
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
-        PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
+        PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
     LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
 
-    status_t result = mSource[source]->dequeueBuffer(sslot, fence,
-            mSinkBufferWidth, mSinkBufferHeight, format, usage, nullptr);
+    status_t result =
+            mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
+                                           format, usage, nullptr, nullptr);
     if (result < 0)
         return result;
     int pslot = mapSource2ProducerSlot(source, *sslot);
@@ -371,7 +376,7 @@
             mSource[source]->cancelBuffer(*sslot, *fence);
             return result;
         }
-        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
+        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64,
                 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
                 mProducerBuffers[pslot]->getPixelFormat(),
                 mProducerBuffers[pslot]->getUsage());
@@ -380,19 +385,20 @@
     return result;
 }
 
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
+status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                              PixelFormat format, uint64_t usage,
+                                              uint64_t* outBufferAge,
+                                              FrameEventHistoryDelta* outTimestamps) {
     if (mDisplayId < 0) {
-        return mSource[SOURCE_SINK]->dequeueBuffer(
-                pslot, fence, w, h, format, usage, outTimestamps);
+        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
+                                                   outTimestamps);
     }
 
     VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
             "Unexpected dequeueBuffer() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_GLES;
 
-    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
+    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#" PRIx64, w, h, format, usage);
 
     status_t result = NO_ERROR;
     Source source = fbSourceForCompositionType(mCompositionType);
@@ -422,8 +428,8 @@
                 (w != 0 && w != mSinkBufferWidth) ||
                 (h != 0 && h != mSinkBufferHeight)) {
             VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
-                    "want %dx%d fmt=%d use=%#x, "
-                    "have %dx%d fmt=%d use=%#x",
+                    "want %dx%d fmt=%d use=%#" PRIx64 ", "
+                    "have %dx%d fmt=%d use=%#" PRIx64,
                     w, h, format, usage,
                     mSinkBufferWidth, mSinkBufferHeight,
                     buf->getPixelFormat(), buf->getUsage());
@@ -445,6 +451,9 @@
             *pslot = mapSource2ProducerSlot(source, sslot);
         }
     }
+    if (outBufferAge) {
+        *outBufferAge = 0;
+    }
     return result;
 }
 
@@ -574,7 +583,7 @@
 }
 
 void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
-        uint32_t /* height */, PixelFormat /* format */, uint32_t /* usage */) {
+        uint32_t /* height */, PixelFormat /* format */, uint64_t /* usage */) {
     // TODO: Should we actually allocate buffers for a virtual display?
 }
 
@@ -618,6 +627,10 @@
     return INVALID_OPERATION;
 }
 
+status_t VirtualDisplaySurface::getConsumerUsage(uint64_t* outUsage) const {
+    return mSource[SOURCE_SINK]->getConsumerUsage(outUsage);
+}
+
 void VirtualDisplaySurface::updateQueueBufferOutput(
         QueueBufferOutput&& qbo) {
     mQueueBufferOutput = std::move(qbo);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 5c0e084..1671aba 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -104,9 +104,9 @@
     virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta *outTimestamps);
+    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
@@ -120,7 +120,7 @@
     virtual status_t disconnect(int api, DisconnectMode mode);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
@@ -130,12 +130,13 @@
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
+    virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
 
     //
     // Utility methods
     //
     static Source fbSourceForCompositionType(CompositionType type);
-    status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
+    status_t dequeueBuffer(Source source, PixelFormat format, uint64_t usage,
             int* sslot, sp<Fence>* fence);
     void updateQueueBufferOutput(QueueBufferOutput&& qbo);
     void resetPerFrameState();
@@ -168,7 +169,7 @@
     // the composition type changes or the GLES driver starts requesting
     // different usage/format, we'll get a new buffer.
     uint32_t mOutputFormat;
-    uint32_t mOutputUsage;
+    uint64_t mOutputUsage;
 
     // Since we present a single producer interface to the GLES driver, but
     // are internally muxing between the sink and scratch producers, we have
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index ee6e886..052a959 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -31,34 +31,35 @@
 }
 
 bool EventControlThread::threadLoop() {
-    Mutex::Autolock lock(mMutex);
-
-    bool vsyncEnabled = mVsyncEnabled;
-
-#ifdef USE_HWC2
-    mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
-#else
-    mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
-            mVsyncEnabled);
-#endif
+    enum class VsyncState {Unset, On, Off};
+    auto currentVsyncState = VsyncState::Unset;
 
     while (true) {
-        status_t err = mCond.wait(mMutex);
-        if (err != NO_ERROR) {
-            ALOGE("error waiting for new events: %s (%d)",
-                strerror(-err), err);
-            return false;
+        auto requestedVsyncState = VsyncState::On;
+        {
+            Mutex::Autolock lock(mMutex);
+            requestedVsyncState =
+                    mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+            while (currentVsyncState == requestedVsyncState) {
+                status_t err = mCond.wait(mMutex);
+                if (err != NO_ERROR) {
+                    ALOGE("error waiting for new events: %s (%d)",
+                          strerror(-err), err);
+                    return false;
+                }
+                requestedVsyncState =
+                        mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+            }
         }
 
-        if (vsyncEnabled != mVsyncEnabled) {
+        bool enable = requestedVsyncState == VsyncState::On;
 #ifdef USE_HWC2
-            mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+        mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
 #else
-            mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
-                    SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+        mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
+                SurfaceFlinger::EVENT_VSYNC, enable);
 #endif
-            vsyncEnabled = mVsyncEnabled;
-        }
+        currentVsyncState = requestedVsyncState;
     }
 
     return false;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
old mode 100644
new mode 100755
index 022b416..038ece2
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -34,6 +34,7 @@
 #include <utils/StopWatch.h>
 #include <utils/Trace.h>
 
+#include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 
@@ -125,6 +126,7 @@
         mPremultipliedAlpha = false;
 
     mName = name;
+    mTransactionName = String8("TX - ") + mName;
 
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
@@ -198,6 +200,14 @@
     }
     mFlinger->deleteTextureAsync(mTextureName);
     mFrameTracker.logAndResetStats(mName);
+
+#ifdef USE_HWC2
+    if (!mHwcLayers.empty()) {
+        ALOGE("Found stale hardware composer layers when destroying "
+                "surface flinger layer %s", mName.string());
+        destroyAllHwcLayers();
+    }
+#endif
 }
 
 // ---------------------------------------------------------------------------
@@ -285,22 +295,29 @@
     }
 }
 
-// called with SurfaceFlinger::mStateLock from the drawing thread after
-// the layer has been remove from the current state list (and just before
-// it's removed from the drawing state list)
-void Layer::onRemoved() {
+void Layer::onRemovedFromCurrentState() {
+    // 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);
         }
         mCurrentState.zOrderRelativeOf = nullptr;
     }
 
-    mSurfaceFlingerConsumer->abandon();
+    for (const auto& child : mCurrentChildren) {
+        child->onRemovedFromCurrentState();
+    }
+}
 
+void Layer::onRemoved() {
+    // the layer is removed from SF mLayersPendingRemoval
+
+    mSurfaceFlingerConsumer->abandon();
 #ifdef USE_HWC2
-    clearHwcLayers();
+    destroyAllHwcLayers();
 #endif
 
     for (const auto& child : mCurrentChildren) {
@@ -361,6 +378,48 @@
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
+#ifdef USE_HWC2
+bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
+    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+                "Already have a layer for hwcId %d", hwcId);
+    HWC2::Layer* layer = hwc->createLayer(hwcId);
+    if (!layer) {
+        return false;
+    }
+    HWCInfo& hwcInfo = mHwcLayers[hwcId];
+    hwcInfo.hwc = hwc;
+    hwcInfo.layer = layer;
+    layer->setLayerDestroyedListener(
+            [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+    return true;
+}
+
+void Layer::destroyHwcLayer(int32_t hwcId) {
+    if (mHwcLayers.count(hwcId) == 0) {
+        return;
+    }
+    auto& hwcInfo = mHwcLayers[hwcId];
+    LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
+            "Attempt to destroy null layer");
+    LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
+    hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
+    // The layer destroyed listener should have cleared the entry from
+    // mHwcLayers. Verify that.
+    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+            "Stale layer entry in mHwcLayers");
+}
+
+void Layer::destroyAllHwcLayers() {
+    size_t numLayers = mHwcLayers.size();
+    for (size_t i = 0; i < numLayers; ++i) {
+        LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
+        destroyHwcLayer(mHwcLayers.begin()->first);
+    }
+    LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
+            "All hardware composer layers should have been destroyed");
+}
+#endif
+
 Rect Layer::getContentCrop() const {
     // this is the crop rectangle that applies to the buffer
     // itself (as opposed to the window)
@@ -472,7 +531,7 @@
 
     Rect activeCrop(s.active.w, s.active.h);
     if (!s.crop.isEmpty()) {
-        activeCrop = s.crop;
+        activeCrop.intersect(s.crop, &activeCrop);
     }
 
     Transform t = getTransform();
@@ -893,9 +952,6 @@
     }
 }
 
-android_dataspace Layer::getDataSpace() const {
-    return mCurrentState.dataSpace;
-}
 #else
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer) {
@@ -1310,7 +1366,8 @@
         // able to be latched. To avoid this, grab this buffer anyway.
         return true;
     }
-    return mQueueItems[0].mFence->getSignalTime() != INT64_MAX;
+    return mQueueItems[0].mFenceTime->getSignalTime() !=
+            Fence::SIGNAL_TIME_PENDING;
 #else
     return true;
 #endif
@@ -1417,9 +1474,9 @@
 
 bool Layer::isOpaque(const Layer::State& s) const
 {
-    // if we don't have a buffer yet, we're translucent regardless of the
+    // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
     // layer's opaque flag.
-    if (mActiveBuffer == 0) {
+    if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
         return false;
     }
 
@@ -1505,6 +1562,7 @@
         mFlinger->setTransactionFlags(eTraversalNeeded);
     }
     mPendingStates.push_back(mCurrentState);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 void Layer::popPendingState(State* stateToCommit) {
@@ -1514,6 +1572,7 @@
             (stateToCommit->flags & stateToCommit->mask);
 
     mPendingStates.removeAt(0);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 bool Layer::applyPendingStates(State* stateToCommit) {
@@ -1928,6 +1987,10 @@
     return true;
 }
 
+android_dataspace Layer::getDataSpace() const {
+    return mCurrentState.dataSpace;
+}
+
 uint32_t Layer::getLayerStack() const {
     auto p = mDrawingParent.promote();
     if (p == nullptr) {
@@ -1947,7 +2010,6 @@
     mCurrentState.barrierLayer = nullptr;
     mCurrentState.frameNumber = 0;
     mCurrentState.modified = false;
-    ALOGE("Deferred transaction");
 }
 
 void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle,
@@ -2007,9 +2069,6 @@
 bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
         const std::shared_ptr<FenceTime>& presentFence,
         const CompositorTiming& compositorTiming) {
-    mAcquireTimeline.updateSignalTimes();
-    mReleaseTimeline.updateSignalTimes();
-
     // mFrameLatencyNeeded is true when a new frame was latched for the
     // composition.
     if (!mFrameLatencyNeeded)
@@ -2060,6 +2119,7 @@
 
     auto releaseFenceTime = std::make_shared<FenceTime>(
             mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+    mReleaseTimeline.updateSignalTimes();
     mReleaseTimeline.push(releaseFenceTime);
 
     Mutex::Autolock lock(mFrameEventHistoryMutex);
@@ -2250,6 +2310,7 @@
 #ifndef USE_HWC2
         auto releaseFenceTime = std::make_shared<FenceTime>(
                 mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+        mReleaseTimeline.updateSignalTimes();
         mReleaseTimeline.push(releaseFenceTime);
         if (mPreviousFrameNumber != 0) {
             mFrameEventHistory.addRelease(mPreviousFrameNumber,
@@ -2373,11 +2434,17 @@
     visibleRegion.dump(result, "visibleRegion");
     surfaceDamageRegion.dump(result, "surfaceDamageRegion");
     sp<Client> client(mClientRef.promote());
+    PixelFormat pf = PIXEL_FORMAT_UNKNOWN;
+    const sp<GraphicBuffer>& buffer(getActiveBuffer());
+    if (buffer != NULL) {
+        pf = buffer->getPixelFormat();
+    }
 
     result.appendFormat(            "      "
             "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), "
             "crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
+            "dataspace=%s, pixelformat=%s "
 #ifdef USE_HWC2
             "alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
 #else
@@ -2392,6 +2459,7 @@
             s.finalCrop.left, s.finalCrop.top,
             s.finalCrop.right, s.finalCrop.bottom,
             isOpaque(s), contentDirty,
+            dataspaceDetails(getDataSpace()).c_str(), decodePixelFormat(pf).c_str(),
             s.alpha, s.flags,
             s.active.transform[0][0], s.active.transform[0][1],
             s.active.transform[1][0], s.active.transform[1][1],
@@ -2498,6 +2566,12 @@
         FrameEventHistoryDelta *outDelta) {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     if (newTimestamps) {
+        // If there are any unsignaled fences in the aquire timeline at this
+        // point, the previously queued frame hasn't been latched yet. Go ahead
+        // and try to get the signal time here so the syscall is taken out of
+        // the main thread's critical path.
+        mAcquireTimeline.updateSignalTimes();
+        // Push the new fence after updating since it's likely still pending.
         mAcquireTimeline.push(newTimestamps->acquireFence);
         mFrameEventHistory.addQueue(*newTimestamps);
     }
@@ -2683,7 +2757,7 @@
         // for in the transform. We need to mirror this scaling in child surfaces
         // or we will break the contract where WM can treat child surfaces as
         // pixels in the parent surface.
-        if (p->isFixedSize()) {
+        if (p->isFixedSize() && p->mActiveBuffer != nullptr) {
             int bufferWidth;
             int bufferHeight;
             if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 24fc10d..c34d8a0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -166,6 +166,8 @@
 
     virtual ~Layer();
 
+    void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
+
     // the this layer's size and format
     status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
 
@@ -231,6 +233,7 @@
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setLayerStack(uint32_t layerStack);
     bool setDataSpace(android_dataspace dataSpace);
+    android_dataspace getDataSpace() const;
     uint32_t getLayerStack() const;
     void deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
     void deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber);
@@ -248,6 +251,10 @@
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags);
 
+    bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const {
+        return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
+    }
+
     void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
             bool useIdentityTransform) const;
     Rect computeBounds(const Region& activeTransparentRegion) const;
@@ -314,8 +321,6 @@
     void forceClientComposition(int32_t hwcId);
     void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
 
-    android_dataspace getDataSpace() const;
-
     // callIntoHwc exists so we can update our local state and call
     // acceptDisplayChanges without unnecessarily updating the device's state
     void setCompositionType(int32_t hwcId, HWC2::Composition type,
@@ -409,12 +414,19 @@
      * to figure out if the content or size of a surface has changed.
      */
     Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime);
+    bool isBufferLatched() const { return mRefreshPending; }
 
     bool isPotentialCursor() const { return mPotentialCursor;}
 
     /*
-     * called with the state lock when the surface is removed from the
-     * current list
+     * called with the state lock from a binder thread when the layer is
+     * removed from the current list to the pending removal list
+     */
+    void onRemovedFromCurrentState();
+
+    /*
+     * called with the state lock from the main thread when the layer is
+     * removed from the pending removal list
      */
     void onRemoved();
 
@@ -438,37 +450,21 @@
 #ifdef USE_HWC2
     // -----------------------------------------------------------------------
 
+    bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
+    void destroyHwcLayer(int32_t hwcId);
+    void destroyAllHwcLayers();
+
     bool hasHwcLayer(int32_t hwcId) {
-        if (mHwcLayers.count(hwcId) == 0) {
-            return false;
-        }
-        if (mHwcLayers[hwcId].layer->isAbandoned()) {
-            ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
-            mHwcLayers.erase(hwcId);
-            return false;
-        }
-        return true;
+        return mHwcLayers.count(hwcId) > 0;
     }
 
-    std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) {
+    HWC2::Layer* getHwcLayer(int32_t hwcId) {
         if (mHwcLayers.count(hwcId) == 0) {
             return nullptr;
         }
         return mHwcLayers[hwcId].layer;
     }
 
-    void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
-        if (layer) {
-            mHwcLayers[hwcId].layer = layer;
-        } else {
-            mHwcLayers.erase(hwcId);
-        }
-    }
-
-    void clearHwcLayers() {
-        mHwcLayers.clear();
-    }
-
 #endif
     // -----------------------------------------------------------------------
 
@@ -698,8 +694,11 @@
     uint32_t mTextureName;      // from GLES
     bool mPremultipliedAlpha;
     String8 mName;
+    String8 mTransactionName; // A cached version of "TX - " + mName for systraces
     PixelFormat mFormat;
 
+    bool mPrimaryDisplayOnly = false;
+
     // these are protected by an external lock
     State mCurrentState;
     State mDrawingState;
@@ -751,12 +750,14 @@
     // HWC items, accessed from the main thread
     struct HWCInfo {
         HWCInfo()
-          : layer(),
+          : hwc(nullptr),
+            layer(nullptr),
             forceClientComposition(false),
             compositionType(HWC2::Composition::Invalid),
             clearClientTarget(false) {}
 
-        std::shared_ptr<HWC2::Layer> layer;
+        HWComposer* hwc;
+        HWC2::Layer* layer;
         bool forceClientComposition;
         HWC2::Composition compositionType;
         bool clearClientTarget;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 6e37b45..e864607 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -17,6 +17,7 @@
 #include "LayerRejecter.h"
 
 #include <gui/BufferItem.h>
+#include <system/window.h>
 
 #include "clz.h"
 
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index bca3430..0b1199c 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -91,6 +91,14 @@
 
 void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
 {
+    if (mEventThread == eventThread) {
+        return;
+    }
+
+    if (mEventTube.getFd() >= 0) {
+        mLooper->removeFd(mEventTube.getFd());
+    }
+
     mEventThread = eventThread;
     mEvents = eventThread->createEventConnection();
     mEvents->stealReceiveChannel(&mEventTube);
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 85a33c8..14f50bb 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -30,6 +30,8 @@
 
 #include "Barrier.h"
 
+#include <functional>
+
 namespace android {
 
 class IDisplayEventConnection;
@@ -58,6 +60,21 @@
     mutable Barrier barrier;
 };
 
+class LambdaMessage : public MessageBase {
+public:
+    explicit LambdaMessage(std::function<void()> handler)
+          : MessageBase(), mHandler(std::move(handler)) {}
+
+    bool handler() override {
+        mHandler();
+        // This return value is no longer checked, so it's always safe to return true
+        return true;
+    }
+
+private:
+    const std::function<void()> mHandler;
+};
+
 // ---------------------------------------------------------------------------
 
 class MessageQueue {
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 2ba1b33..1a5a85e 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -68,11 +68,11 @@
     return mProducer->setAsyncMode(async);
 }
 
-status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
-    return mProducer->dequeueBuffer(
-            slot, fence, w, h, format, usage, outTimestamps);
+status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                          PixelFormat format, uint64_t usage,
+                                          uint64_t* outBufferAge,
+                                          FrameEventHistoryDelta* outTimestamps) {
+    return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
 }
 
 status_t MonitoredProducer::detachBuffer(int slot) {
@@ -116,7 +116,7 @@
 }
 
 void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage) {
+        PixelFormat format, uint64_t usage) {
     mProducer->allocateBuffers(width, height, format, usage);
 }
 
@@ -158,6 +158,10 @@
     return mProducer->getUniqueId(outId);
 }
 
+status_t MonitoredProducer::getConsumerUsage(uint64_t* outUsage) const {
+    return mProducer->getConsumerUsage(outUsage);
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return this;
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index a3ec29d..1246d14 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -39,9 +39,9 @@
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
-            FrameEventHistoryDelta* outTimestamps);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
@@ -56,7 +56,7 @@
     virtual status_t disconnect(int api, DisconnectMode mode);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
@@ -68,6 +68,7 @@
     virtual status_t setAutoRefresh(bool autoRefresh) override;
     virtual void getFrameTimestamps(FrameEventHistoryDelta *outDelta) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
+    virtual status_t getConsumerUsage(uint64_t* outUsage) const 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/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 0dab872..effd319 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -26,8 +26,7 @@
 
 namespace android {
 
-Description::Description() :
-    mUniformsDirty(true) {
+Description::Description() {
     mPlaneAlpha = 1.0f;
     mPremultipliedAlpha = false;
     mOpaque = true;
@@ -41,28 +40,20 @@
 }
 
 void Description::setPlaneAlpha(GLclampf planeAlpha) {
-    if (planeAlpha != mPlaneAlpha) {
-        mUniformsDirty = true;
-        mPlaneAlpha = planeAlpha;
-    }
+    mPlaneAlpha = planeAlpha;
 }
 
 void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
-    if (premultipliedAlpha != mPremultipliedAlpha) {
-        mPremultipliedAlpha = premultipliedAlpha;
-    }
+    mPremultipliedAlpha = premultipliedAlpha;
 }
 
 void Description::setOpaque(bool opaque) {
-    if (opaque != mOpaque) {
-        mOpaque = opaque;
-    }
+    mOpaque = opaque;
 }
 
 void Description::setTexture(const Texture& texture) {
     mTexture = texture;
     mTextureEnabled = true;
-    mUniformsDirty = true;
 }
 
 void Description::disableTexture() {
@@ -74,12 +65,10 @@
     mColor[1] = green;
     mColor[2] = blue;
     mColor[3] = alpha;
-    mUniformsDirty = true;
 }
 
 void Description::setProjectionMatrix(const mat4& mtx) {
     mProjectionMatrix = mtx;
-    mUniformsDirty = true;
 }
 
 void Description::setColorMatrix(const mat4& mtx) {
@@ -92,5 +81,8 @@
     return mColorMatrix;
 }
 
+void Description::setWideGamut(bool wideGamut) {
+    mIsWideGamut = wideGamut;
+}
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 8a3447c..3beffdf 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -54,6 +54,8 @@
     bool mColorMatrixEnabled;
     mat4 mColorMatrix;
 
+    bool mIsWideGamut;
+
 public:
     Description();
     ~Description();
@@ -67,9 +69,7 @@
     void setProjectionMatrix(const mat4& mtx);
     void setColorMatrix(const mat4& mtx);
     const mat4& getColorMatrix() const;
-
-private:
-    bool mUniformsDirty;
+    void setWideGamut(bool wideGamut);
 };
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 04fe182..37a530b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -40,9 +40,7 @@
 #include "Mesh.h"
 #include "Texture.h"
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
+#include <sstream>
 #include <fstream>
 
 // ---------------------------------------------------------------------------
@@ -111,8 +109,10 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-GLES20RenderEngine::GLES20RenderEngine() :
-        mVpWidth(0), mVpHeight(0) {
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) :
+         mVpWidth(0),
+         mVpHeight(0),
+         mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -133,23 +133,16 @@
     //mColorBlindnessCorrection = M;
 
 #ifdef USE_HWC2
-    // retrieve wide-color and hdr settings from configstore
-    using namespace android::hardware::configstore;
-    using namespace android::hardware::configstore::V1_0;
-
-    mPlatformHasWideColor =
-            getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
     if (mPlatformHasWideColor) {
         // Compute sRGB to DisplayP3 color transform
         // NOTE: For now, we are limiting wide-color support to
         // Display-P3 only.
-        mat3 srgbToP3 = ColorSpace::DisplayP3().getXYZtoRGB() * ColorSpace::sRGB().getRGBtoXYZ();
+        mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
 
-        // color transform needs to be transposed and expanded to 4x4
-        // to be what the shader wants
+        // color transform needs to be expanded to 4x4 to be what the shader wants
         // mat has an initializer that expands mat3 to mat4, but
         // not an assignment operator
-        mat4 gamutTransform(transpose(srgbToP3));
+        mat4 gamutTransform(srgbToP3);
         mSrgbToDisplayP3 = gamutTransform;
     }
 #endif
@@ -392,6 +385,7 @@
         Description wideColorState = mState;
         if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
             wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+            wideColorState.setWideGamut(true);
             ALOGV("drawMesh: gamut transform applied");
         }
         ProgramCache::getInstance().useProgram(wideColorState);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 19cbb60..eaf94af 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -59,7 +59,7 @@
     virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
 
 public:
-    GLES20RenderEngine();
+    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
 
 protected:
     virtual ~GLES20RenderEngine();
@@ -86,7 +86,6 @@
     android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
 
     // Indicate if wide-color mode is needed or not
-    bool mPlatformHasWideColor = false;
     bool mDisplayHasWideColor = false;
     bool mUseWideColor = false;
     uint64_t mWideColorFrameCount = 0;
@@ -98,6 +97,8 @@
             int alpha);
     virtual void setupDimLayerBlending(int alpha);
 #endif
+    bool mPlatformHasWideColor = false;
+
     virtual void setupLayerTexturing(const Texture& texture);
     virtual void setupLayerBlackedOut();
     virtual void setupFillWithColor(float r, float g, float b, float a);
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index ba11259..06b2252 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -129,7 +129,9 @@
     .set(Key::OPACITY_MASK,
             description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
     .set(Key::COLOR_MATRIX_MASK,
-            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF);
+            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF)
+    .set(Key::WIDE_GAMUT_MASK,
+            description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
     return needs;
 }
 
@@ -175,6 +177,50 @@
     if (needs.hasColorMatrix()) {
         fs << "uniform mat4 colorMatrix;";
     }
+    if (needs.hasColorMatrix()) {
+        // When in wide gamut mode, the color matrix will contain a color space
+        // conversion matrix that needs to be applied in linear space
+        // When not in wide gamut, we can simply no-op the transfer functions
+        // and let the shader compiler get rid of them
+        if (needs.isWideGamut()) {
+            fs << R"__SHADER__(
+                  float OETF_sRGB(const float linear) {
+                      return linear <= 0.0031308 ?
+                              linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+                  }
+
+                  vec3 OETF_sRGB(const vec3 linear) {
+                      return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+                  }
+
+                  vec3 OETF_scRGB(const vec3 linear) {
+                      return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+                  }
+
+                  float EOTF_sRGB(float srgb) {
+                      return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+                  }
+
+                  vec3 EOTF_sRGB(const vec3 srgb) {
+                      return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+                  }
+
+                  vec3 EOTF_scRGB(const vec3 srgb) {
+                      return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+                  }
+            )__SHADER__";
+        } else {
+            fs << R"__SHADER__(
+                  vec3 OETF_scRGB(const vec3 linear) {
+                      return linear;
+                  }
+
+                  vec3 EOTF_scRGB(const vec3 srgb) {
+                      return srgb;
+                  }
+            )__SHADER__";
+        }
+    }
     fs << "void main(void) {" << indent;
     if (needs.isTexturing()) {
         fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
@@ -197,13 +243,15 @@
     if (needs.hasColorMatrix()) {
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // un-premultiply if needed before linearization
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
+            // avoid divide by 0 by adding 0.5/256 to the alpha channel
+            fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
         }
-        fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
-        fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
+        fs << "vec4 transformed = colorMatrix * vec4(EOTF_scRGB(gl_FragColor.rgb), 1);";
+        // We assume the last row is always {0,0,0,1} and we skip the division by w
+        fs << "gl_FragColor.rgb = OETF_scRGB(transformed.rgb);";
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // and re-premultiply if needed after gamma correction
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
+            fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
         }
     }
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 1fa53d3..5b0fbcd 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -69,6 +69,10 @@
             COLOR_MATRIX_OFF        =       0x00000000,
             COLOR_MATRIX_ON         =       0x00000020,
             COLOR_MATRIX_MASK       =       0x00000020,
+
+            WIDE_GAMUT_OFF          =       0x00000000,
+            WIDE_GAMUT_ON           =       0x00000040,
+            WIDE_GAMUT_MASK         =       0x00000040,
         };
 
         inline Key() : mKey(0) { }
@@ -97,10 +101,13 @@
         inline bool hasColorMatrix() const {
             return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
         }
+        inline bool isWideGamut() const {
+            return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
+        }
 
         // this is the definition of a friend function -- not a method of class Needs
         friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
-            return  (lhs.mKey < rhs.mKey) ? 1 : 0;
+            return (lhs.mKey < rhs.mKey) ? 1 : 0;
         }
     };
 
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 7564269..56e9ac0 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -26,7 +26,7 @@
 #include <vector>
 #include <SurfaceFlinger.h>
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -47,20 +47,24 @@
     return false;
 }
 
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
+RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t featureFlags) {
     // EGL_ANDROIDX_no_config_context is an experimental extension with no
     // written specification. It will be replaced by something more formal.
     // SurfaceFlinger is using it to allow a single EGLContext to render to
     // both a 16-bit primary display framebuffer and a 32-bit virtual display
     // framebuffer.
     //
+    // EGL_KHR_no_config_context is official extension to allow creating a
+    // context that works with any surface of a display.
+    //
     // The code assumes that ES2 or later is available if this extension is
     // supported.
     EGLConfig config = EGL_NO_CONFIG;
-    if (!findExtension(
-            eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
-            "EGL_ANDROIDX_no_config_context")) {
-        config = chooseEglConfig(display, hwcFormat);
+    if (!findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+                       "EGL_ANDROIDX_no_config_context") &&
+        !findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+                       "EGL_KHR_no_config_context")) {
+        config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
     }
 
     EGLint renderableType = 0;
@@ -104,7 +108,7 @@
 
     EGLConfig dummyConfig = config;
     if (dummyConfig == EGL_NO_CONFIG) {
-        dummyConfig = chooseEglConfig(display, hwcFormat);
+        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
     }
     EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
     EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
@@ -131,7 +135,7 @@
         break;
     case GLES_VERSION_2_0:
     case GLES_VERSION_3_0:
-        engine = new GLES20RenderEngine();
+        engine = new GLES20RenderEngine(featureFlags);
         break;
     }
     engine->setEGLHandles(config, ctxt);
@@ -402,7 +406,8 @@
     return err;
 }
 
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
+                                        bool logConfig) {
     status_t err;
     EGLConfig config;
 
@@ -423,18 +428,20 @@
         }
     }
 
-    // print some debugging info
-    EGLint r,g,b,a;
-    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
-    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
-    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
-    ALOGI("EGL information:");
-    ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-    ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-    ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
-    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+    if (logConfig) {
+        // print some debugging info
+        EGLint r,g,b,a;
+        eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
+        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
+        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+        ALOGI("EGL information:");
+        ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+        ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+        ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+        ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+    }
 
     return config;
 }
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8b031bc..9544579 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -59,9 +59,12 @@
     virtual ~RenderEngine() = 0;
 
 public:
-    static RenderEngine* create(EGLDisplay display, int hwcFormat);
+    enum FeatureFlag {
+        WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
+    };
+    static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
 
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format);
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
     void primeCache() const;
 
diff --git a/services/surfaceflinger/StartBootAnimThread.cpp b/services/surfaceflinger/StartBootAnimThread.cpp
deleted file mode 100644
index c3f7296..0000000
--- a/services/surfaceflinger/StartBootAnimThread.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cutils/properties.h>
-#include "StartBootAnimThread.h"
-
-namespace android {
-
-StartBootAnimThread::StartBootAnimThread():
-        Thread(false) {
-}
-
-status_t StartBootAnimThread::Start() {
-    return run("SurfaceFlinger::StartBootAnimThread", PRIORITY_NORMAL);
-}
-
-bool StartBootAnimThread::threadLoop() {
-    property_set("service.bootanim.exit", "0");
-    property_set("ctl.start", "bootanim");
-    // Exit immediately
-    return false;
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/StartPropertySetThread.cpp b/services/surfaceflinger/StartPropertySetThread.cpp
new file mode 100644
index 0000000..db82772
--- /dev/null
+++ b/services/surfaceflinger/StartPropertySetThread.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/properties.h>
+#include "StartPropertySetThread.h"
+
+namespace android {
+
+StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
+        Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}
+
+status_t StartPropertySetThread::Start() {
+    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
+}
+
+bool StartPropertySetThread::threadLoop() {
+    // Set property service.sf.present_timestamp, consumer need check its readiness
+    property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
+    // Clear BootAnimation exit flag
+    property_set("service.bootanim.exit", "0");
+    // Start BootAnimation if not started
+    property_set("ctl.start", "bootanim");
+    // Exit immediately
+    return false;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/StartBootAnimThread.h b/services/surfaceflinger/StartPropertySetThread.h
similarity index 78%
rename from services/surfaceflinger/StartBootAnimThread.h
rename to services/surfaceflinger/StartPropertySetThread.h
index dba2bee..a64c21b 100644
--- a/services/surfaceflinger/StartBootAnimThread.h
+++ b/services/surfaceflinger/StartPropertySetThread.h
@@ -24,17 +24,21 @@
 
 namespace android {
 
-class StartBootAnimThread : public Thread {
+class StartPropertySetThread : public Thread {
 // Boot animation is triggered via calls to "property_set()" which can block
 // if init's executing slow operation such as 'mount_all --late' (currently
 // happening 1/10th with fsck)  concurrently. Running in a separate thread
 // allows to pursue the SurfaceFlinger's init process without blocking.
 // see b/34499826.
+// Any property_set() will block during init stage so need to be offloaded
+// to this thread. see b/63844978.
 public:
-    StartBootAnimThread();
+    StartPropertySetThread(bool timestampPropertyValue);
     status_t Start();
 private:
     virtual bool threadLoop();
+    static constexpr const char* kTimestampProperty = "service.sf.present_timestamp";
+    const bool mTimestampPropertyValue;
 };
 
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 29e7bd6..4055693 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -19,12 +19,14 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <algorithm>
 #include <errno.h>
 #include <math.h>
 #include <mutex>
 #include <dlfcn.h>
 #include <inttypes.h>
 #include <stdatomic.h>
+#include <optional>
 
 #include <EGL/egl.h>
 
@@ -74,6 +76,7 @@
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 
+#include "DisplayHardware/ComposerHal.h"
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
@@ -94,14 +97,28 @@
  */
 #define DEBUG_SCREENSHOTS   false
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 namespace android {
 
-
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 
+namespace {
+class ConditionalLock {
+public:
+    ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
+        if (lock) {
+            mMutex.lock();
+        }
+    }
+    ~ConditionalLock() { if (mLocked) mMutex.unlock(); }
+private:
+    Mutex& mMutex;
+    bool mLocked;
+};
+}  // namespace anonymous
+
 // ---------------------------------------------------------------------------
 
 const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -129,9 +146,6 @@
         mLayersRemoved(false),
         mLayersAdded(false),
         mRepaintEverything(0),
-        mHwc(nullptr),
-        mRealHwc(nullptr),
-        mVrHwc(nullptr),
         mRenderEngine(nullptr),
         mBootTime(systemTime()),
         mBuiltinDisplays(),
@@ -158,7 +172,9 @@
         mTotalTime(0),
         mLastSwapTime(0),
         mNumLayers(0),
-        mVrFlingerRequestsDisplay(false)
+        mVrFlingerRequestsDisplay(false),
+        mMainThreadId(std::this_thread::get_id()),
+        mComposerSequenceId(0)
 {
     ALOGI("SurfaceFlinger is starting");
 
@@ -193,6 +209,8 @@
     hasWideColorDisplay =
             getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
 
+    mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset);
+
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
 
@@ -224,6 +242,11 @@
     property_get("ro.sf.disable_triple_buffer", value, "1");
     mLayerTripleBufferingDisabled = atoi(value);
     ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
+
+    // We should be reading 'persist.sys.sf.color_saturation' here
+    // but since /data may be encrypted, we need to wait until after vold
+    // comes online to attempt to read the property. The property is
+    // instead read after the boot animation
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -341,13 +364,12 @@
 
 void SurfaceFlinger::bootFinished()
 {
-    if (mStartBootAnimThread->join() != NO_ERROR) {
-        ALOGE("Join StartBootAnimThread failed!");
+    if (mStartPropertySetThread->join() != NO_ERROR) {
+        ALOGE("Join StartPropertySetThread failed!");
     }
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-    mBootFinished = true;
 
     // wait patiently for the window manager death
     const String16 name("window");
@@ -368,6 +390,11 @@
     const int LOGTAG_SF_STOP_BOOTANIM = 60110;
     LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                    ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+
+    sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
+        readPersistentProperties();
+    });
+    postMessageAsync(readProperties);
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -515,7 +542,9 @@
 
     virtual void onInjectSyncEvent(nsecs_t when) {
         std::lock_guard<std::mutex> lock(mCallbackMutex);
-        mCallback->onVSyncEvent(when);
+        if (mCallback != nullptr) {
+            mCallback->onVSyncEvent(when);
+        }
     }
 
     virtual void setVSyncEnabled(bool) {}
@@ -526,74 +555,43 @@
     sp<VSyncSource::Callback> mCallback;
 };
 
+// Do not call property_set on main thread which will be blocked by init
+// Use StartPropertySetThread instead.
 void SurfaceFlinger::init() {
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
     ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
 
-    { // Autolock scope
-        Mutex::Autolock _l(mStateLock);
-
-        // initialize EGL for the default display
-        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        eglInitialize(mEGLDisplay, NULL, NULL);
-
-        // start the EventThread
-        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-                vsyncPhaseOffsetNs, true, "app");
-        mEventThread = new EventThread(vsyncSrc, *this, false);
-        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-                sfVsyncPhaseOffsetNs, true, "sf");
-        mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
-        mEventQueue.setEventThread(mSFEventThread);
-
-        // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
-        struct sched_param param = {0};
-        param.sched_priority = 2;
-        if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-            ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
-        }
-        if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-            ALOGE("Couldn't set SCHED_FIFO for EventThread");
-        }
-
-        // Get a RenderEngine for the given display / config (can't fail)
-        mRenderEngine = RenderEngine::create(mEGLDisplay,
-                HAL_PIXEL_FORMAT_RGBA_8888);
-    }
-
-    // Drop the state lock while we initialize the hardware composer. We drop
-    // the lock because on creation, it will call back into SurfaceFlinger to
-    // initialize the primary display.
-    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
-        "Starting with vr flinger active is not currently supported.");
-    mRealHwc = new HWComposer(false);
-    mHwc = mRealHwc;
-    mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-
     Mutex::Autolock _l(mStateLock);
 
-    // Inform native graphics APIs whether the present timestamp is supported:
-    if (getHwComposer().hasCapability(
-            HWC2::Capability::PresentFenceIsNotReliable)) {
-        property_set(kTimestampProperty, "0");
-    } else {
-        property_set(kTimestampProperty, "1");
+    // initialize EGL for the default display
+    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(mEGLDisplay, NULL, NULL);
+
+    // start the EventThread
+    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            vsyncPhaseOffsetNs, true, "app");
+    mEventThread = new EventThread(vsyncSrc, *this, false);
+    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            sfVsyncPhaseOffsetNs, true, "sf");
+    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
+    mEventQueue.setEventThread(mSFEventThread);
+
+    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
+    }
+    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for EventThread");
     }
 
-    if (useVrFlinger) {
-        auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
-            ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
-            mVrFlingerRequestsDisplay = requestDisplay;
-            signalTransaction();
-        };
-        mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
-                                            vrFlingerRequestDisplayCallback);
-        if (!mVrFlinger) {
-            ALOGE("Failed to start vrflinger");
-        }
-    }
+    // Get a RenderEngine for the given display / config (can't fail)
+    mRenderEngine = RenderEngine::create(mEGLDisplay,
+            HAL_PIXEL_FORMAT_RGBA_8888,
+            hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
 
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
@@ -601,9 +599,32 @@
     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
             "couldn't create EGLContext");
 
-    // make the GLContext current so that we can create textures when creating
-    // Layers (which may happens before we render something)
-    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
+    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
+            "Starting with vr flinger active is not currently supported.");
+    mHwc.reset(new HWComposer(false));
+    mHwc->registerCallback(this, mComposerSequenceId);
+
+    if (useVrFlinger) {
+        auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
+            // This callback is called from the vr flinger dispatch thread. We
+            // need to call signalTransaction(), which requires holding
+            // mStateLock when we're not on the main thread. Acquiring
+            // mStateLock from the vr flinger dispatch thread might trigger a
+            // deadlock in surface flinger (see b/66916578), so post a message
+            // to be handled on the main thread instead.
+            sp<LambdaMessage> message = new LambdaMessage([=]() {
+                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
+                mVrFlingerRequestsDisplay = requestDisplay;
+                signalTransaction();
+            });
+            postMessageAsync(message);
+        };
+        mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
+                                            vrFlingerRequestDisplayCallback);
+        if (!mVrFlinger) {
+            ALOGE("Failed to start vrflinger");
+        }
+    }
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -616,21 +637,42 @@
 
     mRenderEngine->primeCache();
 
-    mStartBootAnimThread = new StartBootAnimThread();
-    if (mStartBootAnimThread->Start() != NO_ERROR) {
-        ALOGE("Run StartBootAnimThread failed!");
+    // Inform native graphics APIs whether the present timestamp is supported:
+    if (getHwComposer().hasCapability(
+            HWC2::Capability::PresentFenceIsNotReliable)) {
+        mStartPropertySetThread = new StartPropertySetThread(false);
+    } else {
+        mStartPropertySetThread = new StartPropertySetThread(true);
+    }
+
+    if (mStartPropertySetThread->Start() != NO_ERROR) {
+        ALOGE("Run StartPropertySetThread failed!");
     }
 
     ALOGV("Done initializing");
 }
 
+void SurfaceFlinger::readPersistentProperties() {
+    char value[PROPERTY_VALUE_MAX];
+
+    property_get("persist.sys.sf.color_saturation", value, "1.0");
+    mSaturation = atof(value);
+    ALOGV("Saturation is set to %.2f", mSaturation);
+
+    property_get("persist.sys.sf.native_mode", value, "0");
+    mForceNativeColorMode = atoi(value) == 1;
+    if (mForceNativeColorMode) {
+        ALOGV("Forcing native color mode");
+    }
+}
+
 void SurfaceFlinger::startBootAnim() {
     // Start boot animation service by setting a property mailbox
     // if property setting thread is already running, Start() will be just a NOP
-    mStartBootAnimThread->Start();
+    mStartPropertySetThread->Start();
     // Wait until property was set
-    if (mStartBootAnimThread->join() != NO_ERROR) {
-        ALOGE("Join StartBootAnimThread failed!");
+    if (mStartPropertySetThread->join() != NO_ERROR) {
+        ALOGE("Join StartPropertySetThread failed!");
     }
 }
 
@@ -668,6 +710,8 @@
         FrameEvent::DEQUEUE_READY,
         FrameEvent::RELEASE,
     };
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
     if (!getHwComposer().hasCapability(
             HWC2::Capability::PresentFenceIsNotReliable)) {
         outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
@@ -715,6 +759,8 @@
 
     configs->clear();
 
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
     for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
         DisplayInfo info = DisplayInfo();
 
@@ -738,7 +784,7 @@
             info.density = density;
 
             // TODO: this needs to go away (currently needed only by webkit)
-            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+            sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
             info.orientation = hw->getOrientation();
         } else {
             // TODO: where should this value come from?
@@ -881,7 +927,12 @@
         return type;
     }
 
-    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+    std::vector<android_color_mode_t> modes;
+    {
+        ConditionalLock _l(mStateLock,
+                std::this_thread::get_id() != mMainThreadId);
+        modes = getHwComposer().getColorModes(type);
+    }
     outColorModes->clear();
     std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
 
@@ -988,13 +1039,14 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
-    if (enable == mInjectVSyncs) {
-        return NO_ERROR;
+void SurfaceFlinger::enableVSyncInjectionsInternal(bool enable) {
+    Mutex::Autolock _l(mStateLock);
+
+    if (mInjectVSyncs == enable) {
+        return;
     }
 
     if (enable) {
-        mInjectVSyncs = enable;
         ALOGV("VSync Injections enabled");
         if (mVSyncInjector.get() == nullptr) {
             mVSyncInjector = new InjectVSyncSource();
@@ -1002,15 +1054,33 @@
         }
         mEventQueue.setEventThread(mInjectorEventThread);
     } else {
-        mInjectVSyncs = enable;
         ALOGV("VSync Injections disabled");
         mEventQueue.setEventThread(mSFEventThread);
-        mVSyncInjector.clear();
     }
+
+    mInjectVSyncs = enable;
+}
+
+status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
+    class MessageEnableVSyncInjections : public MessageBase {
+        SurfaceFlinger* mFlinger;
+        bool mEnable;
+    public:
+        MessageEnableVSyncInjections(SurfaceFlinger* flinger, bool enable)
+            : mFlinger(flinger), mEnable(enable) { }
+        virtual bool handler() {
+            mFlinger->enableVSyncInjectionsInternal(mEnable);
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageEnableVSyncInjections(this, enable);
+    postMessageSync(msg);
     return NO_ERROR;
 }
 
 status_t SurfaceFlinger::injectVSync(nsecs_t when) {
+    Mutex::Autolock _l(mStateLock);
+
     if (!mInjectVSyncs) {
         ALOGE("VSync Injections not enabled");
         return BAD_VALUE;
@@ -1048,6 +1118,7 @@
 }
 
 void SurfaceFlinger::signalRefresh() {
+    mRefreshPending = true;
     mEventQueue.refresh();
 }
 
@@ -1131,11 +1202,16 @@
     sLastResyncAttempted = now;
 }
 
-void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
-                                     nsecs_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
+        hwc2_display_t displayId, int64_t timestamp) {
     Mutex::Autolock lock(mStateLock);
-    // Ignore any vsyncs from the non-active hardware composer.
-    if (composer != mHwc) {
+    // Ignore any vsyncs from a previous hardware composer.
+    if (sequenceId != mComposerSequenceId) {
+        return;
+    }
+
+    int32_t type;
+    if (!mHwc->onVsync(displayId, timestamp, &type)) {
         return;
     }
 
@@ -1143,7 +1219,7 @@
 
     { // Scope for the lock
         Mutex::Autolock _l(mHWVsyncLock);
-        if (type == 0 && mPrimaryHWVsyncEnabled) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
             needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
         }
     }
@@ -1161,7 +1237,7 @@
 }
 
 void SurfaceFlinger::createDefaultDisplayDevice() {
-    const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+    const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY;
     wp<IBinder> token = mBuiltinDisplays[type];
 
     // All non-virtual displays are currently considered secure.
@@ -1186,37 +1262,60 @@
                 break;
         }
     }
+    bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode;
     sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
                                              token, fbs, producer, mRenderEngine->getEGLConfig(),
-                                             hasWideColorModes && hasWideColorDisplay);
+                                             useWideColorMode);
     mDisplays.add(token, hw);
     android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
-    if (hasWideColorModes && hasWideColorDisplay) {
+    if (useWideColorMode) {
         defaultColorMode = HAL_COLOR_MODE_SRGB;
     }
     setActiveColorModeInternal(hw, defaultColorMode);
+    hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+
+    // Add the primary display token to mDrawingState so we don't try to
+    // recreate the DisplayDevice for the primary display.
+    mDrawingState.displays.add(token, DisplayDeviceState(type, true));
+
+    // make the GLContext current so that we can create textures when creating
+    // Layers (which may happens before we render something)
+    hw->makeCurrent(mEGLDisplay, mEGLContext);
 }
 
-void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
-    ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
+        hwc2_display_t display, HWC2::Connection connection,
+        bool primaryDisplay) {
+    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
+          sequenceId, display,
+          connection == HWC2::Connection::Connected ?
+                  "connected" : "disconnected",
+          primaryDisplay ? "primary" : "external");
 
-    if (composer->isUsingVrComposer()) {
-        // We handle initializing the primary display device for the VR
-        // window manager hwc explicitly at the time of transition.
-        if (disp != DisplayDevice::DISPLAY_PRIMARY) {
-            ALOGE("External displays are not supported by the vr hardware composer.");
+    // Only lock if we're not on the main thread. This function is normally
+    // called on a hwbinder thread, but for the primary display it's called on
+    // the main thread with the state lock already held, so don't attempt to
+    // acquire it here.
+    ConditionalLock lock(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
+
+    if (primaryDisplay) {
+        mHwc->onHotplug(display, connection);
+        if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) {
+            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
         }
-        return;
-    }
-
-    if (disp == DisplayDevice::DISPLAY_PRIMARY) {
-        Mutex::Autolock lock(mStateLock);
-        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
         createDefaultDisplayDevice();
     } else {
+        if (sequenceId != mComposerSequenceId) {
+            return;
+        }
+        if (mHwc->isUsingVrComposer()) {
+            ALOGE("External displays are not supported by the vr hardware composer.");
+            return;
+        }
+        mHwc->onHotplug(display, connection);
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
-        Mutex::Autolock _l(mStateLock);
-        if (connected) {
+        if (connection == HWC2::Connection::Connected) {
             createBuiltinDisplayLocked(type);
         } else {
             mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
@@ -1228,49 +1327,31 @@
     }
 }
 
-void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId,
+                                       hwc2_display_t /*display*/) {
     Mutex::Autolock lock(mStateLock);
-    if (composer == mHwc) {
-        repaintEverything();
-    } else {
-        // This isn't from our current hardware composer. If it's a callback
-        // from the real composer, forward the refresh request to vr
-        // flinger. Otherwise ignore it.
-        if (!composer->isUsingVrComposer()) {
-            mVrFlinger->OnHardwareComposerRefresh();
-        }
+    if (sequenceId != mComposerSequenceId) {
+        return;
     }
+    repaintEverythingLocked();
 }
 
 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
     ATRACE_CALL();
+    Mutex::Autolock lock(mStateLock);
     getHwComposer().setVsyncEnabled(disp,
             enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
 }
 
-void SurfaceFlinger::clearHwcLayers(const LayerVector& layers) {
-    for (size_t i = 0; i < layers.size(); ++i) {
-        layers[i]->clearHwcLayers();
-    }
-}
-
 // Note: it is assumed the caller holds |mStateLock| when this is called
-void SurfaceFlinger::resetHwcLocked() {
+void SurfaceFlinger::resetDisplayState() {
     disableHardwareVsync(true);
-    clearHwcLayers(mDrawingState.layersSortedByZ);
-    clearHwcLayers(mCurrentState.layersSortedByZ);
     // Clear the drawing state so that the logic inside of
     // handleTransactionLocked will fire. It will determine the delta between
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
-    // Release virtual display hwcId during vr mode transition.
-    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
-        const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
-        if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
-            displayDevice->disconnect(getHwComposer());
-        }
-    }
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     mDisplays.clear();
 }
 
@@ -1282,46 +1363,52 @@
         return;
     }
 
-    if (vrFlingerRequestsDisplay && !mVrHwc) {
-        // Construct new HWComposer without holding any locks.
-        mVrHwc = new HWComposer(true);
-
-        // Set up the event handlers. This step is neccessary to initialize the internal state of
-        // the hardware composer object properly. Our callbacks are designed such that if they are
-        // triggered between now and the point where the display is properly re-initialized, they
-        // will not have any effect, so this is safe to do here, before the lock is aquired.
-        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-        ALOGV("Vr HWC created");
+    if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) {
+        ALOGE("Vr flinger is only supported for remote hardware composer"
+              " service connections. Ignoring request to transition to vr"
+              " flinger.");
+        mVrFlingerRequestsDisplay = false;
+        return;
     }
 
     Mutex::Autolock _l(mStateLock);
 
-    if (vrFlingerRequestsDisplay) {
-        resetHwcLocked();
+    int currentDisplayPowerMode = getDisplayDeviceLocked(
+            mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode();
 
-        mHwc = mVrHwc;
-        mVrFlinger->GrantDisplayOwnership();
-
-    } else {
+    if (!vrFlingerRequestsDisplay) {
         mVrFlinger->SeizeDisplayOwnership();
+    }
 
-        resetHwcLocked();
+    resetDisplayState();
+    mHwc.reset();  // Delete the current instance before creating the new one
+    mHwc.reset(new HWComposer(vrFlingerRequestsDisplay));
+    mHwc->registerCallback(this, ++mComposerSequenceId);
 
-        mHwc = mRealHwc;
+    LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(),
+            "Switched to non-remote hardware composer");
+
+    if (vrFlingerRequestsDisplay) {
+        mVrFlinger->GrantDisplayOwnership();
+    } else {
         enableHardwareVsync();
     }
 
     mVisibleRegionsDirty = true;
     invalidateHwcGeometry();
 
-    // Explicitly re-initialize the primary display. This is because some other
-    // parts of this class rely on the primary display always being available.
-    createDefaultDisplayDevice();
+    // Re-enable default display.
+    sp<DisplayDevice> hw(getDisplayDeviceLocked(
+            mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
+    setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true);
 
     // Reset the timing values to account for the period of the swapped in HWC
     const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
     const nsecs_t period = activeConfig->getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(period);
+
+    // Use phase of 0 since phase is not known.
+    // Use latency of 0, which will snap to the ideal latency.
     setCompositorTimingSnapped(0, period, 0);
 
     android_atomic_or(1, &mRepaintEverything);
@@ -1338,7 +1425,6 @@
                             Fence::SIGNAL_TIME_PENDING);
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
             if (mPropagateBackpressure && frameMissed) {
-                ALOGD("Backpressure trigger, skipping transaction & refresh!");
                 signalLayerUpdate();
                 break;
             }
@@ -1383,6 +1469,8 @@
 void SurfaceFlinger::handleMessageRefresh() {
     ATRACE_CALL();
 
+    mRefreshPending = false;
+
     nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
 
     preComposition(refreshStartTime);
@@ -1538,6 +1626,7 @@
     // |mStateLock| not needed as we are on the main thread
     const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
+    mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
     if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
         glCompositionDoneFenceTime =
@@ -1546,12 +1635,11 @@
     } else {
         glCompositionDoneFenceTime = FenceTime::NO_FENCE;
     }
-    mGlCompositionDoneTimeline.updateSignalTimes();
 
+    mDisplayTimeline.updateSignalTimes();
     sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
     auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
     mDisplayTimeline.push(presentFenceTime);
-    mDisplayTimeline.updateSignalTimes();
 
     nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
     nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
@@ -1576,8 +1664,8 @@
         }
     });
 
-    if (presentFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+    if (presentFenceTime->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(presentFenceTime)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1644,12 +1732,11 @@
             const Transform& tr(displayDevice->getTransform());
             const Rect bounds(displayDevice->getBounds());
             if (displayDevice->isDisplayOn()) {
-                computeVisibleRegions(
-                        displayDevice->getLayerStack(), dirtyRegion,
-                        opaqueRegion);
+                computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
 
                 mDrawingState.traverseInZOrder([&](Layer* layer) {
-                    if (layer->getLayerStack() == displayDevice->getLayerStack()) {
+                    if (layer->belongsToDisplay(displayDevice->getLayerStack(),
+                                displayDevice->isPrimary())) {
                         Region drawRegion(tr.transform(
                                 layer->visibleNonTransparentRegion));
                         drawRegion.andSelf(bounds);
@@ -1658,15 +1745,14 @@
                         } else {
                             // Clear out the HWC layer if this layer was
                             // previously visible, but no longer is
-                            layer->setHwcLayer(displayDevice->getHwcDisplayId(),
-                                    nullptr);
+                            layer->destroyHwcLayer(
+                                    displayDevice->getHwcDisplayId());
                         }
                     } else {
                         // WM changes displayDevice->layerStack upon sleep/awake.
                         // Here we make sure we delete the HWC layers even if
                         // WM changed their layer stack.
-                        layer->setHwcLayer(displayDevice->getHwcDisplayId(),
-                                nullptr);
+                        layer->destroyHwcLayer(displayDevice->getHwcDisplayId());
                     }
                 });
             }
@@ -1679,9 +1765,29 @@
     }
 }
 
+mat4 SurfaceFlinger::computeSaturationMatrix() const {
+    if (mSaturation == 1.0f) {
+        return mat4();
+    }
+
+    // Rec.709 luma coefficients
+    float3 luminance{0.213f, 0.715f, 0.072f};
+    luminance *= 1.0f - mSaturation;
+    return mat4(
+        vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f},
+        vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f},
+        vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f},
+        vec4{0.0f, 0.0f, 0.0f, 1.0f}
+    );
+}
+
 // pickColorMode translates a given dataspace into the best available color mode.
 // Currently only support sRGB and Display-P3.
-android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
+    if (mForceNativeColorMode) {
+        return HAL_COLOR_MODE_NATIVE;
+    }
+
     switch (dataSpace) {
         // treat Unknown as regular SRGB buffer, since that's what the rest of the
         // system expects.
@@ -1704,11 +1810,19 @@
     }
 }
 
-android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+android_dataspace SurfaceFlinger::bestTargetDataSpace(
+        android_dataspace a, android_dataspace b) const {
     // Only support sRGB and Display-P3 right now.
     if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
         return HAL_DATASPACE_DISPLAY_P3;
     }
+    if (a == HAL_DATASPACE_V0_SCRGB_LINEAR || b == HAL_DATASPACE_V0_SCRGB_LINEAR) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+    if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+
     return HAL_DATASPACE_V0_SRGB;
 }
 
@@ -1757,10 +1871,7 @@
                 for (size_t i = 0; i < currentLayers.size(); i++) {
                     const auto& layer = currentLayers[i];
                     if (!layer->hasHwcLayer(hwcId)) {
-                        auto hwcLayer = mHwc->createLayer(hwcId);
-                        if (hwcLayer) {
-                            layer->setHwcLayer(hwcId, std::move(hwcLayer));
-                        } else {
+                        if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
                             layer->forceClientComposition(hwcId);
                             continue;
                         }
@@ -1776,7 +1887,7 @@
     }
 
 
-    mat4 colorMatrix = mColorMatrix * mDaltonizer();
+    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
 
     // Set the per-frame data
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
@@ -2041,7 +2152,7 @@
                         if (state.surface != NULL) {
 
                             // Allow VR composer to use virtual displays.
-                            if (mUseHwcVirtualDisplays || mHwc == mVrHwc) {
+                            if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) {
                                 int width = 0;
                                 int status = state.surface->query(
                                         NATIVE_WINDOW_WIDTH, &width);
@@ -2142,7 +2253,7 @@
                 disp.clear();
                 for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                     sp<const DisplayDevice> hw(mDisplays[dpy]);
-                    if (hw->getLayerStack() == currentlayerStack) {
+                    if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
                         if (disp == NULL) {
                             disp = hw;
                         } else {
@@ -2191,7 +2302,7 @@
                 // TODO: we could cache the transformed region
                 Region visibleReg;
                 visibleReg.set(layer->computeScreenBounds());
-                invalidateLayerStack(layer->getLayerStack(), visibleReg);
+                invalidateLayerStack(layer, visibleReg);
             }
         });
     }
@@ -2240,7 +2351,7 @@
     mTransactionCV.broadcast();
 }
 
-void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack,
+void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
         Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
@@ -2257,7 +2368,7 @@
         const Layer::State& s(layer->getDrawingState());
 
         // only consider the layers on the given layer stack
-        if (layer->getLayerStack() != layerStack)
+        if (!layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary()))
             return;
 
         /*
@@ -2372,11 +2483,10 @@
     outOpaqueRegion = aboveOpaqueLayers;
 }
 
-void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
-        const Region& dirty) {
+void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->getLayerStack() == layerStack) {
+        if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
             hw->dirtyRegion.orSelf(dirty);
         }
     }
@@ -2417,8 +2527,8 @@
     for (auto& layer : mLayersWithQueuedFrames) {
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
-        invalidateLayerStack(layer->getLayerStack(), dirty);
-        if (!dirty.isEmpty()) {
+        invalidateLayerStack(layer, dirty);
+        if (layer->isBufferLatched()) {
             newDataLatched = true;
         }
     }
@@ -2428,7 +2538,7 @@
     // If we will need to wake up at some time in the future to deal with a
     // queued frame that shouldn't be displayed during this vsync period, wake
     // up during the next vsync period to check again.
-    if (frameQueued && mLayersWithQueuedFrames.empty()) {
+    if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
         signalLayerUpdate();
     }
 
@@ -2512,8 +2622,10 @@
         ALOGV("hasClientComposition");
 
 #ifdef USE_HWC2
-        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
-        mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+        mRenderEngine->setWideColor(
+                displayDevice->getWideColorSupport() && !mForceNativeColorMode);
+        mRenderEngine->setColorMode(mForceNativeColorMode ?
+                HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode());
 #endif
         if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -2656,6 +2768,8 @@
     {
         Mutex::Autolock _l(mStateLock);
         if (mNumLayers >= MAX_LAYERS) {
+            ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
+                  MAX_LAYERS);
             return NO_MEMORY;
         }
         if (parent == nullptr) {
@@ -2717,6 +2831,7 @@
         return NO_ERROR;
     }
 
+    layer->onRemovedFromCurrentState();
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
     mNumLayers -= 1 + layer->getChildrenCount();
@@ -2792,10 +2907,12 @@
         }
     }
 
-    // If a synchronous transaction is explicitly requested without any changes,
-    // force a transaction anyway. This can be used as a flush mechanism for
-    // previous async transactions.
-    if (transactionFlags == 0 && (flags & eSynchronous)) {
+    // If a synchronous transaction is explicitly requested without any changes, force a transaction
+    // anyway. This can be used as a flush mechanism for previous async transactions.
+    // Empty animation transaction can be used to simulate back-pressure, so also force a
+    // transaction for empty animation transactions.
+    if (transactionFlags == 0 &&
+            ((flags & eSynchronous) || (flags & eAnimation))) {
         transactionFlags = eTransactionNeeded;
     }
 
@@ -3037,6 +3154,13 @@
         return result;
     }
 
+    // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
+    // TODO b/64227542
+    if (windowType == 441731) {
+        windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
+        layer->setPrimaryDisplayOnly();
+    }
+
     layer->setInfo(windowType, ownerUid);
 
     result = addClientLayer(client, *handle, *gbp, layer, *parent);
@@ -3154,7 +3278,8 @@
     d.height = 0;
     displays.add(d);
     setTransactionState(state, displays, 0);
-    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
+    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
+                         /*stateLockHeld*/ false);
 
     const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
     const nsecs_t period = activeConfig->getVsyncPeriod();
@@ -3180,7 +3305,7 @@
 }
 
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
-        int mode) {
+             int mode, bool stateLockHeld) {
     ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
             this);
     int32_t type = hw->getDisplayType();
@@ -3197,7 +3322,7 @@
     }
 
     if (mInterceptor.isEnabled()) {
-        Mutex::Autolock _l(mStateLock);
+        ConditionalLock lock(mStateLock, !stateLockHeld);
         ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
         if (idx < 0) {
             ALOGW("Surface Interceptor SavePowerMode: invalid display token");
@@ -3209,7 +3334,8 @@
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            mode != HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
             resyncToHardwareVsync(true);
@@ -3217,7 +3343,7 @@
 
         mVisibleRegionsDirty = true;
         mHasPoweredOff = true;
-        repaintEverything();
+        repaintEverythingLocked();
 
         struct sched_param param = {0};
         param.sched_priority = 1;
@@ -3241,7 +3367,25 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
+    } else if (mode == HWC_POWER_MODE_DOZE ||
+               mode == HWC_POWER_MODE_NORMAL) {
+        // Update display while dozing
+        getHwComposer().setPowerMode(type, mode);
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+            resyncToHardwareVsync(true);
+        }
+    } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+        // Leave display going to doze
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            disableHardwareVsync(true); // also cancels any in-progress resync
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenReleased();
+        }
+        getHwComposer().setPowerMode(type, mode);
     } else {
+        ALOGE("Attempting to set unknown power mode: %d\n", mode);
         getHwComposer().setPowerMode(type, mode);
     }
 }
@@ -3264,7 +3408,8 @@
                 ALOGW("Attempt to set power mode = %d for virtual display",
                         mMode);
             } else {
-                mFlinger.setPowerModeInternal(hw, mMode);
+                mFlinger.setPowerModeInternal(
+                        hw, mMode, /*stateLockHeld*/ false);
             }
             return true;
         }
@@ -3521,6 +3666,7 @@
 
 void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
     result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+    result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode);
 
     // TODO: print out if wide-color mode is active or not
 
@@ -3710,6 +3856,15 @@
      */
     const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
     alloc.dump(result);
+
+    /*
+     * Dump VrFlinger state if in use.
+     */
+    if (mVrFlingerRequestsDisplay && mVrFlinger) {
+        result.append("VrFlinger state:\n");
+        result.append(mVrFlinger->Dump().c_str());
+        result.append("\n");
+    }
 }
 
 const Vector< sp<Layer> >&
@@ -3757,6 +3912,8 @@
         case GET_ANIMATION_FRAME_STATS:
         case SET_POWER_MODE:
         case GET_HDR_CAPABILITIES:
+        case ENABLE_VSYNC_INJECTIONS:
+        case INJECT_VSYNC:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -3808,10 +3965,11 @@
     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
         CHECK_INTERFACE(ISurfaceComposer, data, reply);
-        if (CC_UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
-            IPCThreadState* ipc = IPCThreadState::self();
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int uid = ipc->getCallingUid();
+        if (CC_UNLIKELY(uid != AID_SYSTEM
+                && !PermissionCache::checkCallingPermission(sHardwareTest))) {
             const int pid = ipc->getCallingPid();
-            const int uid = ipc->getCallingUid();
             ALOGE("Permission Denial: "
                     "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
             return PERMISSION_DENIED;
@@ -3832,6 +3990,7 @@
                 return NO_ERROR;
             }
             case 1005:{ // force transaction
+                Mutex::Autolock _l(mStateLock);
                 setTransactionFlags(
                         eTransactionNeeded|
                         eDisplayTransactionNeeded|
@@ -3896,9 +4055,7 @@
                 // apply a color matrix
                 n = data.readInt32();
                 if (n) {
-                    // color matrix is sent as mat3 matrix followed by vec3
-                    // offset, then packed into a mat4 where the last row is
-                    // the offset and extra values are 0
+                    // color matrix is sent as a column-major mat4 matrix
                     for (size_t i = 0 ; i < 4; i++) {
                         for (size_t j = 0; j < 4; j++) {
                             mColorMatrix[i][j] = data.readFloat();
@@ -3907,6 +4064,14 @@
                 } else {
                     mColorMatrix = mat4();
                 }
+
+                // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
+                // the division by w in the fragment shader
+                float4 lastRow(transpose(mColorMatrix)[3]);
+                if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
+                    ALOGE("The color transform's last row must be (0, 0, 0, 1)");
+                }
+
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -3950,138 +4115,122 @@
                 mUseHwcVirtualDisplays = !n;
                 return NO_ERROR;
             }
+            case 1022: { // Set saturation boost
+                mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f));
+
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
+            case 1023: { // Set native mode
+                mForceNativeColorMode = data.readInt32() == 1;
+
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
+            case 1024: { // Is wide color gamut rendering/color management supported?
+                reply->writeBool(hasWideColorDisplay);
+                return NO_ERROR;
+            }
         }
     }
     return err;
 }
 
-void SurfaceFlinger::repaintEverything() {
+void SurfaceFlinger::repaintEverythingLocked() {
     android_atomic_or(1, &mRepaintEverything);
     signalTransaction();
 }
 
-// ---------------------------------------------------------------------------
-// Capture screen into an IGraphiBufferProducer
-// ---------------------------------------------------------------------------
+void SurfaceFlinger::repaintEverything() {
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
+    repaintEverythingLocked();
+}
 
-/* The code below is here to handle b/8734824
- *
- * We create a IGraphicBufferProducer wrapper that forwards all calls
- * from the surfaceflinger thread to the calling binder thread, where they
- * are executed. This allows the calling thread in the calling process to be
- * reused and not depend on having "enough" binder threads to handle the
- * requests.
- */
-class GraphicProducerWrapper : public BBinder, public MessageHandler {
-    /* Parts of GraphicProducerWrapper are run on two different threads,
-     * communicating by sending messages via Looper but also by shared member
-     * data. Coherence maintenance is subtle and in places implicit (ugh).
-     *
-     * Don't rely on Looper's sendMessage/handleMessage providing
-     * release/acquire semantics for any data not actually in the Message.
-     * Data going from surfaceflinger to binder threads needs to be
-     * synchronized explicitly.
-     *
-     * Barrier open/wait do provide release/acquire semantics. This provides
-     * implicit synchronization for data coming back from binder to
-     * surfaceflinger threads.
-     */
+// Checks that the requested width and height are valid and updates them to the display dimensions
+// if they are set to 0
+static status_t updateDimensionsLocked(const sp<const DisplayDevice>& displayDevice,
+                                       Transform::orientation_flags rotation,
+                                       uint32_t* requestedWidth, uint32_t* requestedHeight) {
+    // get screen geometry
+    uint32_t displayWidth = displayDevice->getWidth();
+    uint32_t displayHeight = displayDevice->getHeight();
 
-    sp<IGraphicBufferProducer> impl;
-    sp<Looper> looper;
-    status_t result;
-    bool exitPending;
-    bool exitRequested;
-    Barrier barrier;
-    uint32_t code;
-    Parcel const* data;
-    Parcel* reply;
-
-    enum {
-        MSG_API_CALL,
-        MSG_EXIT
-    };
-
-    /*
-     * Called on surfaceflinger thread. This is called by our "fake"
-     * BpGraphicBufferProducer. We package the data and reply Parcel and
-     * forward them to the binder thread.
-     */
-    virtual status_t transact(uint32_t code,
-            const Parcel& data, Parcel* reply, uint32_t /* flags */) {
-        this->code = code;
-        this->data = &data;
-        this->reply = reply;
-        if (exitPending) {
-            // if we've exited, we run the message synchronously right here.
-            // note (JH): as far as I can tell from looking at the code, this
-            // never actually happens. if it does, i'm not sure if it happens
-            // on the surfaceflinger or binder thread.
-            handleMessage(Message(MSG_API_CALL));
-        } else {
-            barrier.close();
-            // Prevent stores to this->{code, data, reply} from being
-            // reordered later than the construction of Message.
-            atomic_thread_fence(memory_order_release);
-            looper->sendMessage(this, Message(MSG_API_CALL));
-            barrier.wait();
-        }
-        return result;
+    if (rotation & Transform::ROT_90) {
+        std::swap(displayWidth, displayHeight);
     }
 
-    /*
-     * here we run on the binder thread. All we've got to do is
-     * call the real BpGraphicBufferProducer.
-     */
-    virtual void handleMessage(const Message& message) {
-        int what = message.what;
-        // Prevent reads below from happening before the read from Message
-        atomic_thread_fence(memory_order_acquire);
-        if (what == MSG_API_CALL) {
-            result = IInterface::asBinder(impl)->transact(code, data[0], reply);
-            barrier.open();
-        } else if (what == MSG_EXIT) {
-            exitRequested = true;
-        }
+    if ((*requestedWidth > displayWidth) || (*requestedHeight > displayHeight)) {
+        ALOGE("size mismatch (%d, %d) > (%d, %d)",
+                *requestedWidth, *requestedHeight, displayWidth, displayHeight);
+        return BAD_VALUE;
     }
 
+    if (*requestedWidth == 0) {
+        *requestedWidth = displayWidth;
+    }
+    if (*requestedHeight == 0) {
+        *requestedHeight = displayHeight;
+    }
+
+    return NO_ERROR;
+}
+
+// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
+class WindowDisconnector {
 public:
-    explicit GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
-    :   impl(impl),
-        looper(new Looper(true)),
-        result(NO_ERROR),
-        exitPending(false),
-        exitRequested(false),
-        code(0),
-        data(NULL),
-        reply(NULL)
-    {}
-
-    // Binder thread
-    status_t waitForResponse() {
-        do {
-            looper->pollOnce(-1);
-        } while (!exitRequested);
-        return result;
+    WindowDisconnector(ANativeWindow* window, int api) : mWindow(window), mApi(api) {}
+    ~WindowDisconnector() {
+        native_window_api_disconnect(mWindow, mApi);
     }
 
-    // Client thread
-    void exit(status_t result) {
-        this->result = result;
-        exitPending = true;
-        // Ensure this->result is visible to the binder thread before it
-        // handles the message.
-        atomic_thread_fence(memory_order_release);
-        looper->sendMessage(this, Message(MSG_EXIT));
-    }
+private:
+    ANativeWindow* mWindow;
+    const int mApi;
 };
 
+static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth,
+                                uint32_t requestedHeight, bool hasWideColorDisplay,
+                                bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) {
+    const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+            GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+    int err = 0;
+    err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight);
+    err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+    err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+    err |= native_window_set_usage(window, usage);
+
+    if (hasWideColorDisplay) {
+        err |= native_window_set_buffers_data_space(window,
+                                                    renderEngineUsesWideColor
+                                                            ? HAL_DATASPACE_DISPLAY_P3
+                                                            : HAL_DATASPACE_V0_SRGB);
+    }
+
+    if (err != NO_ERROR) {
+        return BAD_VALUE;
+    }
+
+    /* TODO: Once we have the sync framework everywhere this can use
+     * server-side waits on the fence that dequeueBuffer returns.
+     */
+    err = native_window_dequeue_buffer_and_wait(window, outBuffer);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    return NO_ERROR;
+}
 
 status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
         const sp<IGraphicBufferProducer>& producer,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         int32_t minLayerZ, int32_t maxLayerZ,
         bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+    ATRACE_CALL();
 
     if (CC_UNLIKELY(display == 0))
         return BAD_VALUE;
@@ -4115,65 +4264,96 @@
             break;
     }
 
-    class MessageCaptureScreen : public MessageBase {
-        SurfaceFlinger* flinger;
-        sp<IBinder> display;
-        sp<IGraphicBufferProducer> producer;
-        Rect sourceCrop;
-        uint32_t reqWidth, reqHeight;
-        uint32_t minLayerZ,maxLayerZ;
-        bool useIdentityTransform;
-        Transform::orientation_flags rotation;
-        status_t result;
-        bool isLocalScreenshot;
-    public:
-        MessageCaptureScreen(SurfaceFlinger* flinger,
-                const sp<IBinder>& display,
-                const sp<IGraphicBufferProducer>& producer,
-                Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-                int32_t minLayerZ, int32_t maxLayerZ,
-                bool useIdentityTransform,
-                Transform::orientation_flags rotation,
-                bool isLocalScreenshot)
-            : flinger(flinger), display(display), producer(producer),
-              sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
-              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
-              useIdentityTransform(useIdentityTransform),
-              rotation(rotation), result(PERMISSION_DENIED),
-              isLocalScreenshot(isLocalScreenshot)
-        {
-        }
-        status_t getResult() const {
-            return result;
-        }
-        virtual bool handler() {
-            Mutex::Autolock _l(flinger->mStateLock);
-            sp<const DisplayDevice> hw(flinger->getDisplayDeviceLocked(display));
-            result = flinger->captureScreenImplLocked(hw, producer,
-                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform, rotation, isLocalScreenshot);
-            static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
-            return true;
-        }
-    };
-
-    // this creates a "fake" BBinder which will serve as a "fake" remote
-    // binder to receive the marshaled calls and forward them to the
-    // real remote (a BpGraphicBufferProducer)
-    sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
-
-    // the asInterface() call below creates our "fake" BpGraphicBufferProducer
-    // which does the marshaling work forwards to our "fake remote" above.
-    sp<MessageBase> msg = new MessageCaptureScreen(this,
-            display, IGraphicBufferProducer::asInterface( wrapper ),
-            sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-            useIdentityTransform, rotationFlags, isLocalScreenshot);
-
-    status_t res = postMessageAsync(msg);
-    if (res == NO_ERROR) {
-        res = wrapper->waitForResponse();
+    { // Autolock scope
+        Mutex::Autolock lock(mStateLock);
+        sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
+        updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight);
     }
-    return res;
+
+    // create a surface (because we're a producer, and we need to
+    // dequeue/queue a buffer)
+    sp<Surface> surface = new Surface(producer, false);
+
+    // Put the screenshot Surface into async mode so that
+    // Layer::headFenceHasSignaled will always return true and we'll latch the
+    // first buffer regardless of whether or not its acquire fence has
+    // signaled. This is needed to avoid a race condition in the rotation
+    // animation. See b/30209608
+    surface->setAsyncMode(true);
+
+    ANativeWindow* window = surface.get();
+
+    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+    if (result != NO_ERROR) {
+        return result;
+    }
+    WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
+
+    ANativeWindowBuffer* buffer = nullptr;
+    result = getWindowBuffer(window, reqWidth, reqHeight,
+            hasWideColorDisplay && !mForceNativeColorMode,
+            getRenderEngine().usesWideColor(), &buffer);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    // This mutex protects syncFd and captureResult for communication of the return values from the
+    // main thread back to this Binder thread
+    std::mutex captureMutex;
+    std::condition_variable captureCondition;
+    std::unique_lock<std::mutex> captureLock(captureMutex);
+    int syncFd = -1;
+    std::optional<status_t> captureResult;
+
+    sp<LambdaMessage> message = new LambdaMessage([&]() {
+        // If there is a refresh pending, bug out early and tell the binder thread to try again
+        // after the refresh.
+        if (mRefreshPending) {
+            ATRACE_NAME("Skipping screenshot for now");
+            std::unique_lock<std::mutex> captureLock(captureMutex);
+            captureResult = std::make_optional<status_t>(EAGAIN);
+            captureCondition.notify_one();
+            return;
+        }
+
+        status_t result = NO_ERROR;
+        int fd = -1;
+        {
+            Mutex::Autolock _l(mStateLock);
+            sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+            result = captureScreenImplLocked(device, buffer, sourceCrop, reqWidth, reqHeight,
+                                             minLayerZ, maxLayerZ, useIdentityTransform,
+                                             rotationFlags, isLocalScreenshot, &fd);
+        }
+
+        {
+            std::unique_lock<std::mutex> captureLock(captureMutex);
+            syncFd = fd;
+            captureResult = std::make_optional<status_t>(result);
+            captureCondition.notify_one();
+        }
+    });
+
+    result = postMessageAsync(message);
+    if (result == NO_ERROR) {
+        captureCondition.wait(captureLock, [&]() { return captureResult; });
+        while (*captureResult == EAGAIN) {
+            captureResult.reset();
+            result = postMessageAsync(message);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            captureCondition.wait(captureLock, [&]() { return captureResult; });
+        }
+        result = *captureResult;
+    }
+
+    if (result == NO_ERROR) {
+        // queueBuffer takes ownership of syncFd
+        result = window->queueBuffer(window, buffer, syncFd);
+    }
+
+    return result;
 }
 
 
@@ -4213,6 +4393,11 @@
         ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
     }
 
+#ifdef USE_HWC2
+     engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode);
+     engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode());
+#endif
+
     // make sure to clear all GL error flags
     engine.checkErrors();
 
@@ -4227,7 +4412,7 @@
     // We loop through the first level of layers without traversing,
     // as we need to interpret min/max layer Z in the top level Z space.
     for (const auto& layer : mDrawingState.layersSortedByZ) {
-        if (layer->getLayerStack() != hw->getLayerStack()) {
+        if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
             continue;
         }
         const Layer::State& state(layer->getDrawingState());
@@ -4247,38 +4432,39 @@
     hw->setViewportAndProjection();
 }
 
+// A simple RAII class that holds an EGLImage and destroys it either:
+//   a) When the destroy() method is called
+//   b) When the object goes out of scope
+class ImageHolder {
+public:
+    ImageHolder(EGLDisplay display, EGLImageKHR image) : mDisplay(display), mImage(image) {}
+    ~ImageHolder() { destroy(); }
 
-status_t SurfaceFlinger::captureScreenImplLocked(
-        const sp<const DisplayDevice>& hw,
-        const sp<IGraphicBufferProducer>& producer,
-        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
-        int32_t minLayerZ, int32_t maxLayerZ,
-        bool useIdentityTransform, Transform::orientation_flags rotation,
-        bool isLocalScreenshot)
-{
+    void destroy() {
+        if (mImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mDisplay, mImage);
+            mImage = EGL_NO_IMAGE_KHR;
+        }
+    }
+
+private:
+    const EGLDisplay mDisplay;
+    EGLImageKHR mImage;
+};
+
+status_t SurfaceFlinger::captureScreenImplLocked(const sp<const DisplayDevice>& hw,
+                                                 ANativeWindowBuffer* buffer, Rect sourceCrop,
+                                                 uint32_t reqWidth, uint32_t reqHeight,
+                                                 int32_t minLayerZ, int32_t maxLayerZ,
+                                                 bool useIdentityTransform,
+                                                 Transform::orientation_flags rotation,
+                                                 bool isLocalScreenshot, int* outSyncFd) {
     ATRACE_CALL();
 
-    // get screen geometry
-    uint32_t hw_w = hw->getWidth();
-    uint32_t hw_h = hw->getHeight();
-
-    if (rotation & Transform::ROT_90) {
-        std::swap(hw_w, hw_h);
-    }
-
-    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)",
-                reqWidth, reqHeight, hw_w, hw_h);
-        return BAD_VALUE;
-    }
-
-    reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
-    reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
     bool secureLayerIsVisible = false;
     for (const auto& layer : mDrawingState.layersSortedByZ) {
         const Layer::State& state(layer->getDrawingState());
-        if ((layer->getLayerStack() != hw->getLayerStack()) ||
+        if (!layer->belongsToDisplay(hw->getLayerStack(), false) ||
                 (state.z < minLayerZ || state.z > maxLayerZ)) {
             continue;
         }
@@ -4293,123 +4479,84 @@
         return PERMISSION_DENIED;
     }
 
-    // create a surface (because we're a producer, and we need to
-    // dequeue/queue a buffer)
-    sp<Surface> sur = new Surface(producer, false);
-
-    // Put the screenshot Surface into async mode so that
-    // Layer::headFenceHasSignaled will always return true and we'll latch the
-    // first buffer regardless of whether or not its acquire fence has
-    // signaled. This is needed to avoid a race condition in the rotation
-    // animation. See b/30209608
-    sur->setAsyncMode(true);
-
-    ANativeWindow* window = sur.get();
-
-    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
-    if (result == NO_ERROR) {
-        uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
-                        GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
-        int err = 0;
-        err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
-        err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-        err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
-        err |= native_window_set_usage(window, usage);
-
-        if (err == NO_ERROR) {
-            ANativeWindowBuffer* buffer;
-            /* TODO: Once we have the sync framework everywhere this can use
-             * server-side waits on the fence that dequeueBuffer returns.
-             */
-            result = native_window_dequeue_buffer_and_wait(window,  &buffer);
-            if (result == NO_ERROR) {
-                int syncFd = -1;
-                // create an EGLImage from the buffer so we can later
-                // turn it into a texture
-                EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
-                        EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
-                if (image != EGL_NO_IMAGE_KHR) {
-                    // this binds the given EGLImage as a framebuffer for the
-                    // duration of this scope.
-                    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
-                    if (imageBond.getStatus() == NO_ERROR) {
-                        // this will in fact render into our dequeued buffer
-                        // via an FBO, which means we didn't have to create
-                        // an EGLSurface and therefore we're not
-                        // dependent on the context's EGLConfig.
-                        renderScreenImplLocked(
-                            hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
-                            useIdentityTransform, rotation);
-
-                        // Attempt to create a sync khr object that can produce a sync point. If that
-                        // isn't available, create a non-dupable sync object in the fallback path and
-                        // wait on it directly.
-                        EGLSyncKHR sync;
-                        if (!DEBUG_SCREENSHOTS) {
-                           sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
-                           // native fence fd will not be populated until flush() is done.
-                           getRenderEngine().flush();
-                        } else {
-                            sync = EGL_NO_SYNC_KHR;
-                        }
-                        if (sync != EGL_NO_SYNC_KHR) {
-                            // get the sync fd
-                            syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
-                            if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-                                ALOGW("captureScreen: failed to dup sync khr object");
-                                syncFd = -1;
-                            }
-                            eglDestroySyncKHR(mEGLDisplay, sync);
-                        } else {
-                            // fallback path
-                            sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
-                            if (sync != EGL_NO_SYNC_KHR) {
-                                EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
-                                    EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
-                                EGLint eglErr = eglGetError();
-                                if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-                                    ALOGW("captureScreen: fence wait timed out");
-                                } else {
-                                    ALOGW_IF(eglErr != EGL_SUCCESS,
-                                            "captureScreen: error waiting on EGL fence: %#x", eglErr);
-                                }
-                                eglDestroySyncKHR(mEGLDisplay, sync);
-                            } else {
-                                ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
-                            }
-                        }
-                        if (DEBUG_SCREENSHOTS) {
-                            uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
-                            getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
-                            checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
-                                    hw, minLayerZ, maxLayerZ);
-                            delete [] pixels;
-                        }
-
-                    } else {
-                        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
-                        result = INVALID_OPERATION;
-                        window->cancelBuffer(window, buffer, syncFd);
-                        buffer = NULL;
-                    }
-                    // destroy our image
-                    eglDestroyImageKHR(mEGLDisplay, image);
-                } else {
-                    result = BAD_VALUE;
-                }
-                if (buffer) {
-                    // queueBuffer takes ownership of syncFd
-                    result = window->queueBuffer(window, buffer, syncFd);
-                }
-            }
-        } else {
-            result = BAD_VALUE;
-        }
-        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+    int syncFd = -1;
+    // create an EGLImage from the buffer so we can later
+    // turn it into a texture
+    EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+            EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
+    if (image == EGL_NO_IMAGE_KHR) {
+        return BAD_VALUE;
     }
 
-    return result;
+    // This will automatically destroy the image if we return before calling its destroy method
+    ImageHolder imageHolder(mEGLDisplay, image);
+
+    // this binds the given EGLImage as a framebuffer for the
+    // duration of this scope.
+    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
+    if (imageBond.getStatus() != NO_ERROR) {
+        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+        return INVALID_OPERATION;
+    }
+
+    // this will in fact render into our dequeued buffer
+    // via an FBO, which means we didn't have to create
+    // an EGLSurface and therefore we're not
+    // dependent on the context's EGLConfig.
+    renderScreenImplLocked(
+        hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
+        useIdentityTransform, rotation);
+
+    // Attempt to create a sync khr object that can produce a sync point. If that
+    // isn't available, create a non-dupable sync object in the fallback path and
+    // wait on it directly.
+    EGLSyncKHR sync = EGL_NO_SYNC_KHR;
+    if (!DEBUG_SCREENSHOTS) {
+       sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+       // native fence fd will not be populated until flush() is done.
+       getRenderEngine().flush();
+    }
+
+    if (sync != EGL_NO_SYNC_KHR) {
+        // get the sync fd
+        syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+        if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+            ALOGW("captureScreen: failed to dup sync khr object");
+            syncFd = -1;
+        }
+        eglDestroySyncKHR(mEGLDisplay, sync);
+    } else {
+        // fallback path
+        sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+        if (sync != EGL_NO_SYNC_KHR) {
+            EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+            EGLint eglErr = eglGetError();
+            if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                ALOGW("captureScreen: fence wait timed out");
+            } else {
+                ALOGW_IF(eglErr != EGL_SUCCESS,
+                        "captureScreen: error waiting on EGL fence: %#x", eglErr);
+            }
+            eglDestroySyncKHR(mEGLDisplay, sync);
+        } else {
+            ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+        }
+    }
+    *outSyncFd = syncFd;
+
+    if (DEBUG_SCREENSHOTS) {
+        uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
+        getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
+        checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
+                hw, minLayerZ, maxLayerZ);
+        delete [] pixels;
+    }
+
+    // destroy our image
+    imageHolder.destroy();
+
+    return NO_ERROR;
 }
 
 void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
@@ -4428,7 +4575,7 @@
         size_t i = 0;
         for (const auto& layer : mDrawingState.layersSortedByZ) {
             const Layer::State& state(layer->getDrawingState());
-            if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
+            if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ &&
                     state.z <= maxLayerZ) {
                 layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
                     ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9239538..99d4a1a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -58,15 +58,22 @@
 #include "LayerVector.h"
 #include "MessageQueue.h"
 #include "SurfaceInterceptor.h"
-#include "StartBootAnimThread.h"
+#include "StartPropertySetThread.h"
 
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
 #include "DisplayHardware/HWComposer.h"
+#else
+#include "DisplayHardware/HWComposer_hwc1.h"
+#endif
+
 #include "Effects/Daltonizer.h"
 
 #include <map>
 #include <mutex>
 #include <queue>
 #include <string>
+#include <thread>
 #include <utility>
 
 namespace android {
@@ -99,7 +106,11 @@
 
 class SurfaceFlinger : public BnSurfaceComposer,
                        private IBinder::DeathRecipient,
+#ifdef USE_HWC2
+                       private HWC2::ComposerCallback
+#else
                        private HWComposer::EventHandler
+#endif
 {
 public:
 
@@ -181,6 +192,8 @@
 
     // force full composition on all displays
     void repaintEverything();
+    // Can only be called from the main thread or with mStateLock held
+    void repaintEverythingLocked();
 
     // returns the default Display
     sp<const DisplayDevice> getDefaultDisplayDevice() const {
@@ -227,7 +240,6 @@
     enum { LOG_FRAME_STATS_PERIOD =  30*60*60 };
 
     static const size_t MAX_LAYERS = 4096;
-    static constexpr const char* kTimestampProperty = "service.sf.present_timestamp";
 
     // We're reference counted, never destroy SurfaceFlinger directly
     virtual ~SurfaceFlinger();
@@ -314,17 +326,28 @@
     virtual void onFirstRef();
 
     /* ------------------------------------------------------------------------
-     * HWComposer::EventHandler interface
+     * HWC2::ComposerCallback / HWComposer::EventHandler interface
      */
-    virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
-    virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
-    virtual void onInvalidateReceived(HWComposer* composer);
+#ifdef USE_HWC2
+    void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+                         int64_t timestamp) override;
+    void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+                           HWC2::Connection connection,
+                           bool primaryDisplay) override;
+    void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+#else
+    void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
+    void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
+    void onInvalidateReceived(HWComposer* composer) override;
+#endif
 
     /* ------------------------------------------------------------------------
      * Message handling
      */
     void waitForEvent();
+    // Can only be called from the main thread or with mStateLock held
     void signalTransaction();
+    // Can only be called from the main thread or with mStateLock held
     void signalLayerUpdate();
     void signalRefresh();
 
@@ -333,11 +356,19 @@
     // called on the main thread in response to setActiveConfig()
     void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
     // called on the main thread in response to setPowerMode()
+#ifdef USE_HWC2
+    void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
+                              bool stateLockHeld);
+#else
     void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
+#endif
 
     // Called on the main thread in response to setActiveColorMode()
     void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
 
+    // Called on the main thread in response to enableVSyncInjections()
+    void enableVSyncInjectionsInternal(bool enable);
+
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
 
@@ -362,6 +393,7 @@
      */
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t peekTransactionFlags();
+    // Can only be called from the main thread or with mStateLock held
     uint32_t setTransactionFlags(uint32_t flags);
     void commitTransaction();
     uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
@@ -417,6 +449,14 @@
             int32_t minLayerZ, int32_t maxLayerZ,
             bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation);
 
+#ifdef USE_HWC2
+    status_t captureScreenImplLocked(const sp<const DisplayDevice>& device,
+                                     ANativeWindowBuffer* buffer, Rect sourceCrop,
+                                     uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+                                     int32_t maxLayerZ, bool useIdentityTransform,
+                                     Transform::orientation_flags rotation, bool isLocalScreenshot,
+                                     int* outSyncFd);
+#else
     status_t captureScreenImplLocked(
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,
@@ -424,8 +464,14 @@
             int32_t minLayerZ, int32_t maxLayerZ,
             bool useIdentityTransform, Transform::orientation_flags rotation,
             bool isLocalScreenshot);
+#endif
 
-    sp<StartBootAnimThread> mStartBootAnimThread = nullptr;
+    sp<StartPropertySetThread> mStartPropertySetThread = nullptr;
+
+    /* ------------------------------------------------------------------------
+     * Properties
+     */
+    void readPersistentProperties();
 
     /* ------------------------------------------------------------------------
      * EGL
@@ -481,7 +527,7 @@
 
     // mark a region of a layer stack dirty. this updates the dirty
     // region of all screens presenting this layer stack.
-    void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
+    void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
 
 #ifndef USE_HWC2
     int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
@@ -497,7 +543,7 @@
      * Compositing
      */
     void invalidateHwcGeometry();
-    void computeVisibleRegions(uint32_t layerStack,
+    void computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
             Region& dirtyRegion, Region& opaqueRegion);
 
     void preComposition(nsecs_t refreshStartTime);
@@ -512,8 +558,10 @@
 
     // Given a dataSpace, returns the appropriate color_mode to use
     // to display that dataSpace.
-    android_color_mode pickColorMode(android_dataspace dataSpace);
-    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+    android_color_mode pickColorMode(android_dataspace dataSpace) const;
+    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const;
+
+    mat4 computeSaturationMatrix() const;
 
     void setUpHWComposer();
     void doComposition();
@@ -575,8 +623,7 @@
     /* ------------------------------------------------------------------------
      * VrFlinger
      */
-    void clearHwcLayers(const LayerVector& layers);
-    void resetHwcLocked();
+    void resetDisplayState();
 
     // Check to see if we should handoff to vr flinger.
     void updateVrFlinger();
@@ -603,12 +650,28 @@
     // access must be protected by mInvalidateLock
     volatile int32_t mRepaintEverything;
 
-    // current, real and vr hardware composers.
-    HWComposer* mHwc;
-#ifdef USE_HWC2
-    HWComposer* mRealHwc;
-    HWComposer* mVrHwc;
-#endif
+    // The current hardware composer interface.
+    //
+    // The following thread safety rules apply when accessing mHwc, either
+    // directly or via getHwComposer():
+    //
+    // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
+    //    only when switching into and out of vr. Recreating mHwc must only be
+    //    done on the main thread.
+    //
+    // 2. When accessing mHwc on the main thread, it's not necessary to acquire
+    //    mStateLock.
+    //
+    // 3. When accessing mHwc on a thread other than the main thread, we always
+    //    need to acquire mStateLock. This is because the main thread could be
+    //    in the process of destroying the current mHwc instance.
+    //
+    // The above thread safety rules only apply to SurfaceFlinger.cpp. In
+    // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never
+    // destroy it, so it's always safe to access mHwc from any thread without
+    // acquiring mStateLock.
+    std::unique_ptr<HWComposer> mHwc;
+
     // constant members (no synchronization needed for access)
     RenderEngine* mRenderEngine;
     nsecs_t mBootTime;
@@ -622,10 +685,6 @@
     EGLDisplay mEGLDisplay;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
-#ifdef USE_HWC2
-    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
-#endif
-
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
@@ -693,6 +752,8 @@
     };
     std::queue<CompositePresentTime> mCompositePresentTimes;
 
+    std::atomic<bool> mRefreshPending{false};
+
     /* ------------------------------------------------------------------------
      * Feature prototyping
      */
@@ -745,10 +806,19 @@
     status_t CheckTransactCodeCredentials(uint32_t code);
 
 #ifdef USE_HWC2
+    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
     std::atomic<bool> mVrFlingerRequestsDisplay;
     static bool useVrFlinger;
+    std::thread::id mMainThreadId;
+    // 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;
 #endif
-    };
+
+    float mSaturation = 1.0f;
+    bool mForceNativeColorMode = false;
+};
 }; // namespace android
 
 #endif // ANDROID_SURFACE_FLINGER_H
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 9babeef..abc8fde 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -240,10 +240,15 @@
 }
 
 void SurfaceFlingerConsumer::onSidebandStreamChanged() {
+    FrameAvailableListener* unsafeFrameAvailableListener = nullptr;
+    {
+        Mutex::Autolock lock(mFrameAvailableMutex);
+        unsafeFrameAvailableListener = mFrameAvailableListener.unsafe_get();
+    }
     sp<ContentsChangedListener> listener;
     {   // scope for the lock
         Mutex::Autolock lock(mMutex);
-        ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get());
+        ALOG_ASSERT(unsafeFrameAvailableListener == mContentsChangedListener.unsafe_get());
         listener = mContentsChangedListener.promote();
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 0904fab..b28fe68 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -94,7 +94,7 @@
  */
 #define DEBUG_SCREENSHOTS   false
 
-EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -320,8 +320,8 @@
 
 void SurfaceFlinger::bootFinished()
 {
-    if (mStartBootAnimThread->join() != NO_ERROR) {
-        ALOGE("Join StartBootAnimThread failed!");
+    if (mStartPropertySetThread->join() != NO_ERROR) {
+        ALOGE("Join StartPropertySetThread failed!");
     }
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
@@ -501,6 +501,8 @@
     sp<VSyncSource::Callback> mCallback;
 };
 
+// Do not call property_set on main thread which will be blocked by init
+// Use StartPropertySetThread instead.
 void SurfaceFlinger::init() {
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
@@ -532,11 +534,12 @@
 
     // Initialize the H/W composer object.  There may or may not be an
     // actual hardware composer underneath.
-    mHwc = new HWComposer(this,
-            *static_cast<HWComposer::EventHandler *>(this));
+    mHwc.reset(new HWComposer(this,
+            *static_cast<HWComposer::EventHandler *>(this)));
 
     // get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
+    mRenderEngine = RenderEngine::create(mEGLDisplay,
+            mHwc->getVisualID(), 0);
 
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
@@ -544,9 +547,6 @@
     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
             "couldn't create EGLContext");
 
-    // Inform native graphics APIs that the present timestamp is NOT supported:
-    property_set(kTimestampProperty, "0");
-
     // initialize our non-virtual displays
     for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
@@ -599,9 +599,10 @@
 
     mRenderEngine->primeCache();
 
-    mStartBootAnimThread = new StartBootAnimThread();
-    if (mStartBootAnimThread->Start() != NO_ERROR) {
-        ALOGE("Run StartBootAnimThread failed!");
+    // Inform native graphics APIs that the present timestamp is NOT supported:
+    mStartPropertySetThread = new StartPropertySetThread(false);
+    if (mStartPropertySetThread->Start() != NO_ERROR) {
+        ALOGE("Run StartPropertySetThread failed!");
     }
 
     ALOGV("Done initializing");
@@ -615,10 +616,10 @@
 void SurfaceFlinger::startBootAnim() {
     // Start boot animation service by setting a property mailbox
     // if property setting thread is already running, Start() will be just a NOP
-    mStartBootAnimThread->Start();
+    mStartPropertySetThread->Start();
     // Wait until property was set
-    if (mStartBootAnimThread->join() != NO_ERROR) {
-        ALOGE("Join StartBootAnimThread failed!");
+    if (mStartPropertySetThread->join() != NO_ERROR) {
+        ALOGE("Join StartPropertySetThread failed!");
     }
 }
 
@@ -1256,6 +1257,7 @@
     const HWComposer& hwc = getHwComposer();
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
 
+    mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
     if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
         glCompositionDoneFenceTime =
@@ -1264,12 +1266,11 @@
     } else {
         glCompositionDoneFenceTime = FenceTime::NO_FENCE;
     }
-    mGlCompositionDoneTimeline.updateSignalTimes();
 
+    mDisplayTimeline.updateSignalTimes();
     sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
     auto retireFenceTime = std::make_shared<FenceTime>(retireFence);
     mDisplayTimeline.push(retireFenceTime);
-    mDisplayTimeline.updateSignalTimes();
 
     nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
     nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
@@ -1297,7 +1298,7 @@
     });
 
     if (retireFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(retireFence)) {
+        if (mPrimaryDispSync.addPresentFence(retireFenceTime)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1360,8 +1361,7 @@
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
             if (hw->isDisplayOn()) {
-                computeVisibleRegions(hw->getLayerStack(), dirtyRegion,
-                        opaqueRegion);
+                computeVisibleRegions(hw, dirtyRegion, opaqueRegion);
 
                 mDrawingState.traverseInZOrder([&](Layer* layer) {
                     if (layer->getLayerStack() == hw->getLayerStack()) {
@@ -1862,7 +1862,7 @@
                 // TODO: we could cache the transformed region
                 Region visibleReg;
                 visibleReg.set(layer->computeScreenBounds());
-                invalidateLayerStack(layer->getLayerStack(), visibleReg);
+                invalidateLayerStack(layer, visibleReg);
             }
         });
     }
@@ -1923,7 +1923,7 @@
     mTransactionCV.broadcast();
 }
 
-void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack,
+void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
         Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
@@ -1939,7 +1939,7 @@
         const Layer::State& s(layer->getDrawingState());
 
         // only consider the layers on the given layer stack
-        if (layer->getLayerStack() != layerStack)
+        if (layer->getLayerStack() != displayDevice->getLayerStack())
             return;
 
         /*
@@ -2054,8 +2054,8 @@
     outOpaqueRegion = aboveOpaqueLayers;
 }
 
-void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
-        const Region& dirty) {
+void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
+    uint32_t layerStack = layer->getLayerStack();
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
         if (hw->getLayerStack() == layerStack) {
@@ -2098,7 +2098,7 @@
         Layer* layer = layersWithQueuedFrames[i];
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
-        invalidateLayerStack(layer->getLayerStack(), dirty);
+        invalidateLayerStack(layer, dirty);
     }
 
     mVisibleRegionsDirty |= visibleRegions;
@@ -2382,6 +2382,7 @@
         return NO_ERROR;
     }
 
+    layer->onRemovedFromCurrentState();
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
     mNumLayers -= 1 + layer->getChildrenCount();
@@ -2870,7 +2871,8 @@
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
-        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY &&
+            mode != HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
             mEventThread->onScreenAcquired();
             resyncToHardwareVsync(true);
@@ -2902,7 +2904,25 @@
         getHwComposer().setPowerMode(type, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
+    } else if (mode == HWC_POWER_MODE_DOZE ||
+               mode == HWC_POWER_MODE_NORMAL) {
+        // Update display while dozing
+        getHwComposer().setPowerMode(type, mode);
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+            resyncToHardwareVsync(true);
+        }
+    } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
+        // Leave display going to doze
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            disableHardwareVsync(true); // also cancels any in-progress resync
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenReleased();
+        }
+        getHwComposer().setPowerMode(type, mode);
     } else {
+        ALOGE("Attempting to set unknown power mode: %d\n", mode);
         getHwComposer().setPowerMode(type, mode);
     }
 }
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index 16041da..43e22a0 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -4,7 +4,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_MODULE := SurfaceFlinger_test
-
+LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
diff --git a/services/surfaceflinger/tests/AndroidTest.xml b/services/surfaceflinger/tests/AndroidTest.xml
new file mode 100644
index 0000000..8315037
--- /dev/null
+++ b/services/surfaceflinger/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for SurfaceFlinger_test">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="SurfaceFlinger_test->/data/local/tmp/SurfaceFlinger_test" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="SurfaceFlinger_test" />
+    </test>
+</configuration>
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 915b5cd..6be708a 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*" 
+            "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*"
         }
 }
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index b7792c7..4ce14f8 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -566,6 +566,15 @@
         sc->expectBGColor(127, 127);
         sc->expectBGColor(128, 128);
     }
+
+    void EXPECT_RESIZE_STATE(const char* trace) {
+        SCOPED_TRACE(trace);
+        ScreenCapture::captureScreen(&sc);
+        // The FG is now resized too 128,128 at 64,64
+        sc->expectFGColor(64, 64);
+        sc->expectFGColor(191, 191);
+        sc->expectBGColor(192, 192);
+    }
 };
 
 TEST_F(CropLatchingTest, CropLatching) {
@@ -666,15 +675,17 @@
     mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
     SurfaceComposerClient::closeGlobalTransaction(true);
 
+    EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+
     SurfaceComposerClient::openGlobalTransaction();
     mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
     SurfaceComposerClient::closeGlobalTransaction(true);
 
-    EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
+    EXPECT_INITIAL_STATE("after setting another crop");
 
     completeFGResize();
 
-    EXPECT_INITIAL_STATE("after the resize finishes");
+    EXPECT_RESIZE_STATE("after the resize finishes");
 }
 
 TEST_F(LayerUpdateTest, DeferredTransactionTest) {
diff --git a/services/surfaceflinger/tests/vsync/Android.mk b/services/surfaceflinger/tests/vsync/Android.mk
index 9181760..8e41617 100644
--- a/services/surfaceflinger/tests/vsync/Android.mk
+++ b/services/surfaceflinger/tests/vsync/Android.mk
@@ -15,4 +15,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_CFLAGS := -Werror
+
 include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index aa72c79..a1b45e6 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -20,7 +20,7 @@
 
 using namespace android;
 
-int receiver(int fd, int events, void* data)
+int receiver(int /*fd*/, int /*events*/, void* data)
 {
     DisplayEventReceiver* q = (DisplayEventReceiver*)data;
 
@@ -47,7 +47,7 @@
     return 1;
 }
 
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
 {
     DisplayEventReceiver myDisplayEvent;
 
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.mk b/services/surfaceflinger/tests/waitforvsync/Android.mk
index c25f5ab..932d2be 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.mk
+++ b/services/surfaceflinger/tests/waitforvsync/Android.mk
@@ -11,4 +11,6 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_CFLAGS := -Werror
+
 include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
index b88b04a..65eaae5 100644
--- a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
+++ b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
@@ -29,7 +29,7 @@
 #define FBIO_WAITFORVSYNC   _IOW('F', 0x20, __u32)
 #endif
 
-int main(int argc, char** argv) {
+int main(int /*argc*/, char** /*argv*/) {
     int fd = open("/dev/graphics/fb0", O_RDWR);
     if (fd >= 0) {
         do {
diff --git a/services/thermalservice/Android.bp b/services/thermalservice/Android.bp
new file mode 100644
index 0000000..d754560
--- /dev/null
+++ b/services/thermalservice/Android.bp
@@ -0,0 +1,61 @@
+subdirs = [
+    "libthermalcallback"
+]
+
+cc_library {
+    name: "libthermalservice",
+
+    srcs: [
+        "aidl/android/os/IThermalEventListener.aidl",
+        "aidl/android/os/IThermalService.aidl",
+        "aidl/android/os/Temperature.cpp",
+    ],
+    aidl: {
+      include_dirs: ["frameworks/native/services/thermalservice/aidl"],
+      export_aidl_headers: true,
+    },
+    export_include_dirs: ["aidl"],
+
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
+
+cc_binary {
+    name: "thermalserviced",
+
+    srcs: [
+        "ThermalService.cpp",
+        "thermalserviced.cpp",
+    ],
+
+    include_dirs: ["frameworks/native"],
+
+    shared_libs: [
+        "libthermalservice",
+        "libbinder",
+        "libutils",
+        "libthermalcallback",
+        "android.hardware.thermal@1.1",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+
+    init_rc: ["thermalservice.rc"],
+}
diff --git a/services/thermalservice/ThermalService.cpp b/services/thermalservice/ThermalService.cpp
new file mode 100644
index 0000000..6e09a83
--- /dev/null
+++ b/services/thermalservice/ThermalService.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ThermalService.h"
+#include <android/os/IThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace os {
+
+/**
+ * Notify registered listeners of a thermal throttling start/stop event.
+ * @param temperature the temperature at which the event was generated
+ */
+binder::Status ThermalService::notifyThrottling(
+    const bool isThrottling, const Temperature& temperature) {
+    Mutex::Autolock _l(mListenersLock);
+
+    mThrottled = isThrottling;
+    mThrottleTemperature = temperature;
+
+    for (size_t i = 0; i < mListeners.size(); i++) {
+      mListeners[i]->notifyThrottling(isThrottling, temperature);
+    }
+    return binder::Status::ok();
+}
+
+/**
+ * Query whether the system is currently thermal throttling.
+ * @return true if currently thermal throttling, else false
+ */
+binder::Status ThermalService::isThrottling(bool* _aidl_return) {
+    Mutex::Autolock _l(mListenersLock);
+    *_aidl_return = mThrottled;
+    return binder::Status::ok();
+}
+
+/**
+ * Register a new thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ *                 notifications are to be sent
+ */
+binder::Status ThermalService::registerThermalEventListener(
+    const sp<IThermalEventListener>& listener) {
+    {
+        if (listener == NULL)
+            return binder::Status::ok();
+        Mutex::Autolock _l(mListenersLock);
+        // check whether this is a duplicate
+        for (size_t i = 0; i < mListeners.size(); i++) {
+            if (IInterface::asBinder(mListeners[i]) ==
+                IInterface::asBinder(listener)) {
+                return binder::Status::ok();
+            }
+        }
+
+        mListeners.add(listener);
+        IInterface::asBinder(listener)->linkToDeath(this);
+    }
+
+    return binder::Status::ok();
+}
+
+/**
+ * Unregister a previously-registered thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ *                 notifications are to no longer be sent
+ */
+binder::Status ThermalService::unregisterThermalEventListener(
+    const sp<IThermalEventListener>& listener) {
+    if (listener == NULL)
+        return binder::Status::ok();
+    Mutex::Autolock _l(mListenersLock);
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (IInterface::asBinder(mListeners[i]) ==
+            IInterface::asBinder(listener)) {
+            IInterface::asBinder(mListeners[i])->unlinkToDeath(this);
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+
+    return binder::Status::ok();
+}
+
+void ThermalService::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(mListenersLock);
+
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (IInterface::asBinder(mListeners[i]) == who) {
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+}
+
+/**
+ * Publish the supplied ThermalService to servicemanager.
+ */
+void ThermalService::publish(
+    const sp<ThermalService>& service) {
+    defaultServiceManager()->addService(String16("thermalservice"),
+                                        service);
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/services/thermalservice/ThermalService.h b/services/thermalservice/ThermalService.h
new file mode 100644
index 0000000..17dfcbc
--- /dev/null
+++ b/services/thermalservice/ThermalService.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICE_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICE_H
+
+#include <android/os/BnThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace os {
+
+class ThermalService : public BnThermalService,
+                       public IBinder::DeathRecipient {
+public:
+  ThermalService() : mThrottled(false) {};
+    void publish(const sp<ThermalService>& service);
+    binder::Status notifyThrottling(
+        const bool isThrottling, const Temperature& temperature);
+
+private:
+    Mutex mListenersLock;
+    Vector<sp<IThermalEventListener> > mListeners;
+    bool mThrottled;
+    Temperature mThrottleTemperature;
+
+    binder::Status registerThermalEventListener(
+        const sp<IThermalEventListener>& listener);
+    binder::Status unregisterThermalEventListener(
+        const sp<IThermalEventListener>& listener);
+    binder::Status isThrottling(bool* _aidl_return);
+    void binderDied(const wp<IBinder>& who);
+};
+
+};  // namespace os
+};  // namespace android
+
+#endif // ANDROID_THERMALSERVICE_THERMALSERVICE_H
diff --git a/services/thermalservice/aidl/android/os/IThermalEventListener.aidl b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
new file mode 100644
index 0000000..050325e
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.os.Temperature;
+
+/**
+  * Listener for thermal events.
+  * {@hide}
+  */
+oneway interface IThermalEventListener {
+    /**
+     * Called when a thermal throttling start/stop event is received.
+     * @param temperature the temperature at which the event was generated.
+     */
+    void notifyThrottling(
+        in boolean isThrottling, in Temperature temperature);
+}
diff --git a/services/thermalservice/aidl/android/os/IThermalService.aidl b/services/thermalservice/aidl/android/os/IThermalService.aidl
new file mode 100644
index 0000000..e699202
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalService.aidl
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+
+/** {@hide} */
+interface IThermalService {
+    /**
+      * Register a listener for thermal events.
+      * @param listener the IThermalEventListener to be notified.
+      * {@hide}
+      */
+    void registerThermalEventListener(in IThermalEventListener listener);
+    /**
+      * Unregister a previously-registered listener for thermal events.
+      * @param listener the IThermalEventListener to no longer be notified.
+      * {@hide}
+      */
+    void unregisterThermalEventListener(in IThermalEventListener listener);
+    /**
+      * Send a thermal throttling start/stop notification to all listeners.
+      * @param temperature the temperature at which the event was generated.
+      * {@hide}
+      */
+    oneway void notifyThrottling(
+        in boolean isThrottling, in Temperature temperature);
+    /**
+      * Return whether system performance is currently thermal throttling.
+      * {@hide}
+      */
+    boolean isThrottling();
+}
diff --git a/services/thermalservice/aidl/android/os/Temperature.aidl b/services/thermalservice/aidl/android/os/Temperature.aidl
new file mode 100644
index 0000000..0293c39
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.aidl
@@ -0,0 +1,5 @@
+package android.os;
+
+/* Encodes a temperature used by ThermalService. */
+
+parcelable Temperature cpp_header "android/os/Temperature.h";
diff --git a/services/thermalservice/aidl/android/os/Temperature.cpp b/services/thermalservice/aidl/android/os/Temperature.cpp
new file mode 100644
index 0000000..df207b7
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android/os/Temperature.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <binder/Parcel.h>
+#include <hardware/thermal.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+namespace android {
+namespace os {
+
+Temperature::Temperature() : value_(NAN), type_(DEVICE_TEMPERATURE_UNKNOWN) {}
+
+Temperature::Temperature(const float value, const int type) :
+    value_(value), type_(type)  {}
+
+Temperature::~Temperature() {}
+
+/*
+ * Parcel read/write code must be kept in sync with
+ * frameworks/base/core/java/android/os/Temperature.java
+ */
+
+status_t Temperature::readFromParcel(const Parcel* p) {
+    value_ = p->readFloat();
+    type_ = p->readInt32();
+    return OK;
+}
+
+status_t Temperature::writeToParcel(Parcel* p) const {
+    p->writeFloat(value_);
+    p->writeInt32(type_);
+    return OK;
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/services/thermalservice/aidl/android/os/Temperature.h b/services/thermalservice/aidl/android/os/Temperature.h
new file mode 100644
index 0000000..bbc5607
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.h
@@ -0,0 +1,33 @@
+#ifndef ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+#define ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+class Temperature : public Parcelable {
+ public:
+
+  Temperature();
+  Temperature(const float value, const int type);
+  ~Temperature() override;
+
+  float getValue() const {return value_;};
+  float getType() const {return type_;};
+
+  status_t writeToParcel(Parcel* parcel) const override;
+  status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+  // The value of the temperature as a float, or NAN if unknown.
+  float value_;
+  // The type of the temperature, an enum temperature_type from
+  // hardware/thermal.h
+  int type_;
+};
+
+}  // namespace os
+}  // namespace android
+
+#endif   // ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
diff --git a/services/thermalservice/libthermalcallback/Android.bp b/services/thermalservice/libthermalcallback/Android.bp
new file mode 100644
index 0000000..e98506e
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/Android.bp
@@ -0,0 +1,19 @@
+cc_library_shared {
+    name: "libthermalcallback",
+    srcs: [
+        "ThermalCallback.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    include_dirs: ["frameworks/native"],
+    shared_libs: [
+        "android.hardware.thermal@1.1",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libthermalservice",
+        "libutils",
+    ],
+}
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.cpp b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
new file mode 100644
index 0000000..5e094fa
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
@@ -0,0 +1,69 @@
+#define LOG_TAG "android.hardware.thermal.thermalcallback@1.1-impl"
+#include <log/log.h>
+
+#include "ThermalCallback.h"
+#include "services/thermalservice/ThermalService.h"
+#include <math.h>
+#include <android/os/Temperature.h>
+#include <hardware/thermal.h>
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::os::ThermalService;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+
+// Register a binder ThermalService object for sending events
+void ThermalCallback::registerThermalService(sp<ThermalService> thermalService)
+{
+    mThermalService = thermalService;
+}
+
+// Methods from IThermalCallback::V1_1 follow.
+Return<void> ThermalCallback::notifyThrottling(
+      bool isThrottling,
+      const android::hardware::thermal::V1_0::Temperature& temperature) {
+
+    // Convert HIDL IThermal Temperature to binder IThermalService Temperature.
+    if (mThermalService != nullptr) {
+        float value = NAN;
+        int type = DEVICE_TEMPERATURE_UNKNOWN;
+
+        switch(temperature.type) {
+          case TemperatureType::CPU:
+            type = DEVICE_TEMPERATURE_CPU;
+            break;
+          case TemperatureType::GPU:
+            type = DEVICE_TEMPERATURE_GPU;
+            break;
+          case TemperatureType::BATTERY:
+            type = DEVICE_TEMPERATURE_BATTERY;
+            break;
+          case TemperatureType::SKIN:
+            type = DEVICE_TEMPERATURE_SKIN;
+            break;
+          case TemperatureType::UNKNOWN:
+          default:
+            type = DEVICE_TEMPERATURE_UNKNOWN;
+            break;
+        }
+
+        value = temperature.currentValue == UNKNOWN_TEMPERATURE ? NAN :
+            temperature.currentValue;
+
+        android::os::Temperature thermal_svc_temp(value, type);
+        mThermalService->notifyThrottling(isThrottling, thermal_svc_temp);
+    } else {
+        ALOGE("IThermalService binder service not created, drop throttling event");
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.h b/services/thermalservice/libthermalcallback/ThermalCallback.h
new file mode 100644
index 0000000..3d72c68
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.h
@@ -0,0 +1,43 @@
+#ifndef ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+#define ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+#include <android/os/Temperature.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "services/thermalservice/ThermalService.h"
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::os::ThermalService;
+
+class ThermalCallback : public IThermalCallback {
+ public:
+    // Register a binder ThermalService object for sending events
+    void registerThermalService(sp<ThermalService> thermalService);
+
+    // Methods from IThermalCallback::V1_1 follow.
+    Return<void> notifyThrottling(
+        bool isThrottling,
+        const android::hardware::thermal::V1_0::Temperature& temperature)
+        override;
+
+ private:
+    // Our registered binder ThermalService object to use for sending events
+    sp<android::os::ThermalService> mThermalService;
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
diff --git a/services/thermalservice/thermalservice.rc b/services/thermalservice/thermalservice.rc
new file mode 100644
index 0000000..b9836ce
--- /dev/null
+++ b/services/thermalservice/thermalservice.rc
@@ -0,0 +1,2 @@
+service thermalservice /system/bin/thermalserviced
+    class core
diff --git a/services/thermalservice/thermalserviced.cpp b/services/thermalservice/thermalserviced.cpp
new file mode 100644
index 0000000..8e27266
--- /dev/null
+++ b/services/thermalservice/thermalserviced.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "thermalserviced"
+#include <log/log.h>
+
+#include "thermalserviced.h"
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+#include <android/hardware/thermal/1.1/IThermal.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
+
+using namespace android;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::os::ThermalService;
+
+template<typename T>
+using Return = hardware::Return<T>;
+
+namespace {
+
+// Our thermalserviced main object
+ThermalServiceDaemon* gThermalServiceDaemon;
+
+// Thermal HAL client
+sp<IThermal> gThermalHal = nullptr;
+
+// Binder death notifier informing of Thermal HAL death.
+struct ThermalServiceDeathRecipient : hidl_death_recipient {
+    virtual void serviceDied(
+        uint64_t cookie __unused, const wp<IBase>& who __unused) {
+        gThermalHal = nullptr;
+        ALOGE("IThermal HAL died");
+        gThermalServiceDaemon->getThermalHal();
+    }
+};
+
+sp<ThermalServiceDeathRecipient> gThermalHalDied = nullptr;
+
+}  // anonymous namespace
+
+void ThermalServiceDaemon::thermalServiceStartup() {
+    // Binder IThermalService startup
+    mThermalService = new android::os::ThermalService;
+    mThermalService->publish(mThermalService);
+    // Register IThermalService object with IThermalCallback
+    if (mThermalCallback != nullptr)
+        mThermalCallback->registerThermalService(mThermalService);
+    IPCThreadState::self()->joinThreadPool();
+}
+
+// Lookup Thermal HAL, register death notifier, register our
+// ThermalCallback with the Thermal HAL.
+void ThermalServiceDaemon::getThermalHal() {
+    gThermalHal = IThermal::getService();
+    if (gThermalHal == nullptr) {
+        ALOGW("Unable to get Thermal HAL V1.1, vendor thermal event notification not available");
+        return;
+    }
+
+    // Binder death notifier for Thermal HAL
+    if (gThermalHalDied == nullptr)
+        gThermalHalDied = new ThermalServiceDeathRecipient();
+
+    if (gThermalHalDied != nullptr)
+        gThermalHal->linkToDeath(gThermalHalDied, 0x451F /* cookie */);
+
+    if (mThermalCallback != nullptr) {
+        Return<void> ret = gThermalHal->registerThermalCallback(
+            mThermalCallback);
+        if (!ret.isOk())
+            ALOGE("registerThermalCallback failed, status: %s",
+                  ret.description().c_str());
+    }
+}
+
+void ThermalServiceDaemon::thermalCallbackStartup() {
+    // HIDL IThermalCallback startup
+    // Need at least 2 threads in thread pool since we wait for dead HAL
+    // to come back on the binder death notification thread and we need
+    // another thread for the incoming service now available call.
+    configureRpcThreadpool(2, false /* callerWillJoin */);
+    mThermalCallback = new ThermalCallback();
+    // Lookup Thermal HAL and register our ThermalCallback.
+    getThermalHal();
+}
+
+int main(int /*argc*/, char** /*argv*/) {
+    gThermalServiceDaemon = new ThermalServiceDaemon();
+    gThermalServiceDaemon->thermalCallbackStartup();
+    gThermalServiceDaemon->thermalServiceStartup();
+    /* NOTREACHED */
+}
diff --git a/services/thermalservice/thermalserviced.h b/services/thermalservice/thermalserviced.h
new file mode 100644
index 0000000..309e2fe
--- /dev/null
+++ b/services/thermalservice/thermalserviced.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICED_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICED_H
+
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+using namespace android;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::os::ThermalService;
+
+class ThermalServiceDaemon {
+ public:
+    void thermalServiceStartup();
+    void thermalCallbackStartup();
+    void getThermalHal();
+    ThermalServiceDaemon() {};
+
+ private:
+    sp<ThermalService> mThermalService;
+    sp<ThermalCallback> mThermalCallback;
+};
+
+#endif  // ANDROID_THERMALSERVICE_THERMALSERVICED_H
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index 97f0332..28cf53d 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -22,6 +22,9 @@
     consumer_queue_channel.cpp \
     producer_queue_channel.cpp \
 
+headerLibraries := \
+	libdvr_headers
+
 staticLibraries := \
 	libperformance \
 	libpdx_default_transport \
@@ -41,6 +44,7 @@
 LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\"
 LOCAL_CFLAGS += -DTRACE=0
 LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
+LOCAL_HEADER_LIBRARIES := $(headerLibraries)
 LOCAL_STATIC_LIBRARIES := $(staticLibraries)
 LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
 LOCAL_MODULE := bufferhubd
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index d27f274..cdb1f91 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -20,8 +20,8 @@
 using android::pdx::ErrorStatus;
 using android::pdx::Message;
 using android::pdx::Status;
-using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::default_transport::Endpoint;
+using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
 namespace dvr {
@@ -53,7 +53,15 @@
   stream << " ";
   stream << std::setw(6) << "Format";
   stream << " ";
-  stream << std::setw(11) << "Usage";
+  stream << std::setw(10) << "Usage";
+  stream << " ";
+  stream << std::setw(9) << "Pending";
+  stream << " ";
+  stream << std::setw(18) << "State";
+  stream << " ";
+  stream << std::setw(18) << "Signaled";
+  stream << " ";
+  stream << std::setw(10) << "Index";
   stream << " ";
   stream << "Name";
   stream << std::endl;
@@ -83,46 +91,15 @@
       stream << std::setw(8) << info.usage;
       stream << std::dec << std::setfill(' ');
       stream << " ";
-      stream << info.name;
-      stream << std::endl;
-    }
-  }
-
-  stream << "Active Consumer Buffers:\n";
-  stream << std::right;
-  stream << std::setw(6) << "Id";
-  stream << " ";
-  stream << std::setw(14) << "Geometry";
-  stream << " ";
-  stream << "Name";
-  stream << std::endl;
-
-  for (const auto& channel : channels) {
-    if (channel->channel_type() == BufferHubChannel::kConsumerType) {
-      BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
-
-      stream << std::right;
-      stream << std::setw(6) << info.id;
+      stream << std::setw(9) << info.pending_count;
       stream << " ";
-
-      if (info.consumer_count == 0) {
-        // consumer_count is tracked by producer. When it's zero, producer must
-        // have already hung up and the consumer is orphaned.
-        stream << std::setw(14) << "Orphaned.";
-        stream << (" channel_id=" + std::to_string(channel->channel_id()));
-        stream << std::endl;
-        continue;
-      }
-
-      if (info.format == HAL_PIXEL_FORMAT_BLOB) {
-        std::string size = std::to_string(info.width) + " B";
-        stream << std::setw(14) << size;
-      } else {
-        std::string dimensions = std::to_string(info.width) + "x" +
-                                 std::to_string(info.height) + "x" +
-                                 std::to_string(info.layer_count);
-        stream << std::setw(14) << dimensions;
-      }
+      stream << "0x" << std::hex << std::setfill('0');
+      stream << std::setw(16) << info.state;
+      stream << " ";
+      stream << "0x" << std::setw(16) << info.signaled_mask;
+      stream << std::dec << std::setfill(' ');
+      stream << " ";
+      stream << std::setw(8) << info.index;
       stream << " ";
       stream << info.name;
       stream << std::endl;
@@ -184,6 +161,32 @@
     }
   }
 
+  stream << std::endl;
+  stream << "Orphaned Consumer Buffers:\n";
+  stream << std::right;
+  stream << std::setw(6) << "Id";
+  stream << " ";
+  stream << std::setw(14) << "Geometry";
+  stream << " ";
+  stream << "Name";
+  stream << std::endl;
+
+  for (const auto& channel : channels) {
+    BufferHubChannel::BufferInfo info = channel->GetBufferInfo();
+    // consumer_count is tracked by producer. When it's zero, producer must have
+    // already hung up and the consumer is orphaned.
+    if (channel->channel_type() == BufferHubChannel::kConsumerType &&
+        info.consumer_count == 0) {
+      stream << std::right;
+      stream << std::setw(6) << info.id;
+      stream << " ";
+
+      stream << std::setw(14) << "Orphaned.";
+      stream << (" channel_id=" + std::to_string(channel->channel_id()));
+      stream << std::endl;
+    }
+  }
+
   return stream.str();
 }
 
@@ -382,7 +385,7 @@
 }
 
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
-    pdx::Message& message, size_t meta_size_bytes,
+    pdx::Message& message, const ProducerQueueConfig& producer_config,
     const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
@@ -396,11 +399,11 @@
     return ErrorStatus(EALREADY);
   }
 
-  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+  auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
                                              usage_policy);
   if (status) {
     message.SetChannel(status.take());
-    return {{meta_size_bytes, queue_id}};
+    return {{producer_config, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
     return status.error_status();
@@ -444,6 +447,7 @@
            "BufferHubChannel::SignalAvailable: channel_id=%d buffer_id=%d",
            channel_id(), buffer_id());
   if (!IsDetached()) {
+    signaled_ = true;
     const auto status = service_->ModifyChannelEvents(channel_id_, 0, POLLIN);
     ALOGE_IF(!status,
              "BufferHubChannel::SignalAvailable: failed to signal availability "
@@ -460,6 +464,7 @@
            "BufferHubChannel::ClearAvailable: channel_id=%d buffer_id=%d",
            channel_id(), buffer_id());
   if (!IsDetached()) {
+    signaled_ = false;
     const auto status = service_->ModifyChannelEvents(channel_id_, POLLIN, 0);
     ALOGE_IF(!status,
              "BufferHubChannel::ClearAvailable: failed to clear availability "
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 3bc2635..270ac95 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -53,6 +53,10 @@
     uint32_t layer_count = 0;
     uint32_t format = 0;
     uint64_t usage = 0;
+    size_t pending_count = 0;
+    uint64_t state = 0;
+    uint64_t signaled_mask = 0;
+    uint64_t index = 0;
     std::string name;
 
     // Data filed for producer queue.
@@ -60,7 +64,9 @@
     UsagePolicy usage_policy{0, 0, 0, 0};
 
     BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
-               uint32_t layer_count, uint32_t format, uint64_t usage, const std::string& name)
+               uint32_t layer_count, uint32_t format, uint64_t usage,
+               size_t pending_count, uint64_t state, uint64_t signaled_mask,
+               uint64_t index, const std::string& name)
         : id(id),
           type(kProducerType),
           consumer_count(consumer_count),
@@ -69,6 +75,10 @@
           layer_count(layer_count),
           format(format),
           usage(usage),
+          pending_count(pending_count),
+          state(state),
+          signaled_mask(signaled_mask),
+          index(index),
           name(name) {}
 
     BufferInfo(int id, size_t consumer_count, size_t capacity,
@@ -101,6 +111,8 @@
   int channel_id() const { return channel_id_; }
   bool IsDetached() const { return channel_id_ == kDetachedId; }
 
+  bool signaled() const { return signaled_; }
+
   void Detach() {
     if (channel_type_ == kProducerType)
       channel_id_ = kDetachedId;
@@ -124,6 +136,8 @@
   // buffer if it is detached and re-attached to another channel.
   int channel_id_;
 
+  bool signaled_;
+
   ChannelType channel_type_;
 
   BufferHubChannel(const BufferHubChannel&) = delete;
@@ -166,9 +180,9 @@
                                              size_t meta_size_bytes);
   pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
                                           const std::string& name);
-  pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
-                                               size_t meta_size_bytes,
-                                               const UsagePolicy& usage_policy);
+  pdx::Status<QueueInfo> OnCreateProducerQueue(
+      pdx::Message& message, const ProducerQueueConfig& producer_config,
+      const UsagePolicy& usage_policy);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index d4fc540..b27f218 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -2,9 +2,10 @@
 #include <unistd.h>
 
 #include <log/log.h>
+#include <sys/resource.h>
 
 #include <dvr/performance_client_api.h>
-#include <pdx/default_transport/service_dispatcher.h>
+#include <pdx/service_dispatcher.h>
 
 #include "buffer_hub.h"
 
@@ -16,7 +17,24 @@
   // We need to be able to create endpoints with full perms.
   umask(0000);
 
-  dispatcher = android::pdx::default_transport::ServiceDispatcher::Create();
+  // Bump up the soft limit of open fd to the hard limit.
+  struct rlimit64 rlim;
+  ret = getrlimit64(RLIMIT_NOFILE, &rlim);
+  LOG_ALWAYS_FATAL_IF(ret != 0, "Failed to get nofile limit.");
+
+  ALOGI("Current nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
+  rlim.rlim_cur = rlim.rlim_max;
+  ret = setrlimit64(RLIMIT_NOFILE, &rlim);
+  ALOGE_IF(ret < 0, "Failed to set nofile limit, error=%s", strerror(errno));
+
+  rlim.rlim_cur = -1;
+  rlim.rlim_max = -1;
+  if (getrlimit64(RLIMIT_NOFILE, &rlim) < 0)
+    ALOGE("Failed to get nofile limit.");
+  else
+    ALOGI("New nofile limit is %llu/%llu.", rlim.rlim_cur, rlim.rlim_max);
+
+  dispatcher = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher\n");
 
   service = android::dvr::BufferHubService::Create();
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 08b2790..a6d2dbb 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,9 @@
 #include <private/dvr/bufferhub_rpc.h>
 #include "producer_channel.h"
 
-using android::pdx::ErrorStatus;
 using android::pdx::BorrowedHandle;
 using android::pdx::Channel;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
 using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
@@ -19,11 +19,10 @@
 namespace dvr {
 
 ConsumerChannel::ConsumerChannel(BufferHubService* service, int buffer_id,
-                                 int channel_id,
+                                 int channel_id, uint64_t consumer_state_bit,
                                  const std::shared_ptr<Channel> producer)
     : BufferHubChannel(service, buffer_id, channel_id, kConsumerType),
-      handled_(true),
-      ignored_(false),
+      consumer_state_bit_(consumer_state_bit),
       producer_(producer) {
   GetProducer()->AddConsumer(this);
 }
@@ -34,8 +33,6 @@
            channel_id(), buffer_id());
 
   if (auto producer = GetProducer()) {
-    if (!handled_)  // Producer is waiting for our Release.
-      producer->OnConsumerIgnored();
     producer->RemoveConsumer(this);
   }
 }
@@ -45,6 +42,8 @@
   if (auto producer = GetProducer()) {
     // If producer has not hung up, copy most buffer info from the producer.
     info = producer->GetBufferInfo();
+  } else {
+    info.signaled_mask = consumer_state_bit();
   }
   info.id = buffer_id();
   return info;
@@ -57,6 +56,9 @@
 void ConsumerChannel::HandleImpulse(Message& message) {
   ATRACE_NAME("ConsumerChannel::HandleImpulse");
   switch (message.GetOp()) {
+    case BufferHubRPC::ConsumerAcquire::Opcode:
+      OnConsumerAcquire(message);
+      break;
     case BufferHubRPC::ConsumerRelease::Opcode:
       OnConsumerRelease(message, {});
       break;
@@ -72,7 +74,7 @@
   switch (message.GetOp()) {
     case BufferHubRPC::GetBuffer::Opcode:
       DispatchRemoteMethod<BufferHubRPC::GetBuffer>(
-          *producer, &ProducerChannel::OnGetBuffer, message);
+          *this, &ConsumerChannel::OnGetBuffer, message);
       return true;
 
     case BufferHubRPC::NewConsumer::Opcode:
@@ -100,23 +102,37 @@
   }
 }
 
-Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
-ConsumerChannel::OnConsumerAcquire(Message& message,
-                                   std::size_t metadata_size) {
+Status<BufferDescription<BorrowedHandle>> ConsumerChannel::OnGetBuffer(
+    Message& /*message*/) {
+  ATRACE_NAME("ConsumerChannel::OnGetBuffer");
+  ALOGD_IF(TRACE, "ConsumerChannel::OnGetBuffer: buffer=%d", buffer_id());
+  if (auto producer = GetProducer()) {
+    return {producer->GetBuffer(consumer_state_bit_)};
+  } else {
+    return ErrorStatus(EPIPE);
+  }
+}
+
+Status<LocalFence> ConsumerChannel::OnConsumerAcquire(Message& message) {
   ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
   auto producer = GetProducer();
   if (!producer)
     return ErrorStatus(EPIPE);
 
-  if (ignored_ || handled_) {
+  if (acquired_ || released_) {
     ALOGE(
         "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
-        "ignored=%d handled=%d channel_id=%d buffer_id=%d",
-        ignored_, handled_, message.GetChannelId(), producer->buffer_id());
+        "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
+        ignored_, acquired_, released_, message.GetChannelId(),
+        producer->buffer_id());
     return ErrorStatus(EBUSY);
   } else {
-    ClearAvailable();
-    return producer->OnConsumerAcquire(message, metadata_size);
+    auto status = producer->OnConsumerAcquire(message);
+    if (status) {
+      ClearAvailable();
+      acquired_ = true;
+    }
+    return status;
   }
 }
 
@@ -127,17 +143,21 @@
   if (!producer)
     return ErrorStatus(EPIPE);
 
-  if (ignored_ || handled_) {
+  if (!acquired_ || released_) {
     ALOGE(
         "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
-        "ignored=%d handled=%d channel_id=%d buffer_id=%d",
-        ignored_, handled_, message.GetChannelId(), producer->buffer_id());
+        "ignored=%d acquired=%d released=%d channel_id=%d buffer_id=%d",
+        ignored_, acquired_, released_, message.GetChannelId(),
+        producer->buffer_id());
     return ErrorStatus(EBUSY);
   } else {
-    ClearAvailable();
     auto status =
         producer->OnConsumerRelease(message, std::move(release_fence));
-    handled_ = !!status;
+    if (status) {
+      ClearAvailable();
+      acquired_ = false;
+      released_ = true;
+    }
     return status;
   }
 }
@@ -149,12 +169,13 @@
     return ErrorStatus(EPIPE);
 
   ignored_ = ignored;
-  if (ignored_ && !handled_) {
+  if (ignored_ && acquired_) {
     // Update the producer if ignore is set after the consumer acquires the
     // buffer.
     ClearAvailable();
     producer->OnConsumerIgnored();
-    handled_ = false;
+    acquired_ = false;
+    released_ = true;
   }
 
   return {};
@@ -162,10 +183,12 @@
 
 bool ConsumerChannel::OnProducerPosted() {
   if (ignored_) {
-    handled_ = true;
+    acquired_ = false;
+    released_ = true;
     return false;
   } else {
-    handled_ = false;
+    acquired_ = false;
+    released_ = false;
     SignalAvailable();
     return true;
   }
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d84055c..55cf969 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -12,34 +12,38 @@
 // Consumer channels are attached to a Producer channel
 class ConsumerChannel : public BufferHubChannel {
  public:
+  using BorrowedHandle = pdx::BorrowedHandle;
   using Channel = pdx::Channel;
   using Message = pdx::Message;
 
   ConsumerChannel(BufferHubService* service, int buffer_id, int channel_id,
+                  uint64_t consumer_state_bit,
                   const std::shared_ptr<Channel> producer);
   ~ConsumerChannel() override;
 
   bool HandleMessage(Message& message) override;
   void HandleImpulse(Message& message) override;
 
+  uint64_t consumer_state_bit() const { return consumer_state_bit_; }
   BufferInfo GetBufferInfo() const override;
 
   bool OnProducerPosted();
   void OnProducerClosed();
 
  private:
-  using MetaData = pdx::rpc::BufferWrapper<std::uint8_t*>;
-
   std::shared_ptr<ProducerChannel> GetProducer() const;
 
-  pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
-      Message& message, std::size_t metadata_size);
+  pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message);
+
+  pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
   pdx::Status<void> OnConsumerRelease(Message& message,
                                       LocalFence release_fence);
   pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
 
-  bool handled_;  // True if we have processed RELEASE.
-  bool ignored_;  // True if we are ignoring events.
+  uint64_t consumer_state_bit_{0};
+  bool acquired_{false};
+  bool released_{true};
+  bool ignored_{false};  // True if we are ignoring events.
   std::weak_ptr<Channel> producer_;
 
   ConsumerChannel(const ConsumerChannel&) = delete;
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index f447e00..4d43001 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -15,10 +15,11 @@
 
 ConsumerQueueChannel::ConsumerQueueChannel(
     BufferHubService* service, int buffer_id, int channel_id,
-    const std::shared_ptr<Channel>& producer)
+    const std::shared_ptr<Channel>& producer, bool silent)
     : BufferHubChannel(service, buffer_id, channel_id, kConsumerQueueType),
       producer_(producer),
-      capacity_(0) {
+      capacity_(0),
+      silent_(silent) {
   GetProducer()->AddConsumer(this);
 }
 
@@ -83,23 +84,30 @@
 void ConsumerQueueChannel::RegisterNewBuffer(
     const std::shared_ptr<ProducerChannel>& producer_channel, size_t slot) {
   ALOGD_IF(TRACE,
-           "ConsumerQueueChannel::RegisterNewBuffer: buffer_id=%d slot=%zu",
-           producer_channel->buffer_id(), slot);
-  pending_buffer_slots_.emplace(producer_channel, slot);
+           "ConsumerQueueChannel::RegisterNewBuffer: queue_id=%d buffer_id=%d "
+           "slot=%zu silent=%d",
+           buffer_id(), producer_channel->buffer_id(), slot, silent_);
+  // Only register buffers if the queue is not silent.
+  if (!silent_) {
+    pending_buffer_slots_.emplace(producer_channel, slot);
 
-  // Signal the client that there is new buffer available throught POLLIN.
-  SignalAvailable();
+    // Signal the client that there is new buffer available.
+    SignalAvailable();
+  }
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
 ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
   ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
-  ALOGD_IF(
-      TRACE,
-      "ConsumerQueueChannel::OnConsumerQueueImportBuffers number of buffers to "
-      "import: %zu",
-      pending_buffer_slots_.size());
+  ALOGD_IF(TRACE,
+           "ConsumerQueueChannel::OnConsumerQueueImportBuffers: "
+           "pending_buffer_slots=%zu",
+           pending_buffer_slots_.size());
+
+  // Indicate this is a silent queue that will not import buffers.
+  if (silent_)
+    return ErrorStatus(EBADR);
 
   while (!pending_buffer_slots_.empty()) {
     auto producer_channel = pending_buffer_slots_.front().first.lock();
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index aa3f531..8437c4c 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -19,7 +19,7 @@
   using RemoteChannelHandle = pdx::RemoteChannelHandle;
 
   ConsumerQueueChannel(BufferHubService* service, int buffer_id, int channel_id,
-                       const std::shared_ptr<Channel>& producer);
+                       const std::shared_ptr<Channel>& producer, bool silent);
   ~ConsumerQueueChannel() override;
 
   bool HandleMessage(Message& message) override;
@@ -54,6 +54,10 @@
   // Tracks how many buffers have this queue imported.
   size_t capacity_;
 
+  // A silent queue does not signal or export buffers. It is only used to spawn
+  // another consumer queue.
+  bool silent_;
+
   ConsumerQueueChannel(const ConsumerQueueChannel&) = delete;
   void operator=(const ConsumerQueueChannel&) = delete;
 };
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index b9984a0..716db5e 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -2,6 +2,8 @@
 
 #include <log/log.h>
 #include <sync/sync.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
 #include <sys/poll.h>
 #include <utils/Trace.h>
 
@@ -24,24 +26,88 @@
 namespace android {
 namespace dvr {
 
+namespace {
+
+static inline uint64_t FindNextClearedBit(uint64_t bits) {
+  return ~bits - (~bits & (~bits - 1));
+}
+
+}  // namespace
+
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
                                  uint32_t width, uint32_t height,
                                  uint32_t layer_count, uint32_t format,
-                                 uint64_t usage, size_t meta_size_bytes,
+                                 uint64_t usage, size_t user_metadata_size,
                                  int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerType),
       pending_consumers_(0),
       producer_owns_(true),
-      meta_size_bytes_(meta_size_bytes),
-      meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
-  const int ret = buffer_.Alloc(width, height, layer_count, format, usage);
-  if (ret < 0) {
+      user_metadata_size_(user_metadata_size),
+      metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
+                         user_metadata_size) {
+  if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
     ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
           strerror(-ret));
     *error = ret;
     return;
   }
 
+  if (int ret = metadata_buffer_.Alloc(metadata_buf_size_, /*height=*/1,
+                                       /*layer_count=*/1,
+                                       BufferHubDefs::kMetadataFormat,
+                                       BufferHubDefs::kMetadataUsage)) {
+    ALOGE("ProducerChannel::ProducerChannel: Failed to allocate metadata: %s",
+          strerror(-ret));
+    *error = ret;
+    return;
+  }
+
+  void* metadata_ptr = nullptr;
+  if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+                                      /*y=*/0, metadata_buf_size_,
+                                      /*height=*/1, &metadata_ptr)) {
+    ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata.");
+    *error = -ret;
+    return;
+  }
+  metadata_header_ =
+      reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+
+  // Using placement new here to reuse shared memory instead of new allocation
+  // and also initialize the value to zero.
+  buffer_state_ =
+      new (&metadata_header_->buffer_state) std::atomic<uint64_t>(0);
+  fence_state_ =
+      new (&metadata_header_->fence_state) std::atomic<uint64_t>(0);
+
+  acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
+  release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
+  if (!acquire_fence_fd_ || !release_fence_fd_) {
+    ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
+    *error = -EIO;
+    return;
+  }
+
+  dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  if (!dummy_fence_fd_) {
+    ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
+    *error = -EIO;
+    return;
+  }
+
+  epoll_event event;
+  event.events = 0;
+  event.data.u64 = 0ULL;
+  if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_ADD, dummy_fence_fd_.Get(),
+                &event) < 0) {
+    ALOGE(
+        "ProducerChannel::ProducerChannel: Failed to modify the shared "
+        "release fence to include the dummy fence: %s",
+        strerror(errno));
+    *error = -EIO;
+    return;
+  }
+
   // Success.
   *error = 0;
 }
@@ -49,11 +115,11 @@
 Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
     BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
     uint32_t layer_count, uint32_t format, uint64_t usage,
-    size_t meta_size_bytes) {
+    size_t user_metadata_size) {
   int error;
   std::shared_ptr<ProducerChannel> producer(
       new ProducerChannel(service, channel_id, width, height, layer_count,
-                          format, usage, meta_size_bytes, &error));
+                          format, usage, user_metadata_size, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -62,16 +128,24 @@
 
 ProducerChannel::~ProducerChannel() {
   ALOGD_IF(TRACE,
-           "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d",
-           channel_id(), buffer_id());
+           "ProducerChannel::~ProducerChannel: channel_id=%d buffer_id=%d "
+           "state=%" PRIx64 ".",
+           channel_id(), buffer_id(), buffer_state_->load());
   for (auto consumer : consumer_channels_)
     consumer->OnProducerClosed();
 }
 
 BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
+  // Derive the mask of signaled buffers in this producer / consumer set.
+  uint64_t signaled_mask = signaled() ? BufferHubDefs::kProducerStateBit : 0;
+  for (const ConsumerChannel* consumer : consumer_channels_) {
+    signaled_mask |= consumer->signaled() ? consumer->consumer_state_bit() : 0;
+  }
+
   return BufferInfo(buffer_id(), consumer_channels_.size(), buffer_.width(),
                     buffer_.height(), buffer_.layer_count(), buffer_.format(),
-                    buffer_.usage(), name_);
+                    buffer_.usage(), pending_consumers_, buffer_state_->load(),
+                    signaled_mask, metadata_header_->queue_index, name_);
 }
 
 void ProducerChannel::HandleImpulse(Message& message) {
@@ -80,6 +154,9 @@
     case BufferHubRPC::ProducerGain::Opcode:
       OnProducerGain(message);
       break;
+    case BufferHubRPC::ProducerPost::Opcode:
+      OnProducerPost(message, {});
+      break;
   }
 }
 
@@ -121,16 +198,26 @@
   }
 }
 
-Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
-    Message& message) {
+BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
+    uint64_t buffer_state_bit) {
+  return {
+      buffer_,          metadata_buffer_,           buffer_id(),
+      buffer_state_bit, acquire_fence_fd_.Borrow(), release_fence_fd_.Borrow()};
+}
+
+Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
+    Message& /*message*/) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
-  ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
-  return {NativeBufferHandle<BorrowedHandle>(buffer_, buffer_id())};
+  ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx64 ".",
+           buffer_id(), buffer_state_->load());
+  return {GetBuffer(BufferHubDefs::kProducerStateBit)};
 }
 
 Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::CreateConsumer");
-  ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
+  ALOGD_IF(TRACE,
+           "ProducerChannel::CreateConsumer: buffer_id=%d, producer_owns=%d",
+           buffer_id(), producer_owns_);
 
   int channel_id;
   auto status = message.PushChannel(0, nullptr, &channel_id);
@@ -141,8 +228,21 @@
     return ErrorStatus(ENOMEM);
   }
 
-  auto consumer = std::make_shared<ConsumerChannel>(
-      service(), buffer_id(), channel_id, shared_from_this());
+  // Try find the next consumer state bit which has not been claimed by any
+  // consumer yet.
+  uint64_t consumer_state_bit = FindNextClearedBit(
+      active_consumer_bit_mask_ | orphaned_consumer_bit_mask_ |
+      BufferHubDefs::kProducerStateBit);
+  if (consumer_state_bit == 0ULL) {
+    ALOGE(
+        "ProducerChannel::CreateConsumer: reached the maximum mumber of "
+        "consumers per producer: 63.");
+    return ErrorStatus(E2BIG);
+  }
+
+  auto consumer =
+      std::make_shared<ConsumerChannel>(service(), buffer_id(), channel_id,
+                                        consumer_state_bit, shared_from_this());
   const auto channel_status = service()->SetChannel(channel_id, consumer);
   if (!channel_status) {
     ALOGE(
@@ -152,12 +252,14 @@
     return ErrorStatus(ENOMEM);
   }
 
-  if (!producer_owns_) {
+  if (!producer_owns_ &&
+      !BufferHubDefs::IsBufferReleased(buffer_state_->load())) {
     // Signal the new consumer when adding it to a posted producer.
     if (consumer->OnProducerPosted())
       pending_consumers_++;
   }
 
+  active_consumer_bit_mask_ |= consumer_state_bit;
   return {status.take()};
 }
 
@@ -168,8 +270,7 @@
 }
 
 Status<void> ProducerChannel::OnProducerPost(
-    Message&, LocalFence acquire_fence,
-    BufferWrapper<std::vector<std::uint8_t>> metadata) {
+    Message&, LocalFence acquire_fence) {
   ATRACE_NAME("ProducerChannel::OnProducerPost");
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
   if (!producer_owns_) {
@@ -177,34 +278,52 @@
     return ErrorStatus(EBUSY);
   }
 
-  if (meta_size_bytes_ != metadata.size()) {
-    ALOGD_IF(TRACE,
-             "ProducerChannel::OnProducerPost: Expected meta_size_bytes=%zu "
-             "got size=%zu",
-             meta_size_bytes_, metadata.size());
-    return ErrorStatus(EINVAL);
+  epoll_event event;
+  event.events = 0;
+  event.data.u64 = 0ULL;
+  int ret = epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
+                      dummy_fence_fd_.Get(), &event);
+  ALOGE_IF(ret < 0,
+      "ProducerChannel::OnProducerPost: Failed to modify the shared "
+      "release fence to include the dummy fence: %s",
+      strerror(errno));
+
+  eventfd_t dummy_fence_count = 0ULL;
+  if (eventfd_read(dummy_fence_fd_.Get(), &dummy_fence_count) < 0) {
+    const int error = errno;
+    if (error != EAGAIN) {
+      ALOGE(
+          "ProducerChannel::ProducerChannel: Failed to read dummy fence, "
+          "error: %s",
+          strerror(error));
+      return ErrorStatus(error);
+    }
   }
 
-  std::copy(metadata.begin(), metadata.end(), meta_.get());
+  ALOGW_IF(dummy_fence_count > 0,
+           "ProducerChannel::ProducerChannel: %" PRIu64
+           " dummy fence(s) was signaled during last release/gain cycle "
+           "buffer_id=%d.",
+           dummy_fence_count, buffer_id());
+
   post_fence_ = std::move(acquire_fence);
   producer_owns_ = false;
 
-  // Signal any interested consumers. If there are none, automatically release
-  // the buffer.
+  // Signal any interested consumers. If there are none, the buffer will stay
+  // in posted state until a consumer comes online. This behavior guarantees
+  // that no frame is silently dropped.
   pending_consumers_ = 0;
   for (auto consumer : consumer_channels_) {
     if (consumer->OnProducerPosted())
       pending_consumers_++;
   }
-  if (pending_consumers_ == 0)
-    SignalAvailable();
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
            pending_consumers_);
 
   return {};
 }
 
-Status<LocalFence> ProducerChannel::OnProducerGain(Message& message) {
+Status<LocalFence> ProducerChannel::OnProducerGain(Message& /*message*/) {
   ATRACE_NAME("ProducerChannel::OnGain");
   ALOGD_IF(TRACE, "ProducerChannel::OnGain: buffer_id=%d", buffer_id());
   if (producer_owns_) {
@@ -214,8 +333,13 @@
   }
 
   // There are still pending consumers, return busy.
-  if (pending_consumers_ > 0)
+  if (pending_consumers_ > 0) {
+    ALOGE(
+        "ProducerChannel::OnGain: Producer (id=%d) is gaining a buffer that "
+        "still has %d pending consumer(s).",
+        buffer_id(), pending_consumers_);
     return ErrorStatus(EBUSY);
+  }
 
   ClearAvailable();
   producer_owns_ = true;
@@ -223,9 +347,7 @@
   return {std::move(returned_fence_)};
 }
 
-Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
-ProducerChannel::OnConsumerAcquire(Message& message,
-                                   std::size_t metadata_size) {
+Status<LocalFence> ProducerChannel::OnConsumerAcquire(Message& /*message*/) {
   ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
   ALOGD_IF(TRACE, "ProducerChannel::OnConsumerAcquire: buffer_id=%d",
            buffer_id());
@@ -236,12 +358,7 @@
 
   // Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
   // Serialization just needs to read the handle.
-  if (metadata_size == 0)
-    return {std::make_pair(post_fence_.borrow(),
-                           WrapBuffer<std::uint8_t>(nullptr, 0))};
-  else
-    return {std::make_pair(post_fence_.borrow(),
-                           WrapBuffer(meta_.get(), meta_size_bytes_))};
+  return {std::move(post_fence_)};
 }
 
 Status<void> ProducerChannel::OnConsumerRelease(Message&,
@@ -273,17 +390,75 @@
   }
 
   OnConsumerIgnored();
+  if (pending_consumers_ == 0) {
+    // Clear the producer bit atomically to transit into released state. This
+    // has to done by BufferHub as it requries synchronization among all
+    // consumers.
+    BufferHubDefs::ModifyBufferState(buffer_state_,
+                                     BufferHubDefs::kProducerStateBit, 0ULL);
+    ALOGD_IF(TRACE,
+             "ProducerChannel::OnConsumerRelease: releasing last consumer: "
+             "buffer_id=%d state=%" PRIx64 ".",
+             buffer_id(), buffer_state_->load());
+
+    if (orphaned_consumer_bit_mask_) {
+      ALOGW(
+          "ProducerChannel::OnConsumerRelease: orphaned buffer detected "
+          "during the this acquire/release cycle: id=%d orphaned=0x%" PRIx64
+          " queue_index=%" PRIu64 ".",
+          buffer_id(), orphaned_consumer_bit_mask_,
+          metadata_header_->queue_index);
+      orphaned_consumer_bit_mask_ = 0;
+    }
+
+    SignalAvailable();
+  }
+
+  ALOGE_IF(pending_consumers_ &&
+               BufferHubDefs::IsBufferReleased(buffer_state_->load()),
+           "ProducerChannel::OnConsumerRelease: buffer state inconsistent: "
+           "pending_consumers=%d, buffer buffer is in releaed state.",
+           pending_consumers_);
   return {};
 }
 
 void ProducerChannel::OnConsumerIgnored() {
-  if (!--pending_consumers_)
-    SignalAvailable();
+  if (pending_consumers_ == 0) {
+    ALOGE("ProducerChannel::OnConsumerIgnored: no pending consumer.");
+    return;
+  }
+
+  --pending_consumers_;
   ALOGD_IF(TRACE,
            "ProducerChannel::OnConsumerIgnored: buffer_id=%d %d consumers left",
            buffer_id(), pending_consumers_);
 }
 
+void ProducerChannel::OnConsumerOrphaned(ConsumerChannel* channel) {
+  // Ignore the orphaned consumer.
+  OnConsumerIgnored();
+
+  const uint64_t consumer_state_bit = channel->consumer_state_bit();
+  ALOGE_IF(orphaned_consumer_bit_mask_ & consumer_state_bit,
+           "ProducerChannel::OnConsumerOrphaned: Consumer "
+           "(consumer_state_bit=%" PRIx64 ") is already orphaned.",
+           consumer_state_bit);
+  orphaned_consumer_bit_mask_ |= consumer_state_bit;
+
+  // Atomically clear the fence state bit as an orphaned consumer will never
+  // signal a release fence. Also clear the buffer state as it won't be released
+  // as well.
+  fence_state_->fetch_and(~consumer_state_bit);
+  BufferHubDefs::ModifyBufferState(buffer_state_, consumer_state_bit, 0ULL);
+
+  ALOGW(
+      "ProducerChannel::OnConsumerOrphaned: detected new orphaned consumer "
+      "buffer_id=%d consumer_state_bit=%" PRIx64 " queue_index=%" PRIu64
+      " buffer_state=%" PRIx64 " fence_state=%" PRIx64 ".",
+      buffer_id(), consumer_state_bit, metadata_header_->queue_index,
+      buffer_state_->load(), fence_state_->load());
+}
+
 Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
                                                        const std::string& name,
                                                        int user_id,
@@ -335,6 +510,40 @@
 void ProducerChannel::RemoveConsumer(ConsumerChannel* channel) {
   consumer_channels_.erase(
       std::find(consumer_channels_.begin(), consumer_channels_.end(), channel));
+  active_consumer_bit_mask_ &= ~channel->consumer_state_bit();
+
+  const uint64_t buffer_state = buffer_state_->load();
+  if (BufferHubDefs::IsBufferPosted(buffer_state) ||
+      BufferHubDefs::IsBufferAcquired(buffer_state)) {
+    // The consumer client is being destoryed without releasing. This could
+    // happen in corner cases when the consumer crashes. Here we mark it
+    // orphaned before remove it from producer.
+    OnConsumerOrphaned(channel);
+  }
+
+  if (BufferHubDefs::IsBufferReleased(buffer_state) ||
+      BufferHubDefs::IsBufferGained(buffer_state)) {
+    // The consumer is being close while it is suppose to signal a release
+    // fence. Signal the dummy fence here.
+    if (fence_state_->load() & channel->consumer_state_bit()) {
+      epoll_event event;
+      event.events = EPOLLIN;
+      event.data.u64 = channel->consumer_state_bit();
+      if (epoll_ctl(release_fence_fd_.Get(), EPOLL_CTL_MOD,
+                    dummy_fence_fd_.Get(), &event) < 0) {
+        ALOGE(
+            "ProducerChannel::RemoveConsumer: Failed to modify the shared "
+            "release fence to include the dummy fence: %s",
+            strerror(errno));
+        return;
+      }
+      ALOGW(
+          "ProducerChannel::RemoveConsumer: signal dummy release fence "
+          "buffer_id=%d",
+          buffer_id());
+      eventfd_write(dummy_fence_fd_.Get(), 1);
+    }
+  }
 }
 
 // Returns true if either the user or group ids match the owning ids or both
@@ -350,10 +559,12 @@
 // Returns true if the given parameters match the underlying buffer parameters.
 bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
                                       uint32_t layer_count, uint32_t format,
-                                      uint64_t usage, size_t meta_size_bytes) {
-  return meta_size_bytes == meta_size_bytes_ && buffer_.width() == width &&
-         buffer_.height() == height && buffer_.layer_count() == layer_count &&
-         buffer_.format() == format && buffer_.usage() == usage;
+                                      uint64_t usage,
+                                      size_t user_metadata_size) {
+  return user_metadata_size == user_metadata_size_ &&
+         buffer_.width() == width && buffer_.height() == height &&
+         buffer_.layer_count() == layer_count && buffer_.format() == format &&
+         buffer_.usage() == usage;
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index 5ada478..e280f4d 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -33,7 +33,7 @@
   static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
       BufferHubService* service, int channel_id, uint32_t width,
       uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage,
-      size_t meta_size_bytes);
+      size_t user_metadata_size);
 
   ~ProducerChannel() override;
 
@@ -42,24 +42,25 @@
 
   BufferInfo GetBufferInfo() const override;
 
-  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message);
+  BufferDescription<BorrowedHandle> GetBuffer(uint64_t buffer_state_bit);
 
   pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
   pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
 
-  pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
-  OnConsumerAcquire(Message& message, std::size_t metadata_size);
+  pdx::Status<LocalFence> OnConsumerAcquire(Message& message);
   pdx::Status<void> OnConsumerRelease(Message& message,
                                       LocalFence release_fence);
 
   void OnConsumerIgnored();
+  void OnConsumerOrphaned(ConsumerChannel* channel);
 
   void AddConsumer(ConsumerChannel* channel);
   void RemoveConsumer(ConsumerChannel* channel);
 
   bool CheckAccess(int euid, int egid);
   bool CheckParameters(uint32_t width, uint32_t height, uint32_t layer_count,
-                       uint32_t format, uint64_t usage, size_t meta_size_bytes);
+                       uint32_t format, uint64_t usage,
+                       size_t user_metadata_size);
 
   pdx::Status<void> OnProducerMakePersistent(Message& message,
                                              const std::string& name,
@@ -74,11 +75,28 @@
 
   IonBuffer buffer_;
 
+  // IonBuffer that is shared between bufferhubd, producer, and consumers.
+  IonBuffer metadata_buffer_;
+  BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
+  std::atomic<uint64_t>* buffer_state_ = nullptr;
+  std::atomic<uint64_t>* fence_state_ = nullptr;
+
+  // All active consumer bits. Valid bits are the lower 63 bits, while the
+  // highest bit is reserved for the producer and should not be set.
+  uint64_t active_consumer_bit_mask_{0ULL};
+  // All orphaned consumer bits. Valid bits are the lower 63 bits, while the
+  // highest bit is reserved for the producer and should not be set.
+  uint64_t orphaned_consumer_bit_mask_{0ULL};
+
   bool producer_owns_;
   LocalFence post_fence_;
   LocalFence returned_fence_;
-  size_t meta_size_bytes_;
-  std::unique_ptr<uint8_t[]> meta_;
+  size_t user_metadata_size_;  // size of user requested buffer buffer size.
+  size_t metadata_buf_size_;  // size of the ion buffer that holds metadata.
+
+  pdx::LocalHandle acquire_fence_fd_;
+  pdx::LocalHandle release_fence_fd_;
+  pdx::LocalHandle dummy_fence_fd_;
 
   static constexpr int kNoCheckId = -1;
   static constexpr int kUseCallerId = 0;
@@ -92,11 +110,10 @@
 
   ProducerChannel(BufferHubService* service, int channel, uint32_t width,
                   uint32_t height, uint32_t layer_count, uint32_t format,
-                  uint64_t usage, size_t meta_size_bytes, int* error);
+                  uint64_t usage, size_t user_metadata_size, int* error);
 
-  pdx::Status<void> OnProducerPost(
-      Message& message, LocalFence acquire_fence,
-      BufferWrapper<std::vector<std::uint8_t>> metadata);
+  pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message);
+  pdx::Status<void> OnProducerPost(Message& message, LocalFence acquire_fence);
   pdx::Status<LocalFence> OnProducerGain(Message& message);
 
   ProducerChannel(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 886e621..c0c48c2 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -7,8 +7,8 @@
 
 using android::pdx::ErrorStatus;
 using android::pdx::Message;
-using android::pdx::Status;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -16,11 +16,11 @@
 
 ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
                                            int channel_id,
-                                           size_t meta_size_bytes,
+                                           const ProducerQueueConfig& config,
                                            const UsagePolicy& usage_policy,
                                            int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
-      meta_size_bytes_(meta_size_bytes),
+      config_(config),
       usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
@@ -35,8 +35,8 @@
 
 /* static */
 Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    const UsagePolicy& usage_policy) {
+    BufferHubService* service, int channel_id,
+    const ProducerQueueConfig& config, const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
   if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) {
@@ -50,7 +50,7 @@
 
   int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_policy, &error));
+      service, channel_id, config, usage_policy, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -76,9 +76,9 @@
           message);
       return true;
 
-    case BufferHubRPC::ProducerQueueDetachBuffer::Opcode:
-      DispatchRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(
-          *this, &ProducerQueueChannel::OnProducerQueueDetachBuffer, message);
+    case BufferHubRPC::ProducerQueueRemoveBuffer::Opcode:
+      DispatchRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>(
+          *this, &ProducerQueueChannel::OnProducerQueueRemoveBuffer, message);
       return true;
 
     default:
@@ -96,10 +96,12 @@
 }
 
 Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
-    Message& message) {
+    Message& message, bool silent) {
   ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue");
-  ALOGD_IF(TRACE, "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d",
-           channel_id());
+  ALOGD_IF(
+      TRACE,
+      "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d slient=%d",
+      channel_id(), silent);
 
   int channel_id;
   auto status = message.PushChannel(0, nullptr, &channel_id);
@@ -112,7 +114,7 @@
   }
 
   auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>(
-      service(), buffer_id(), channel_id, shared_from_this());
+      service(), buffer_id(), channel_id, shared_from_this(), silent);
 
   // Register the existing buffers with the new consumer queue.
   for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) {
@@ -134,7 +136,7 @@
 }
 
 Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
-  return {{meta_size_bytes_, buffer_id()}};
+  return {{config_, buffer_id()}};
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
@@ -222,7 +224,7 @@
 
   auto producer_channel_status =
       ProducerChannel::Create(service(), buffer_id, width, height, layer_count,
-                              format, usage, meta_size_bytes_);
+                              format, usage, config_.user_metadata_size);
   if (!producer_channel_status) {
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
@@ -276,11 +278,11 @@
   return {{std::move(buffer_handle), slot}};
 }
 
-Status<void> ProducerQueueChannel::OnProducerQueueDetachBuffer(
+Status<void> ProducerQueueChannel::OnProducerQueueRemoveBuffer(
     Message& /*message*/, size_t slot) {
   if (buffers_[slot].expired()) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach "
+        "ProducerQueueChannel::OnProducerQueueRemoveBuffer: trying to remove "
         "an invalid buffer producer at slot %zu",
         slot);
     return ErrorStatus(EINVAL);
@@ -288,7 +290,7 @@
 
   if (capacity_ == 0) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach a "
+        "ProducerQueueChannel::OnProducerQueueRemoveBuffer: trying to remove a "
         "buffer producer while the queue's capacity is already zero.");
     return ErrorStatus(EINVAL);
   }
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 28c74cd..e825f47 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -12,8 +12,8 @@
 class ProducerQueueChannel : public BufferHubChannel {
  public:
   static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
-      BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      const UsagePolicy& usage_policy);
+      BufferHubService* service, int channel_id,
+      const ProducerQueueConfig& config, const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
   bool HandleMessage(pdx::Message& message) override;
@@ -26,7 +26,7 @@
   // Returns a handle for the service channel, as well as the size of the
   // metadata associated with the queue.
   pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue(
-      pdx::Message& message);
+      pdx::Message& message, bool silent);
 
   pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message);
 
@@ -40,7 +40,7 @@
 
   // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
   // be in Gain'ed state for the producer queue to detach.
-  pdx::Status<void> OnProducerQueueDetachBuffer(pdx::Message& message,
+  pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message,
                                                 size_t slot);
 
   void AddConsumer(ConsumerQueueChannel* channel);
@@ -48,8 +48,8 @@
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, const UsagePolicy& usage_policy,
-                       int* error);
+                       const ProducerQueueConfig& config,
+                       const UsagePolicy& usage_policy, int* error);
 
   // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
   // Note that the newly created buffer's file handle will be pushed to client
@@ -60,10 +60,9 @@
       pdx::Message& message, uint32_t width, uint32_t height,
       uint32_t layer_count, uint32_t format, uint64_t usage);
 
-  // Size of the meta data associated with all the buffers allocated from the
-  // queue. Now we assume the metadata size is immutable once the queue is
-  // created.
-  size_t meta_size_bytes_;
+  // The producer queue's configuration. Now we assume the configuration is
+  // immutable once the queue is created.
+  ProducerQueueConfig config_;
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 5cb201d..9201520 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -7,6 +7,7 @@
   ],
 
   static_libs: [
+    "libbroadcastring",
     "libhwcomposer-client",
     "libdisplay",
     "libbufferhubqueue",
diff --git a/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl b/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl
index 5fd5c36..be1ec5b 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl
+++ b/services/vr/hardware_composer/aidl/android/dvr/IVrComposer.aidl
@@ -17,4 +17,9 @@
    * Registers a callback used to receive frame notifications.
    */
   void registerObserver(in IVrComposerCallback callback);
+
+  /**
+   * Clears a previously registered frame notification callback.
+   */
+  void clearObserver();
 }
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.cpp b/services/vr/hardware_composer/impl/vr_composer_client.cpp
index ae54e56..abe571a 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.cpp
+++ b/services/vr/hardware_composer/impl/vr_composer_client.cpp
@@ -24,26 +24,63 @@
 
 namespace android {
 namespace dvr {
+namespace {
 
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::frameworks::vr::composer::V1_0::IVrComposerClient;
 
-VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
+class ComposerClientImpl : public ComposerClient {
+ public:
+  ComposerClientImpl(android::dvr::VrHwc& hal);
+  virtual ~ComposerClientImpl();
+
+ private:
+  class VrCommandReader : public ComposerClient::CommandReader {
+   public:
+    VrCommandReader(ComposerClientImpl& client);
+    ~VrCommandReader() override;
+
+    bool parseCommand(IComposerClient::Command command,
+                      uint16_t length) override;
+
+   private:
+    bool parseSetLayerInfo(uint16_t length);
+    bool parseSetClientTargetMetadata(uint16_t length);
+    bool parseSetLayerBufferMetadata(uint16_t length);
+
+    IVrComposerClient::BufferMetadata readBufferMetadata();
+
+    ComposerClientImpl& mVrClient;
+    android::dvr::VrHwc& mVrHal;
+
+    VrCommandReader(const VrCommandReader&) = delete;
+    void operator=(const VrCommandReader&) = delete;
+  };
+
+  std::unique_ptr<CommandReader> createCommandReader() override;
+
+  dvr::VrHwc& mVrHal;
+
+  ComposerClientImpl(const ComposerClientImpl&) = delete;
+  void operator=(const ComposerClientImpl&) = delete;
+};
+
+ComposerClientImpl::ComposerClientImpl(android::dvr::VrHwc& hal)
     : ComposerClient(hal), mVrHal(hal) {}
 
-VrComposerClient::~VrComposerClient() {}
+ComposerClientImpl::~ComposerClientImpl() {}
 
 std::unique_ptr<ComposerClient::CommandReader>
-VrComposerClient::createCommandReader() {
+ComposerClientImpl::createCommandReader() {
   return std::unique_ptr<CommandReader>(new VrCommandReader(*this));
 }
 
-VrComposerClient::VrCommandReader::VrCommandReader(VrComposerClient& client)
+ComposerClientImpl::VrCommandReader::VrCommandReader(ComposerClientImpl& client)
     : CommandReader(client), mVrClient(client), mVrHal(client.mVrHal) {}
 
-VrComposerClient::VrCommandReader::~VrCommandReader() {}
+ComposerClientImpl::VrCommandReader::~VrCommandReader() {}
 
-bool VrComposerClient::VrCommandReader::parseCommand(
+bool ComposerClientImpl::VrCommandReader::parseCommand(
     IComposerClient::Command command, uint16_t length) {
   IVrComposerClient::VrCommand vrCommand =
       static_cast<IVrComposerClient::VrCommand>(command);
@@ -59,7 +96,7 @@
   }
 }
 
-bool VrComposerClient::VrCommandReader::parseSetLayerInfo(uint16_t length) {
+bool ComposerClientImpl::VrCommandReader::parseSetLayerInfo(uint16_t length) {
   if (length != 2) {
     return false;
   }
@@ -72,7 +109,7 @@
   return true;
 }
 
-bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+bool ComposerClientImpl::VrCommandReader::parseSetClientTargetMetadata(
     uint16_t length) {
   if (length != 7)
     return false;
@@ -84,7 +121,7 @@
   return true;
 }
 
-bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+bool ComposerClientImpl::VrCommandReader::parseSetLayerBufferMetadata(
     uint16_t length) {
   if (length != 7)
     return false;
@@ -98,7 +135,7 @@
 }
 
 IVrComposerClient::BufferMetadata
-VrComposerClient::VrCommandReader::readBufferMetadata() {
+ComposerClientImpl::VrCommandReader::readBufferMetadata() {
   IVrComposerClient::BufferMetadata metadata = {
     .width = read(),
     .height = read(),
@@ -110,5 +147,136 @@
   return metadata;
 }
 
+}  // namespace
+
+VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
+    : client_(new ComposerClientImpl(hal)) {
+  client_->initialize();
+}
+
+VrComposerClient::~VrComposerClient() {}
+
+void VrComposerClient::onHotplug(Display display,
+    IComposerCallback::Connection connected) {
+  client_->onHotplug(display, connected);
+}
+
+void VrComposerClient::onRefresh(Display display) {
+  client_->onRefresh(display);
+}
+
+Return<void> VrComposerClient::registerCallback(
+    const sp<IComposerCallback>& callback) {
+  return client_->registerCallback(callback);
+}
+
+Return<uint32_t> VrComposerClient::getMaxVirtualDisplayCount() {
+  return client_->getMaxVirtualDisplayCount();
+}
+
+Return<void> VrComposerClient::createVirtualDisplay(uint32_t width,
+    uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
+    createVirtualDisplay_cb hidl_cb) {
+  return client_->createVirtualDisplay(
+      width, height, formatHint, outputBufferSlotCount, hidl_cb);
+}
+
+Return<Error> VrComposerClient::destroyVirtualDisplay(Display display) {
+  return client_->destroyVirtualDisplay(display);
+}
+
+Return<void> VrComposerClient::createLayer(Display display,
+    uint32_t bufferSlotCount, createLayer_cb hidl_cb) {
+  return client_->createLayer(display, bufferSlotCount, hidl_cb);
+}
+
+Return<Error> VrComposerClient::destroyLayer(Display display, Layer layer) {
+  return client_->destroyLayer(display, layer);
+}
+
+Return<void> VrComposerClient::getActiveConfig(Display display,
+    getActiveConfig_cb hidl_cb) {
+  return client_->getActiveConfig(display, hidl_cb);
+}
+
+Return<Error> VrComposerClient::getClientTargetSupport(Display display,
+    uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) {
+  return client_->getClientTargetSupport(display, width, height, format,
+                                         dataspace);
+}
+
+Return<void> VrComposerClient::getColorModes(Display display,
+    getColorModes_cb hidl_cb) {
+  return client_->getColorModes(display, hidl_cb);
+}
+
+Return<void> VrComposerClient::getDisplayAttribute(Display display,
+    Config config, Attribute attribute, getDisplayAttribute_cb hidl_cb) {
+  return client_->getDisplayAttribute(display, config, attribute, hidl_cb);
+}
+
+Return<void> VrComposerClient::getDisplayConfigs(Display display,
+    getDisplayConfigs_cb hidl_cb) {
+  return client_->getDisplayConfigs(display, hidl_cb);
+}
+
+Return<void> VrComposerClient::getDisplayName(Display display,
+    getDisplayName_cb hidl_cb) {
+  return client_->getDisplayName(display, hidl_cb);
+}
+
+Return<void> VrComposerClient::getDisplayType(Display display,
+    getDisplayType_cb hidl_cb) {
+  return client_->getDisplayType(display, hidl_cb);
+}
+
+Return<void> VrComposerClient::getDozeSupport(
+    Display display, getDozeSupport_cb hidl_cb) {
+  return client_->getDozeSupport(display, hidl_cb);
+}
+
+Return<void> VrComposerClient::getHdrCapabilities(
+    Display display, getHdrCapabilities_cb hidl_cb) {
+  return client_->getHdrCapabilities(display, hidl_cb);
+}
+
+Return<Error> VrComposerClient::setActiveConfig(Display display,
+    Config config) {
+  return client_->setActiveConfig(display, config);
+}
+
+Return<Error> VrComposerClient::setColorMode(Display display, ColorMode mode) {
+  return client_->setColorMode(display, mode);
+}
+
+Return<Error> VrComposerClient::setPowerMode(Display display, PowerMode mode) {
+  return client_->setPowerMode(display, mode);
+}
+
+Return<Error> VrComposerClient::setVsyncEnabled(Display display,
+    Vsync enabled) {
+  return client_->setVsyncEnabled(display, enabled);
+}
+
+Return<Error> VrComposerClient::setClientTargetSlotCount(
+    Display display, uint32_t clientTargetSlotCount) {
+  return client_->setClientTargetSlotCount(display, clientTargetSlotCount);
+}
+
+Return<Error> VrComposerClient::setInputCommandQueue(
+    const hardware::MQDescriptorSync<uint32_t>& descriptor) {
+  return client_->setInputCommandQueue(descriptor);
+}
+
+Return<void> VrComposerClient::getOutputCommandQueue(
+    getOutputCommandQueue_cb hidl_cb) {
+  return client_->getOutputCommandQueue(hidl_cb);
+}
+
+Return<void> VrComposerClient::executeCommands(uint32_t inLength,
+    const hidl_vec<hidl_handle>& inHandles, executeCommands_cb hidl_cb) {
+  return client_->executeCommands(inLength, inHandles, hidl_cb);
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index 1236be9..dfc656a 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -29,37 +29,60 @@
 using hardware::graphics::common::V1_0::PixelFormat;
 using hardware::graphics::composer::V2_1::implementation::ComposerClient;
 
-class VrComposerClient : public ComposerClient {
+class VrComposerClient : public IVrComposerClient {
  public:
   VrComposerClient(android::dvr::VrHwc& hal);
   virtual ~VrComposerClient();
 
+  void onHotplug(Display display, IComposerCallback::Connection connected);
+  void onRefresh(Display display);
+
+  // IComposerClient
+  Return<void> registerCallback(const sp<IComposerCallback>& callback) override;
+  Return<uint32_t> getMaxVirtualDisplayCount() override;
+  Return<void> createVirtualDisplay(
+      uint32_t width, uint32_t height, PixelFormat formatHint,
+      uint32_t outputBufferSlotCount, createVirtualDisplay_cb hidl_cb) override;
+  Return<Error> destroyVirtualDisplay(Display display) override;
+  Return<void> createLayer(Display display, uint32_t bufferSlotCount,
+                           createLayer_cb hidl_cb) override;
+  Return<Error> destroyLayer(Display display, Layer layer) override;
+  Return<void> getActiveConfig(Display display,
+                               getActiveConfig_cb hidl_cb) override;
+  Return<Error> getClientTargetSupport(
+      Display display, uint32_t width, uint32_t height, PixelFormat format,
+      Dataspace dataspace) override;
+  Return<void> getColorModes(Display display,
+                             getColorModes_cb hidl_cb) override;
+  Return<void> getDisplayAttribute(
+      Display display, Config config, Attribute attribute,
+      getDisplayAttribute_cb hidl_cb) override;
+  Return<void> getDisplayConfigs(Display display,
+                                 getDisplayConfigs_cb hidl_cb) override;
+  Return<void> getDisplayName(Display display,
+                              getDisplayName_cb hidl_cb) override;
+  Return<void> getDisplayType(Display display,
+                              getDisplayType_cb hidl_cb) override;
+  Return<void> getDozeSupport(Display display,
+                              getDozeSupport_cb hidl_cb) override;
+  Return<void> getHdrCapabilities(Display display,
+                                  getHdrCapabilities_cb hidl_cb) override;
+  Return<Error> setActiveConfig(Display display, Config config) override;
+  Return<Error> setColorMode(Display display, ColorMode mode) override;
+  Return<Error> setPowerMode(Display display, PowerMode mode) override;
+  Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
+  Return<Error> setClientTargetSlotCount(
+      Display display, uint32_t clientTargetSlotCount) override;
+  Return<Error> setInputCommandQueue(
+      const hardware::MQDescriptorSync<uint32_t>& descriptor) override;
+  Return<void> getOutputCommandQueue(
+      getOutputCommandQueue_cb hidl_cb) override;
+  Return<void> executeCommands(
+      uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+      executeCommands_cb hidl_cb) override;
+
  private:
-  class VrCommandReader : public ComposerClient::CommandReader {
-   public:
-    VrCommandReader(VrComposerClient& client);
-    ~VrCommandReader() override;
-
-    bool parseCommand(IComposerClient::Command command,
-                      uint16_t length) override;
-
-   private:
-    bool parseSetLayerInfo(uint16_t length);
-    bool parseSetClientTargetMetadata(uint16_t length);
-    bool parseSetLayerBufferMetadata(uint16_t length);
-
-    IVrComposerClient::BufferMetadata readBufferMetadata();
-
-    VrComposerClient& mVrClient;
-    android::dvr::VrHwc& mVrHal;
-
-    VrCommandReader(const VrCommandReader&) = delete;
-    void operator=(const VrCommandReader&) = delete;
-  };
-
-  std::unique_ptr<CommandReader> createCommandReader() override;
-
-  dvr::VrHwc& mVrHal;
+  std::unique_ptr<ComposerClient> client_;
 
   VrComposerClient(const VrComposerClient&) = delete;
   void operator=(const VrComposerClient&) = delete;
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 5d51827..5e32af0 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -15,6 +15,7 @@
  */
 #include "impl/vr_hwc.h"
 
+#include <cutils/properties.h>
 #include <private/dvr/display_client.h>
 #include <ui/Fence.h>
 
@@ -132,13 +133,14 @@
               return lhs.info.z_order < rhs.info.z_order;
             });
 
-  int first_client_layer = -1, last_client_layer = -1;
+  const size_t no_layer = std::numeric_limits<size_t>::max();
+  size_t first_client_layer = no_layer, last_client_layer = no_layer;
   for (size_t i = 0; i < layers_.size(); ++i) {
     switch (layers_[i].composition_type) {
       case IComposerClient::Composition::SOLID_COLOR:
       case IComposerClient::Composition::CURSOR:
       case IComposerClient::Composition::SIDEBAND:
-        if (first_client_layer < 0)
+        if (first_client_layer == no_layer)
           first_client_layer = i;
 
         last_client_layer = i;
@@ -336,11 +338,30 @@
       *outValue = display_ptr->height();
       break;
     case IComposerClient::Attribute::VSYNC_PERIOD:
-      *outValue = 1000 * 1000 * 1000 / 30;  // 30fps
+      {
+        int error = 0;
+        auto display_client = display::DisplayClient::Create(&error);
+        if (!display_client) {
+          ALOGE("Could not connect to display service : %s(%d)",
+                strerror(error), error);
+          // Return a default value of 30 fps
+          *outValue = 1000 * 1000 * 1000 / 30;
+        } else {
+          auto metrics = display_client->GetDisplayMetrics();
+          *outValue = metrics.get().vsync_period_ns;
+        }
+      }
       break;
     case IComposerClient::Attribute::DPI_X:
     case IComposerClient::Attribute::DPI_Y:
-      *outValue = 300 * 1000;  // 300dpi
+      {
+        constexpr int32_t kDefaultDPI = 300;
+        int32_t dpi = property_get_int32("ro.vr.hwc.dpi", kDefaultDPI);
+        if (dpi <= 0) {
+          dpi = kDefaultDPI;
+        }
+        *outValue = 1000 * dpi;
+      }
       break;
     default:
       return Error::BAD_PARAMETER;
@@ -820,7 +841,6 @@
   sp<VrComposerClient> client;
   if (client_ == nullptr) {
     client = new VrComposerClient(*this);
-    client->initialize();
   } else {
     ALOGE("Already have a client");
     status = Error::NO_RESOURCES;
@@ -831,6 +851,14 @@
   return Void();
 }
 
+void VrHwc::ForceDisplaysRefresh() {
+  std::lock_guard<std::mutex> guard(mutex_);
+  if (client_ != nullptr) {
+    for (const auto& pair : displays_)
+      client_.promote()->onRefresh(pair.first);
+  }
+}
+
 void VrHwc::RegisterObserver(Observer* observer) {
   std::lock_guard<std::mutex> guard(mutex_);
   if (observer_)
@@ -852,12 +880,5 @@
   return iter == displays_.end() ? nullptr : iter->second.get();
 }
 
-ComposerView* GetComposerViewFromIComposer(
-    hardware::graphics::composer::V2_1::IComposer* composer) {
-  return static_cast<VrHwc*>(composer);
-}
-
-IComposer* HIDL_FETCH_IComposer(const char*) { return new VrHwc(); }
-
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index df04208..fce9a06 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -103,6 +103,7 @@
 
   virtual ~ComposerView() {}
 
+  virtual void ForceDisplaysRefresh() = 0;
   virtual void RegisterObserver(Observer* observer) = 0;
   virtual void UnregisterObserver(Observer* observer) = 0;
 };
@@ -288,6 +289,7 @@
   Return<void> createClient(createClient_cb hidl_cb) override;
 
   // ComposerView:
+  void ForceDisplaysRefresh() override;
   void RegisterObserver(Observer* observer) override;
   void UnregisterObserver(Observer* observer) override;
 
@@ -295,7 +297,6 @@
   HwcDisplay* FindDisplay(Display display);
 
   wp<VrComposerClient> client_;
-  sp<IComposerCallback> callbacks_;
 
   // Guard access to internal state from binder threads.
   std::mutex mutex_;
@@ -309,13 +310,6 @@
   void operator=(const VrHwc&) = delete;
 };
 
-
-ComposerView* GetComposerViewFromIComposer(
-    hardware::graphics::composer::V2_1::IComposer* composer);
-
-hardware::graphics::composer::V2_1::IComposer* HIDL_FETCH_IComposer(
-    const char* name);
-
 }  // namespace dvr
 }  // namespace android
 
diff --git a/services/vr/hardware_composer/tests/vr_composer_test.cpp b/services/vr/hardware_composer/tests/vr_composer_test.cpp
index d082f4b..2e70928 100644
--- a/services/vr/hardware_composer/tests/vr_composer_test.cpp
+++ b/services/vr/hardware_composer/tests/vr_composer_test.cpp
@@ -10,6 +10,24 @@
 
 const char kVrDisplayName[] = "VrDisplay_Test";
 
+class TestComposerView : public ComposerView {
+ public:
+  TestComposerView() {}
+  ~TestComposerView() override = default;
+
+  size_t display_refresh_count() const { return display_refresh_count_; }
+
+  void ForceDisplaysRefresh() override { display_refresh_count_++; }
+  void RegisterObserver(Observer* observer) override {}
+  void UnregisterObserver(Observer* observer) override {}
+
+  TestComposerView(const TestComposerView&) = delete;
+  void operator=(const TestComposerView&) = delete;
+
+ private:
+  size_t display_refresh_count_ = 0;
+};
+
 class TestComposerCallback : public BnVrComposerCallback {
  public:
   TestComposerCallback() {}
@@ -57,7 +75,7 @@
 
 class VrComposerTest : public testing::Test {
  public:
-  VrComposerTest() : composer_(new VrComposer()) {}
+  VrComposerTest() : composer_(new VrComposer(&composer_view_)) {}
   ~VrComposerTest() override = default;
 
   sp<IVrComposer> GetComposerProxy() const {
@@ -72,6 +90,7 @@
   }
 
  protected:
+  TestComposerView composer_view_;
   sp<VrComposer> composer_;
 
   VrComposerTest(const VrComposerTest&) = delete;
@@ -89,7 +108,9 @@
 TEST_F(VrComposerTest, TestWithObserver) {
   sp<IVrComposer> composer = GetComposerProxy();
   sp<TestComposerCallback> callback = new TestComposerCallback();
+  ASSERT_EQ(0, composer_view_.display_refresh_count());
   ASSERT_TRUE(composer->registerObserver(callback).isOk());
+  ASSERT_EQ(1, composer_view_.display_refresh_count());
 
   ComposerView::Frame frame;
   base::unique_fd fence = composer_->OnNewFrame(frame);
diff --git a/services/vr/hardware_composer/vr_composer.cpp b/services/vr/hardware_composer/vr_composer.cpp
index c45fbf4..d93f370 100644
--- a/services/vr/hardware_composer/vr_composer.cpp
+++ b/services/vr/hardware_composer/vr_composer.cpp
@@ -21,24 +21,42 @@
 
 }  // namespace
 
-VrComposer::VrComposer() {}
+VrComposer::VrComposer(ComposerView* composer_view)
+  : composer_view_(composer_view) {
+  composer_view_->RegisterObserver(this);
+}
 
-VrComposer::~VrComposer() {}
+VrComposer::~VrComposer() {
+  composer_view_->UnregisterObserver(this);
+}
 
 binder::Status VrComposer::registerObserver(
     const sp<IVrComposerCallback>& callback) {
-  std::lock_guard<std::mutex> guard(mutex_);
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
 
-  if (!CheckPermission())
-    return binder::Status::fromStatusT(PERMISSION_DENIED);
+    if (!CheckPermission())
+      return binder::Status::fromStatusT(PERMISSION_DENIED);
 
-  if (callback_.get()) {
-    ALOGE("Failed to register callback, already registered");
-    return binder::Status::fromStatusT(ALREADY_EXISTS);
+    if (callback_.get()) {
+      ALOGE("Failed to register callback, already registered");
+      return binder::Status::fromStatusT(ALREADY_EXISTS);
+    }
+
+    callback_ = callback;
+    IInterface::asBinder(callback_)->linkToDeath(this);
   }
 
-  callback_ = callback;
-  IInterface::asBinder(callback_)->linkToDeath(this);
+  // Don't take the lock to force display refresh otherwise it could end in a
+  // deadlock since HWC calls this with new frames and it has a lock of its own
+  // to serialize access to the display information.
+  composer_view_->ForceDisplaysRefresh();
+  return binder::Status::ok();
+}
+
+binder::Status VrComposer::clearObserver() {
+  std::lock_guard<std::mutex> guard(mutex_);
+  callback_ = nullptr;
   return binder::Status::ok();
 }
 
diff --git a/services/vr/hardware_composer/vr_composer.h b/services/vr/hardware_composer/vr_composer.h
index 93d1f2b..1273352 100644
--- a/services/vr/hardware_composer/vr_composer.h
+++ b/services/vr/hardware_composer/vr_composer.h
@@ -20,13 +20,15 @@
       public ComposerView::Observer,
       public IBinder::DeathRecipient {
  public:
-  VrComposer();
+  explicit VrComposer(ComposerView* composer_view);
   ~VrComposer() override;
 
   // BnVrComposer:
   binder::Status registerObserver(
       const sp<IVrComposerCallback>& callback) override;
 
+  binder::Status clearObserver() override;
+
   // ComposerView::Observer:
   base::unique_fd OnNewFrame(const ComposerView::Frame& frame) override;
 
@@ -38,6 +40,8 @@
 
   sp<IVrComposerCallback> callback_;
 
+  ComposerView* composer_view_;  // Not owned.
+
   VrComposer(const VrComposer&) = delete;
   void operator=(const VrComposer&) = delete;
 };
diff --git a/services/vr/hardware_composer/vr_hardware_composer_service.cpp b/services/vr/hardware_composer/vr_hardware_composer_service.cpp
index f980220..7701847 100644
--- a/services/vr/hardware_composer/vr_hardware_composer_service.cpp
+++ b/services/vr/hardware_composer/vr_hardware_composer_service.cpp
@@ -26,22 +26,17 @@
 
   // Register the hwbinder HWC HAL service used by SurfaceFlinger while in VR
   // mode.
-  const char instance[] = "vr";
-  android::sp<IComposer> service =
-      android::dvr::HIDL_FETCH_IComposer(instance);
+  android::sp<android::dvr::VrHwc> service = new android::dvr::VrHwc();
 
   LOG_ALWAYS_FATAL_IF(!service.get(), "Failed to get service");
   LOG_ALWAYS_FATAL_IF(service->isRemote(), "Service is remote");
 
+  const char instance[] = "vr";
   LOG_ALWAYS_FATAL_IF(service->registerAsService(instance) != android::OK,
                       "Failed to register service");
 
   android::sp<android::dvr::VrComposer> composer =
-      new android::dvr::VrComposer();
-
-  android::dvr::ComposerView* composer_view =
-      android::dvr::GetComposerViewFromIComposer(service.get());
-  composer_view->RegisterObserver(composer.get());
+      new android::dvr::VrComposer(service.get());
 
   android::sp<android::IServiceManager> sm(android::defaultServiceManager());
 
@@ -56,7 +51,5 @@
   android::hardware::ProcessState::self()->startThreadPool();
   android::hardware::IPCThreadState::self()->joinThreadPool();
 
-  composer_view->UnregisterObserver(composer.get());
-
   return 0;
 }
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
index 6256e90..dbc66f1 100644
--- a/services/vr/performanced/Android.mk
+++ b/services/vr/performanced/Android.mk
@@ -23,8 +23,10 @@
 staticLibraries := \
 	libperformance \
 	libpdx_default_transport \
+	libvr_manager
 
 sharedLibraries := \
+	libbinder \
 	libbase \
 	libcutils \
 	liblog \
diff --git a/services/vr/performanced/cpu_set.cpp b/services/vr/performanced/cpu_set.cpp
index 1a3723f..1a7264c 100644
--- a/services/vr/performanced/cpu_set.cpp
+++ b/services/vr/performanced/cpu_set.cpp
@@ -15,6 +15,9 @@
 #include "task.h"
 #include "unique_file.h"
 
+using android::pdx::ErrorStatus;
+using android::pdx::Status;
+
 namespace {
 
 constexpr int kDirectoryFlags = O_RDONLY | O_DIRECTORY | O_CLOEXEC;
@@ -176,11 +179,11 @@
                task_id, task.name().c_str(), target_set.c_str(),
                task.thread_group_id(), task.parent_process_id());
 
-      const int ret = target->AttachTask(task_id);
-      ALOGW_IF(ret < 0 && ret != -EINVAL,
+      auto status = target->AttachTask(task_id);
+      ALOGW_IF(!status && status.error() != EINVAL,
                "CpuSetManager::MoveUnboundTasks: Failed to attach task_id=%d "
                "to cpuset=%s: %s",
-               task_id, target_set.c_str(), strerror(-ret));
+               task_id, target_set.c_str(), status.GetErrorMessage().c_str());
     } else {
       ALOGD_IF(TRACE,
                "CpuSet::MoveUnboundTasks: Skipping task_id=%d name=%s cpus=%s.",
@@ -233,7 +236,7 @@
   return fp;
 }
 
-int CpuSet::AttachTask(pid_t task_id) const {
+Status<void> CpuSet::AttachTask(pid_t task_id) const {
   auto file = OpenFile("tasks", O_RDWR);
   if (file.get() >= 0) {
     std::ostringstream stream;
@@ -241,11 +244,15 @@
     std::string value = stream.str();
 
     const bool ret = base::WriteStringToFd(value, file.get());
-    return !ret ? -errno : 0;
+    if (!ret)
+      return ErrorStatus(errno);
+    else
+      return {};
   } else {
+    const int error = errno;
     ALOGE("CpuSet::AttachTask: Failed to open %s/tasks: %s", path_.c_str(),
-          strerror(errno));
-    return -errno;
+          strerror(error));
+    return ErrorStatus(error);
   }
 }
 
diff --git a/services/vr/performanced/cpu_set.h b/services/vr/performanced/cpu_set.h
index fcf280a..6879272 100644
--- a/services/vr/performanced/cpu_set.h
+++ b/services/vr/performanced/cpu_set.h
@@ -11,6 +11,8 @@
 
 #include <android-base/unique_fd.h>
 
+#include <pdx/status.h>
+
 #include "unique_file.h"
 
 namespace android {
@@ -28,7 +30,7 @@
 
   std::string GetCpuList() const;
 
-  int AttachTask(pid_t task_id) const;
+  pdx::Status<void> AttachTask(pid_t task_id) const;
   std::vector<pid_t> GetTasks() const;
 
  private:
diff --git a/services/vr/performanced/main.cpp b/services/vr/performanced/main.cpp
index ca66c71..d7dc8f6 100644
--- a/services/vr/performanced/main.cpp
+++ b/services/vr/performanced/main.cpp
@@ -9,7 +9,7 @@
 #include <sys/resource.h>
 #include <utils/threads.h>
 
-#include <pdx/default_transport/service_dispatcher.h>
+#include <pdx/service_dispatcher.h>
 #include <private/android_filesystem_config.h>
 
 #include "performance_service.h"
@@ -58,7 +58,7 @@
   CHECK_ERROR(ret < 0, error, "Could not set capabilities: %s",
               strerror(errno));
 
-  dispatcher = android::pdx::default_transport::ServiceDispatcher::Create();
+  dispatcher = android::pdx::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher.");
 
   service = android::dvr::PerformanceService::Create();
diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp
index 955c661..4c26671 100644
--- a/services/vr/performanced/performance_service.cpp
+++ b/services/vr/performanced/performance_service.cpp
@@ -8,24 +8,94 @@
 #include <pdx/rpc/argument_encoder.h>
 #include <pdx/rpc/message_buffer.h>
 #include <pdx/rpc/remote_method.h>
+#include <private/android_filesystem_config.h>
 #include <private/dvr/performance_rpc.h>
+#include <private/dvr/trusted_uids.h>
 
 #include "task.h"
 
 // This prctl is only available in Android kernels.
 #define PR_SET_TIMERSLACK_PID 41
 
+using android::dvr::IsTrustedUid;
+using android::dvr::Task;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
-using android::pdx::rpc::DispatchRemoteMethod;
+using android::pdx::Status;
 using android::pdx::default_transport::Endpoint;
+using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace {
 
 const char kCpuSetBasePath[] = "/dev/cpuset";
 
+const char kRootCpuSet[] = "/";
+
 constexpr unsigned long kTimerSlackForegroundNs = 50000;
 constexpr unsigned long kTimerSlackBackgroundNs = 40000000;
 
+// Expands the given parameter pack expression using an initializer list to
+// guarantee ordering and a comma expression to guarantee even void expressions
+// are valid elements of the initializer list.
+#define EXPAND_PACK(...) \
+  std::initializer_list<int> { (__VA_ARGS__, 0)... }
+
+// Returns true if the sender's euid matches any of the uids in |UIDs|.
+template <uid_t... UIDs>
+struct UserId {
+  static bool Check(const Message& sender, const Task&) {
+    const uid_t uid = sender.GetEffectiveUserId();
+    bool allow = false;
+    EXPAND_PACK(allow |= (uid == UIDs));
+    return allow;
+  }
+};
+
+// Returns true if the sender's egid matches any of the gids in |GIDs|.
+template <gid_t... GIDs>
+struct GroupId {
+  static bool Check(const Message& sender, const Task&) {
+    const gid_t gid = sender.GetEffectiveGroupId();
+    bool allow = false;
+    EXPAND_PACK(allow |= (gid == GIDs));
+    return allow;
+  }
+};
+
+// Returns true if the sender's euid is trusted according to VR manager service.
+struct Trusted {
+  static bool Check(const Message& sender, const Task&) {
+    return IsTrustedUid(sender.GetEffectiveUserId());
+  }
+};
+
+// Returns returns true if the task belongs to the sending process.
+struct SameProcess {
+  static bool Check(const Message& sender, const Task& task) {
+    return sender.GetProcessId() == task.thread_group_id();
+  }
+};
+
+// Returns true if any of the checks in |Allows| pass, false otherwise.
+template <typename... Allows>
+struct CheckOr {
+  static bool Check(const Message& sender, const Task& task) {
+    bool allow = false;
+    EXPAND_PACK(allow |= Allows::Check(sender, task));
+    return allow;
+  }
+};
+
+// Returns true if all of the checks in |Allows| pass, false otherwise.
+template <typename... Allows>
+struct CheckAnd {
+  static bool Check(const Message& sender, const Task& task) {
+    bool allow = true;
+    EXPAND_PACK(allow &= Allows::Check(sender, task));
+    return allow;
+  }
+};
+
 }  // anonymous namespace
 
 namespace android {
@@ -48,43 +118,81 @@
   const int fifo_low = sched_fifo_min_priority_;
   const int fifo_medium = sched_fifo_min_priority_ + fifo_range / 5;
 
-  // TODO(eieio): Make this configurable on the command line.
+  // TODO(eieio): Make this configurable on the command line or config file.
   cpuset_.MoveUnboundTasks("/kernel");
 
+  // TODO(eieio): Replace this witha device-specific config file. This is just a
+  // hack for now to put some form of permission logic in place while a longer
+  // term solution is developed.
+  using AllowRootSystem =
+      CheckAnd<SameProcess,
+               CheckOr<UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>>;
+  using AllowRootSystemGraphics =
+      CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_GRAPHICS>,
+                                    GroupId<AID_SYSTEM, AID_GRAPHICS>>>;
+  using AllowRootSystemAudio =
+      CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_AUDIO>,
+                                    GroupId<AID_SYSTEM, AID_AUDIO>>>;
+  using AllowRootSystemTrusted =
+      CheckOr<Trusted, UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>;
+
+  partition_permission_check_ = AllowRootSystemTrusted::Check;
+
   // Setup the scheduler classes.
-  scheduler_classes_ = {
+  // TODO(eieio): Replace this with a device-specific config file.
+  scheduler_policies_ = {
       {"audio:low",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_medium}},
+        .priority = fifo_medium,
+        .permission_check = AllowRootSystemAudio::Check}},
       {"audio:high",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_medium + 3}},
+        .priority = fifo_medium + 3,
+        .permission_check = AllowRootSystemAudio::Check}},
       {"graphics",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_medium}},
+        .priority = fifo_medium,
+        .permission_check = AllowRootSystemGraphics::Check}},
       {"graphics:low",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_medium}},
+        .priority = fifo_medium,
+        .permission_check = AllowRootSystemGraphics::Check}},
       {"graphics:high",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_medium + 2}},
+        .priority = fifo_medium + 2,
+        .permission_check = AllowRootSystemGraphics::Check}},
       {"sensors",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_low}},
+        .priority = fifo_low,
+        .permission_check = AllowRootSystem::Check}},
       {"sensors:low",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_low}},
+        .priority = fifo_low,
+        .permission_check = AllowRootSystem::Check}},
       {"sensors:high",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
-        .priority = fifo_low + 1}},
+        .priority = fifo_low + 1,
+        .permission_check = AllowRootSystem::Check}},
+      {"vr:system:arp",
+       {.timer_slack = kTimerSlackForegroundNs,
+        .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
+        .priority = fifo_medium + 2,
+        .permission_check = AllowRootSystemTrusted::Check,
+        "/system/performance"}},
+      {"vr:app:render",
+       {.timer_slack = kTimerSlackForegroundNs,
+        .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
+        .priority = fifo_medium + 1,
+        .permission_check = AllowRootSystemTrusted::Check,
+        "/application/performance"}},
       {"normal",
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_NORMAL,
@@ -113,67 +221,160 @@
   return cpuset_.DumpState();
 }
 
-int PerformanceService::OnSetCpuPartition(Message& message, pid_t task_id,
-                                          const std::string& partition) {
+Status<void> PerformanceService::OnSetSchedulerPolicy(
+    Message& message, pid_t task_id, const std::string& scheduler_policy) {
+  ALOGI(
+      "PerformanceService::OnSetSchedulerPolicy: task_id=%d "
+      "scheduler_policy=%s",
+      task_id, scheduler_policy.c_str());
+
+  Task task(task_id);
+  if (!task) {
+    ALOGE(
+        "PerformanceService::OnSetSchedulerPolicy: Unable to access /proc/%d "
+        "to gather task information.",
+        task_id);
+    return ErrorStatus(EINVAL);
+  }
+
+  auto search = scheduler_policies_.find(scheduler_policy);
+  if (search != scheduler_policies_.end()) {
+    auto config = search->second;
+
+    // Make sure the sending process is allowed to make the requested change to
+    // this task.
+    if (!config.IsAllowed(message, task))
+      return ErrorStatus(EINVAL);
+
+    // Get the thread group's cpu set. Policies that do not specify a cpuset
+    // should default to this cpuset.
+    std::string thread_group_cpuset;
+    Task thread_group{task.thread_group_id()};
+    if (thread_group) {
+      thread_group_cpuset = thread_group.GetCpuSetPath();
+    } else {
+      ALOGE(
+          "PerformanceService::OnSetSchedulerPolicy: Failed to get thread "
+          "group tgid=%d for task_id=%d",
+          task.thread_group_id(), task_id);
+      thread_group_cpuset = kRootCpuSet;
+    }
+
+    std::string target_cpuset;
+    if (config.cpuset.empty()) {
+      target_cpuset = thread_group_cpuset;
+    } else {
+      target_cpuset = config.cpuset;
+    }
+    ALOGI("PerformanceService::OnSetSchedulerPolicy: Using cpuset=%s",
+          target_cpuset.c_str());
+
+    auto target_set = cpuset_.Lookup(target_cpuset);
+    if (target_set) {
+      auto attach_status = target_set->AttachTask(task_id);
+      ALOGW_IF(!attach_status,
+               "PerformanceService::OnSetSchedulerPolicy: Failed to attach "
+               "task=%d to cpuset=%s: %s",
+               task_id, target_cpuset.c_str(),
+               attach_status.GetErrorMessage().c_str());
+    } else {
+      ALOGW(
+          "PerformanceService::OnSetSchedulerPolicy: Failed to lookup "
+          "cpuset=%s",
+          target_cpuset.c_str());
+    }
+
+    struct sched_param param;
+    param.sched_priority = config.priority;
+
+    sched_setscheduler(task_id, config.scheduler_policy, &param);
+    prctl(PR_SET_TIMERSLACK_PID, config.timer_slack, task_id);
+    return {};
+  } else {
+    ALOGE(
+        "PerformanceService::OnSetSchedulerPolicy: Invalid scheduler_policy=%s "
+        "requested by task=%d.",
+        scheduler_policy.c_str(), task_id);
+    return ErrorStatus(EINVAL);
+  }
+}
+
+Status<void> PerformanceService::OnSetCpuPartition(
+    Message& message, pid_t task_id, const std::string& partition) {
   Task task(task_id);
   if (!task || task.thread_group_id() != message.GetProcessId())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
+
+  // Temporary permission check.
+  // TODO(eieio): Replace this with a configuration file.
+  if (partition_permission_check_ &&
+      !partition_permission_check_(message, task)) {
+    return ErrorStatus(EINVAL);
+  }
 
   auto target_set = cpuset_.Lookup(partition);
   if (!target_set)
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
 
-  const auto attach_error = target_set->AttachTask(task_id);
-  if (attach_error)
-    return attach_error;
+  auto attach_status = target_set->AttachTask(task_id);
+  if (!attach_status)
+    return attach_status;
 
-  return 0;
+  return {};
 }
 
-int PerformanceService::OnSetSchedulerClass(
+Status<void> PerformanceService::OnSetSchedulerClass(
     Message& message, pid_t task_id, const std::string& scheduler_class) {
-  // Make sure the task id is valid and belongs to the sending process.
   Task task(task_id);
-  if (!task || task.thread_group_id() != message.GetProcessId())
-    return -EINVAL;
+  if (!task)
+    return ErrorStatus(EINVAL);
 
-  struct sched_param param;
-
-  // TODO(eieio): Apply rules based on the requesting process. Applications are
-  // only allowed one audio thread that runs at SCHED_FIFO. System services can
-  // have more than one.
-  auto search = scheduler_classes_.find(scheduler_class);
-  if (search != scheduler_classes_.end()) {
+  auto search = scheduler_policies_.find(scheduler_class);
+  if (search != scheduler_policies_.end()) {
     auto config = search->second;
+
+    // Make sure the sending process is allowed to make the requested change to
+    // this task.
+    if (!config.IsAllowed(message, task))
+      return ErrorStatus(EINVAL);
+
+    struct sched_param param;
     param.sched_priority = config.priority;
+
     sched_setscheduler(task_id, config.scheduler_policy, &param);
     prctl(PR_SET_TIMERSLACK_PID, config.timer_slack, task_id);
     ALOGI("PerformanceService::OnSetSchedulerClass: Set task=%d to class=%s.",
           task_id, scheduler_class.c_str());
-    return 0;
+    return {};
   } else {
     ALOGE(
         "PerformanceService::OnSetSchedulerClass: Invalid class=%s requested "
         "by task=%d.",
         scheduler_class.c_str(), task_id);
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 }
 
-std::string PerformanceService::OnGetCpuPartition(Message& message,
-                                                  pid_t task_id) {
+Status<std::string> PerformanceService::OnGetCpuPartition(Message& message,
+                                                          pid_t task_id) {
   // Make sure the task id is valid and belongs to the sending process.
   Task task(task_id);
   if (!task || task.thread_group_id() != message.GetProcessId())
-    REPLY_ERROR_RETURN(message, EINVAL, "");
+    return ErrorStatus(EINVAL);
 
   return task.GetCpuSetPath();
 }
 
-pdx::Status<void> PerformanceService::HandleMessage(Message& message) {
+Status<void> PerformanceService::HandleMessage(Message& message) {
+  ALOGD_IF(TRACE, "PerformanceService::HandleMessage: op=%d", message.GetOp());
   switch (message.GetOp()) {
+    case PerformanceRPC::SetSchedulerPolicy::Opcode:
+      DispatchRemoteMethod<PerformanceRPC::SetSchedulerPolicy>(
+          *this, &PerformanceService::OnSetSchedulerPolicy, message);
+      return {};
+
     case PerformanceRPC::SetCpuPartition::Opcode:
-      DispatchRemoteMethod<PerformanceRPC::SetSchedulerClass>(
+      DispatchRemoteMethod<PerformanceRPC::SetCpuPartition>(
           *this, &PerformanceService::OnSetCpuPartition, message);
       return {};
 
diff --git a/services/vr/performanced/performance_service.h b/services/vr/performanced/performance_service.h
index 34abba7..6b519ab 100644
--- a/services/vr/performanced/performance_service.h
+++ b/services/vr/performanced/performance_service.h
@@ -1,12 +1,14 @@
 #ifndef ANDROID_DVR_PERFORMANCED_PERFORMANCE_SERVICE_H_
 #define ANDROID_DVR_PERFORMANCED_PERFORMANCE_SERVICE_H_
 
+#include <functional>
 #include <string>
 #include <unordered_map>
 
 #include <pdx/service.h>
 
 #include "cpu_set.h"
+#include "task.h"
 
 namespace android {
 namespace dvr {
@@ -27,25 +29,46 @@
 
   PerformanceService();
 
-  int OnSetCpuPartition(pdx::Message& message, pid_t task_id,
-                        const std::string& partition);
-  int OnSetSchedulerClass(pdx::Message& message, pid_t task_id,
-                          const std::string& scheduler_class);
-  std::string OnGetCpuPartition(pdx::Message& message, pid_t task_id);
+  pdx::Status<void> OnSetSchedulerPolicy(pdx::Message& message, pid_t task_id,
+                                         const std::string& scheduler_class);
+
+  pdx::Status<void> OnSetCpuPartition(pdx::Message& message, pid_t task_id,
+                                      const std::string& partition);
+  pdx::Status<void> OnSetSchedulerClass(pdx::Message& message, pid_t task_id,
+                                        const std::string& scheduler_class);
+  pdx::Status<std::string> OnGetCpuPartition(pdx::Message& message,
+                                             pid_t task_id);
 
   CpuSetManager cpuset_;
 
   int sched_fifo_min_priority_;
   int sched_fifo_max_priority_;
 
-  // Scheduler class config type.
-  struct SchedulerClassConfig {
+  struct SchedulerPolicyConfig {
     unsigned long timer_slack;
     int scheduler_policy;
     int priority;
+    std::function<bool(const pdx::Message& message, const Task& task)>
+        permission_check;
+    std::string cpuset;
+
+    // Check the permisison of the given task to use this scheduler class. If a
+    // permission check function is not set then operations are only allowed on
+    // tasks in the sender's process.
+    bool IsAllowed(const pdx::Message& sender, const Task& task) const {
+      if (permission_check)
+        return permission_check(sender, task);
+      else if (!task || task.thread_group_id() != sender.GetProcessId())
+        return false;
+      else
+        return true;
+    }
   };
 
-  std::unordered_map<std::string, SchedulerClassConfig> scheduler_classes_;
+  std::unordered_map<std::string, SchedulerPolicyConfig> scheduler_policies_;
+
+  std::function<bool(const pdx::Message& message, const Task& task)>
+      partition_permission_check_;
 
   PerformanceService(const PerformanceService&) = delete;
   void operator=(const PerformanceService&) = delete;
diff --git a/services/vr/performanced/performance_service_tests.cpp b/services/vr/performanced/performance_service_tests.cpp
index b526082..4065785 100644
--- a/services/vr/performanced/performance_service_tests.cpp
+++ b/services/vr/performanced/performance_service_tests.cpp
@@ -1,14 +1,65 @@
 #include <errno.h>
 #include <sched.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <condition_variable>
+#include <cstdlib>
+#include <iostream>
 #include <mutex>
+#include <sstream>
 #include <thread>
+#include <utility>
 
+#include <android-base/unique_fd.h>
 #include <dvr/performance_client_api.h>
 #include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
 
-TEST(DISABLED_PerformanceTest, SetCpuPartition) {
+#include "stdio_filebuf.h"
+#include "string_trim.h"
+#include "unique_file.h"
+
+using android::dvr::Trim;
+using android::dvr::UniqueFile;
+using android::dvr::stdio_filebuf;
+
+namespace {
+
+const char kTrustedUidEnvironmentVariable[] = "GTEST_TRUSTED_UID";
+
+const char kProcBase[] = "/proc";
+
+std::pair<UniqueFile, int> OpenTaskFile(pid_t task_id,
+                                        const std::string& name) {
+  std::ostringstream stream;
+  stream << kProcBase << "/" << task_id << "/" << name;
+
+  UniqueFile file{fopen(stream.str().c_str(), "r")};
+  const int error = file ? 0 : errno;
+  return {std::move(file), error};
+}
+
+std::string GetTaskCpuSet(pid_t task_id) {
+  int error;
+  UniqueFile file;
+
+  std::tie(file, error) = OpenTaskFile(task_id, "cpuset");
+  if (!file)
+    return std::string("errno:") + strerror(error);
+
+  stdio_filebuf<char> filebuf(file.get());
+  std::istream file_stream(&filebuf);
+
+  std::string line;
+  std::getline(file_stream, line);
+  return Trim(line);
+}
+
+}  // anonymous namespace
+
+TEST(PerformanceTest, SetCpuPartition) {
   int error;
 
   // Test setting the the partition for the current task.
@@ -49,13 +100,6 @@
   }
   thread.join();
 
-  // Test setting the partition for a task that isn't valid using
-  // the task id of the thread that we just joined. Technically the
-  // id could wrap around by the time we get here, but this is
-  // extremely unlikely.
-  error = dvrSetCpuPartition(task_id, "/application");
-  EXPECT_EQ(-EINVAL, error);
-
   // Test setting the partition for a task that doesn't belong to us.
   error = dvrSetCpuPartition(1, "/application");
   EXPECT_EQ(-EINVAL, error);
@@ -63,6 +107,10 @@
   // Test setting the partition to one that doesn't exist.
   error = dvrSetCpuPartition(0, "/foobar");
   EXPECT_EQ(-ENOENT, error);
+
+  // Set the test back to the root partition.
+  error = dvrSetCpuPartition(0, "/");
+  EXPECT_EQ(0, error);
 }
 
 TEST(PerformanceTest, SetSchedulerClass) {
@@ -86,6 +134,69 @@
   EXPECT_EQ(-EINVAL, error);
 }
 
+TEST(PerformanceTest, SetSchedulerPolicy) {
+  int error;
+
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0));
+
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(0, error);
+  EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0));
+
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+  EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0));
+
+  error = dvrSetSchedulerPolicy(0, "foobar");
+  EXPECT_EQ(-EINVAL, error);
+
+  // Set the test back to the root partition.
+  error = dvrSetCpuPartition(0, "/");
+  EXPECT_EQ(0, error);
+
+  const std::string original_cpuset = GetTaskCpuSet(gettid());
+  EXPECT_EQ("/", original_cpuset);
+
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(0, error);
+  EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0));
+
+  const std::string new_cpuset = GetTaskCpuSet(gettid());
+  EXPECT_NE(original_cpuset, new_cpuset);
+
+  // The cpuset for the thread group is now new_cpuset. Scheduler profiles that
+  // do not specify a cpuset should not change the cpuset of a thread, except to
+  // restore it to the thread group cpuset.
+  std::string thread_original_cpuset;
+  std::string thread_new_cpuset;
+  std::string thread_final_cpuset;
+
+  std::thread thread{
+      [&thread_original_cpuset, &thread_new_cpuset, &thread_final_cpuset]() {
+        thread_original_cpuset = GetTaskCpuSet(gettid());
+
+        int error = dvrSetSchedulerPolicy(0, "vr:app:render");
+        EXPECT_EQ(0, error);
+
+        thread_new_cpuset = GetTaskCpuSet(gettid());
+
+        error = dvrSetSchedulerPolicy(0, "normal");
+        EXPECT_EQ(0, error);
+
+        thread_final_cpuset = GetTaskCpuSet(gettid());
+      }};
+  thread.join();
+
+  EXPECT_EQ(new_cpuset, thread_original_cpuset);
+  EXPECT_NE(new_cpuset, thread_new_cpuset);
+  EXPECT_EQ(new_cpuset, thread_final_cpuset);
+
+  error = dvrSetCpuPartition(0, original_cpuset.c_str());
+  EXPECT_EQ(0, error);
+}
+
 TEST(PerformanceTest, SchedulerClassResetOnFork) {
   int error;
 
@@ -135,3 +246,284 @@
   error = dvrGetCpuPartition(0, nullptr, sizeof(partition));
   EXPECT_EQ(-EINVAL, error);
 }
+
+TEST(PerformanceTest, Permissions) {
+  int error;
+
+  const int original_uid = getuid();
+  const int original_gid = getgid();
+  int trusted_uid = -1;
+
+  // See if the environment variable GTEST_TRUSTED_UID is set. If it is enable
+  // testing the ActivityManager trusted uid permission checks using that uid.
+  const char* trusted_uid_env = std::getenv(kTrustedUidEnvironmentVariable);
+  if (trusted_uid_env)
+    trusted_uid = std::atoi(trusted_uid_env);
+
+  ASSERT_EQ(AID_ROOT, original_uid)
+      << "This test must run as root to function correctly!";
+
+  // Test unprivileged policies on a task that does not belong to this process.
+  // Use the init process (task_id=1) as the target.
+  error = dvrSetSchedulerPolicy(1, "batch");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(1, "background");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(1, "foreground");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(1, "normal");
+  EXPECT_EQ(-EINVAL, error);
+
+  // Switch the uid/gid to an id that should not have permission to access any
+  // privileged actions.
+  ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1))
+      << "Failed to set gid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1))
+      << "Failed to set uid: " << strerror(errno);
+
+  // Unprivileged policies.
+  error = dvrSetSchedulerPolicy(0, "batch");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "foreground");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+
+  // Privileged policies.
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "audio:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "graphics");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:app:render");
+  EXPECT_EQ(-EINVAL, error);
+
+  // uid=AID_SYSTEM / gid=AID_NOBODY
+  ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+      << "Failed to restore uid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_SYSTEM, -1))
+      << "Failed to set uid: " << strerror(errno);
+
+  // Unprivileged policies.
+  error = dvrSetSchedulerPolicy(0, "batch");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "foreground");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+
+  // Privileged policies.
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "audio:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "vr:app:render");
+  EXPECT_EQ(0, error);
+
+  // uid=AID_NOBODY / gid=AID_SYSTEM
+  ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+      << "Failed to restore uid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(original_gid, original_gid, -1))
+      << "Failed to restore gid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(AID_SYSTEM, AID_SYSTEM, -1))
+      << "Failed to set gid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_NOBODY, -1))
+      << "Failed to set uid: " << strerror(errno);
+
+  // Unprivileged policies.
+  error = dvrSetSchedulerPolicy(0, "batch");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "foreground");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+
+  // Privileged policies.
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "audio:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "vr:app:render");
+  EXPECT_EQ(0, error);
+
+  // uid=AID_GRAPHICS / gid=AID_NOBODY
+  ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+      << "Failed to restore uid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(original_gid, original_gid, -1))
+      << "Failed to restore gid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1))
+      << "Failed to set gid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(AID_GRAPHICS, AID_GRAPHICS, -1))
+      << "Failed to set uid: " << strerror(errno);
+
+  // Unprivileged policies.
+  error = dvrSetSchedulerPolicy(0, "batch");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "foreground");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+
+  // Privileged policies.
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "audio:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "graphics");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:app:render");
+  EXPECT_EQ(-EINVAL, error);
+
+  // uid=AID_NOBODY / gid=AID_GRAPHICS
+  ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+      << "Failed to restore uid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(original_gid, original_gid, -1))
+      << "Failed to restore gid: " << strerror(errno);
+  ASSERT_EQ(0, setresgid(AID_GRAPHICS, AID_GRAPHICS, -1))
+      << "Failed to set gid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1))
+      << "Failed to set uid: " << strerror(errno);
+
+  // Unprivileged policies.
+  error = dvrSetSchedulerPolicy(0, "batch");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "background");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "foreground");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "normal");
+  EXPECT_EQ(0, error);
+
+  // Privileged policies.
+  error = dvrSetSchedulerPolicy(0, "audio:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "audio:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "graphics");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:low");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "graphics:high");
+  EXPECT_EQ(0, error);
+  error = dvrSetSchedulerPolicy(0, "sensors");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:low");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "sensors:high");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+  EXPECT_EQ(-EINVAL, error);
+  error = dvrSetSchedulerPolicy(0, "vr:app:render");
+  EXPECT_EQ(-EINVAL, error);
+
+  if (trusted_uid != -1) {
+    // uid=<trusted uid> / gid=AID_NOBODY
+    ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+        << "Failed to restore uid: " << strerror(errno);
+    ASSERT_EQ(0, setresgid(original_gid, original_gid, -1))
+        << "Failed to restore gid: " << strerror(errno);
+    ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1))
+        << "Failed to set gid: " << strerror(errno);
+    ASSERT_EQ(0, setresuid(trusted_uid, trusted_uid, -1))
+        << "Failed to set uid: " << strerror(errno);
+
+    // Unprivileged policies.
+    error = dvrSetSchedulerPolicy(0, "batch");
+    EXPECT_EQ(0, error);
+    error = dvrSetSchedulerPolicy(0, "background");
+    EXPECT_EQ(0, error);
+    error = dvrSetSchedulerPolicy(0, "foreground");
+    EXPECT_EQ(0, error);
+    error = dvrSetSchedulerPolicy(0, "normal");
+    EXPECT_EQ(0, error);
+
+    // Privileged policies.
+    error = dvrSetSchedulerPolicy(0, "audio:low");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "audio:high");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "graphics");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "graphics:low");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "graphics:high");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "sensors");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "sensors:low");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "sensors:high");
+    EXPECT_EQ(-EINVAL, error);
+    error = dvrSetSchedulerPolicy(0, "vr:system:arp");
+    EXPECT_EQ(0, error);
+    error = dvrSetSchedulerPolicy(0, "vr:app:render");
+    EXPECT_EQ(0, error);
+  }
+
+  // Restore original effective uid/gid.
+  ASSERT_EQ(0, setresgid(original_gid, original_gid, -1))
+      << "Failed to restore gid: " << strerror(errno);
+  ASSERT_EQ(0, setresuid(original_uid, original_uid, -1))
+      << "Failed to restore uid: " << strerror(errno);
+}
diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp
index 1175a7b..c2f078e 100644
--- a/services/vr/performanced/task.cpp
+++ b/services/vr/performanced/task.cpp
@@ -48,15 +48,18 @@
       thread_count_(0),
       cpus_allowed_mask_(0) {
   task_fd_ = OpenTaskDirectory(task_id_);
-  ALOGE_IF(task_fd_.get() < 0,
+  const int error = errno;
+  ALOGE_IF(task_fd_.get() < 0 && error != EACCES,
            "Task::Task: Failed to open task directory for task_id=%d: %s",
-           task_id, strerror(errno));
+           task_id, strerror(error));
 
-  ReadStatusFields();
-
-  ALOGD_IF(TRACE, "Task::Task: task_id=%d name=%s tgid=%d ppid=%d cpu_mask=%x",
-           task_id_, name_.c_str(), thread_group_id_, parent_process_id_,
-           cpus_allowed_mask_);
+  if (IsValid()) {
+    ReadStatusFields();
+    ALOGD_IF(TRACE,
+             "Task::Task: task_id=%d name=%s tgid=%d ppid=%d cpu_mask=%x",
+             task_id_, name_.c_str(), thread_group_id_, parent_process_id_,
+             cpus_allowed_mask_);
+  }
 }
 
 base::unique_fd Task::OpenTaskFile(const std::string& name) const {
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 3d5dfb2..6b11ce3 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -13,10 +13,15 @@
     "libutils",
 ]
 
+header_libraries = [
+    "libdvr_headers"
+]
+
 cc_library {
     srcs: src,
     export_include_dirs: ["include"],
     shared_libs: shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
     name: "libvirtualtouchpad",
@@ -28,9 +33,6 @@
 test_static_libs = [
     "libcutils",
     "libvirtualtouchpad",
-]
-
-test_shared_libs = [
     "libbase",
     "liblog",
     "libutils",
@@ -41,7 +43,7 @@
 cc_test {
     srcs: test_src_files,
     static_libs: test_static_libs,
-    shared_libs: test_shared_libs,
+    header_libs: header_libraries,
     cppflags = [
         "-std=c++11",
     ],
@@ -77,6 +79,7 @@
     srcs: service_src,
     static_libs: service_static_libs,
     shared_libs: service_shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: [
         "-DLOG_TAG=\"VrVirtualTouchpad\"",
@@ -107,6 +110,7 @@
 cc_library {
     srcs: client_src,
     shared_libs: client_shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
     host_ldlibs: ["-llog"],
diff --git a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
index eb152ed..3ab77a7 100644
--- a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
@@ -40,6 +40,11 @@
   return FromC(client)->ButtonState(touchpad, buttons);
 }
 
+int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x,
+                             float y) {
+  return FromC(client)->Scroll(touchpad, x, y);
+}
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp
index a4ccdd0..7fad379 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.cpp
+++ b/services/vr/virtual_touchpad/EvdevInjector.cpp
@@ -168,6 +168,25 @@
   return ConfigureAbs(ABS_MT_SLOT, 0, slots, 0, 0);
 }
 
+int EvdevInjector::ConfigureRel(uint16_t rel_type) {
+  ALOGV("ConfigureRel 0x%" PRIX16 "", rel_type);
+  if (rel_type < 0 || rel_type >= REL_CNT) {
+    ALOGE("EV_REL type 0x%" PRIX16 " out of range [0,0x%X)", rel_type, REL_CNT);
+    return Error(ERROR_REL_RANGE);
+  }
+  if (const int status = RequireState(State::CONFIGURING)) {
+    return status;
+  }
+  if (const int status = EnableEventType(EV_REL)) {
+    return status;
+  }
+  if (const int status = uinput_->IoctlSetInt(UI_SET_RELBIT, rel_type)) {
+    ALOGE("failed to enable EV_REL 0x%" PRIX16 "", rel_type);
+    return Error(status);
+  }
+  return 0;
+}
+
 int EvdevInjector::ConfigureEnd() {
   ALOGV("ConfigureEnd:");
   ALOGV("  name=\"%s\"", uidev_.name);
@@ -236,6 +255,10 @@
   return Send(EV_ABS, code, value);
 }
 
+int EvdevInjector::SendRel(uint16_t code, int32_t value) {
+  return Send(EV_REL, code, value);
+}
+
 int EvdevInjector::SendMultiTouchSlot(int32_t slot) {
   if (latest_slot_ != slot) {
     if (const int status = SendAbs(ABS_MT_SLOT, slot)) {
diff --git a/services/vr/virtual_touchpad/EvdevInjector.h b/services/vr/virtual_touchpad/EvdevInjector.h
index c69dbef..e87c959 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.h
+++ b/services/vr/virtual_touchpad/EvdevInjector.h
@@ -30,6 +30,7 @@
     ERROR_KEY_RANGE = -3,       // |KEY_*|/|BTN_*| code out of range.
     ERROR_ABS_RANGE = -4,       // |ABS_*| code out of range.
     ERROR_SEQUENCING = -5,      // Configure/Send out of order.
+    ERROR_REL_RANGE = -6,       // |REL_*| code out of range.
   };
 
   // Key event |value| is not defined in <linux/input.h>.
@@ -87,6 +88,10 @@
   // Configure multitouch coordinate range.
   int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
 
+  // Configure a relative axis.
+  // @param rel_type One of the |REL_*| constants from <linux/input.h>.
+  int ConfigureRel(uint16_t rel_type);
+
   // Complete configuration and create the input device.
   int ConfigureEnd();
 
@@ -96,6 +101,7 @@
   int SendSynReport();
   int SendKey(uint16_t code, int32_t value);
   int SendAbs(uint16_t code, int32_t value);
+  int SendRel(uint16_t code, int32_t value);
   int SendMultiTouchSlot(int32_t slot);
   int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
   int SendMultiTouchLift(int32_t slot);
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index c7c8184..00e4ce6 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -60,6 +60,13 @@
     return service_->buttonState(touchpad, buttons).transactionError();
   }
 
+  status_t Scroll(int touchpad, float x, float y) override {
+    if (service_ == nullptr) {
+      return NO_INIT;
+    }
+    return service_->scroll(touchpad, x, y).transactionError();
+  }
+
   void dumpInternal(String8& result) override {
     result.append("[virtual touchpad]\n");
     result.appendFormat("connected = %s\n\n",
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index f0bdcd9..bcfdad3 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -28,6 +28,12 @@
 static constexpr int32_t kHeight = 0x10000;
 static constexpr int32_t kSlots = 2;
 
+static constexpr float kScrollScale = 100.0f;
+
+int32_t scale_relative_scroll(float x) {
+  return kScrollScale * x;
+}
+
 }  // anonymous namespace
 
 std::unique_ptr<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
@@ -66,6 +72,8 @@
     touchpad.injector->ConfigureInputProperty(INPUT_PROP_DIRECT);
     touchpad.injector->ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1);
     touchpad.injector->ConfigureAbsSlots(kSlots);
+    touchpad.injector->ConfigureRel(REL_WHEEL);
+    touchpad.injector->ConfigureRel(REL_HWHEEL);
     touchpad.injector->ConfigureKey(BTN_TOUCH);
     touchpad.injector->ConfigureKey(BTN_BACK);
     touchpad.injector->ConfigureEnd();
@@ -86,9 +94,6 @@
   if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
     return EINVAL;
   }
-  if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
-    return EINVAL;
-  }
   int32_t device_x = x * kWidth;
   int32_t device_y = y * kHeight;
   Touchpad& touchpad = touchpad_[touchpad_id];
@@ -162,6 +167,33 @@
   return touchpad.injector->GetError();
 }
 
+int VirtualTouchpadEvdev::Scroll(int touchpad_id, float x, float y) {
+  if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
+    return EINVAL;
+  }
+  if ((x < -1.0f) || (x > 1.0f) || (y < -1.0f) || (y > 1.0f)) {
+    return EINVAL;
+  }
+  Touchpad& touchpad = touchpad_[touchpad_id];
+  if (!touchpad.injector) {
+    return EvdevInjector::ERROR_SEQUENCING;
+  }
+  touchpad.injector->ResetError();
+  const int32_t scaled_x = scale_relative_scroll(x);
+  const int32_t scaled_y = scale_relative_scroll(y);
+  ALOGV("(%f,%f) -> (%" PRId32 ",%" PRId32 ")", x, y, scaled_x, scaled_y);
+  if (scaled_x) {
+    touchpad.injector->SendRel(REL_HWHEEL, scaled_x);
+  }
+  if (scaled_y) {
+    touchpad.injector->SendRel(REL_WHEEL, scaled_y);
+  }
+  if (scaled_x || scaled_y) {
+    touchpad.injector->SendSynReport();
+  }
+  return touchpad.injector->GetError();
+}
+
 void VirtualTouchpadEvdev::dumpInternal(String8& result) {
   for (int i = 0; i < kTouchpads; ++i) {
     const auto& touchpad = touchpad_[i];
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index 2fb8ff3..c9578bf 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -21,6 +21,7 @@
   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:
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index 81edd32..523f890 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -87,6 +87,16 @@
   return binder::Status::ok();
 }
 
+binder::Status VirtualTouchpadService::scroll(int touchpad, float x, float y) {
+  if (!CheckPermissions()) {
+    return binder::Status::fromStatusT(PERMISSION_DENIED);
+  }
+  if (const status_t error = touchpad_->Scroll(touchpad, x, y)) {
+    return binder::Status::fromStatusT(error);
+  }
+  return binder::Status::ok();
+}
+
 status_t VirtualTouchpadService::dump(
     int fd, const Vector<String16>& args[[gnu::unused]]) {
   String8 result;
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index cf236f9..2c46209 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -23,6 +23,7 @@
   binder::Status detach() override;
   binder::Status touch(int touchpad, float x, float y, float pressure) override;
   binder::Status buttonState(int touchpad, int buttons) override;
+  binder::Status scroll(int touchpad, float x, float y) override;
 
   // Implements BBinder::dump().
   status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
index 9cfb186..256203c 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
@@ -34,4 +34,15 @@
    * @param buttons A union of MotionEvent BUTTON_* values.
    */
   void buttonState(int touchpad, int buttons) = 3;
+
+  /**
+   * Generate a simulated scroll event.
+   *
+   * @param touchpad Selects touchpad.
+   * @param x Horizontal scroll increment.
+   * @param y Vertical scroll increment.
+   *
+   * Scroll values are in the range [-1.0, 1.0].
+   */
+  void scroll(int touchpad, float x, float y) = 4;
 }
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc
new file mode 100644
index 0000000..205e8b9
--- /dev/null
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-0.idc
@@ -0,0 +1,26 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Virtual touchpad for the primary display
+device.internal = 1
+
+touch.deviceType = touchScreen
+
+# Have input flinger treat injected scroll events like a G1 ball
+# rather than the default mouse wheel, because the latter requires
+# a visible pointer for targeting.
+device.type = rotaryEncoder
+device.res = 1.0e+2
+device.scalingFactor = 1.0e-2
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
new file mode 100644
index 0000000..d9714e0
--- /dev/null
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
@@ -0,0 +1,31 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Virtual touchpad for the VR virtual display
+device.internal = 1
+
+touch.deviceType = touchScreen
+
+# Have input flinger treat injected scroll events like a G1 ball
+# rather than the default mouse wheel, because the latter requires
+# a visible pointer for targeting.
+device.type = rotaryEncoder
+device.res = 1.0e+2
+device.scalingFactor = 1.0e-2
+
+# This displayID matches the unique ID of the virtual display created for VR.
+# This will indicate to input flinger than it should link this input device
+# with the virtual display.
+touch.displayId = virtual:android:277f1a09-b88d-4d1e-8716-796f114d080b
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index da3a0b7..99b72fc 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -61,6 +61,16 @@
   //
   virtual status_t ButtonState(int touchpad, int buttons) = 0;
 
+  // Generate a simulated scroll event.
+  //
+  // @param touchpad Touchpad selector index.
+  // @param x Horizontal scroll increment.
+  // @param y Vertical scroll increment.
+  //            Values must be in the range [-1.0, 1.0].
+  // @returns OK on success.
+  //
+  virtual status_t Scroll(int touchpad, float x, float y) = 0;
+
   // Report state for 'dumpsys'.
   virtual void dumpInternal(String8& result) = 0;
 
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 23fb9f8..7d73f06 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -17,6 +17,7 @@
   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:
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
index 08cca1b..09fb1cc 100644
--- a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -1,17 +1,14 @@
 #ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
 #define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
 
+#include <dvr/dvr_api.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
-enum {
-  DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
-  DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
-};
-
 // Creates a new virtual touchpad client.
 //
 // @return Pointer to the created virtual touchpad client; nullptr on failure.
@@ -64,6 +61,17 @@
 int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
                                   int buttons);
 
+// Generate a simulated scroll event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param x Horizontal scroll increment.
+// @param y Vertical scroll increment.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x,
+                             float y);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 564bcd7..b19b018 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -169,6 +169,11 @@
     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y);
     // From ConfigureAbsSlots(kSlots):
     expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT);
+    // From ConfigureRel(REL_WHEEL):
+    expect.IoctlSetInt(UI_SET_EVBIT, EV_REL);
+    expect.IoctlSetInt(UI_SET_RELBIT, REL_WHEEL);
+    // From ConfigureRel(REL_HWHEEL):
+    expect.IoctlSetInt(UI_SET_RELBIT, REL_HWHEEL);
     // From ConfigureKey(BTN_TOUCH):
     expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
     expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 91c270e..6107088 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -25,8 +25,22 @@
 
 cc_library_headers {
     name: "vulkan_headers",
-    export_include_dirs: ["include"],
     vendor_available: true,
+    header_libs: [
+        "libcutils_headers",
+        "libhardware_headers",
+    ],
+    export_header_lib_headers: [
+        "libcutils_headers",
+        "libhardware_headers",
+    ],
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "vulkan_headers_ndk",
+    export_include_dirs: ["include"],
+    sdk_version: "24",
 }
 
 subdirs = [
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index a19fcf1..3a2b1ef 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 0
-define VERSION_PATCH 46
+define VERSION_PATCH 54
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -38,8 +38,10 @@
 define VK_MAX_MEMORY_TYPES              32
 define VK_MAX_MEMORY_HEAPS              16    /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
 define VK_MAX_DEVICE_GROUP_SIZE_KHX     32
-define VK_LUID_SIZE_KHX                 8
-define VK_QUEUE_FAMILY_EXTERNAL_KHX     -2
+//@extension("VK_KHR_external_memory_capabilities")
+define VK_LUID_SIZE_KHR                 8
+//@extension("VK_KHR_external_memory")
+define VK_QUEUE_FAMILY_EXTERNAL_KHR     -2
 
 // API keywords
 define VK_TRUE        1
@@ -85,7 +87,7 @@
 @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     5
+@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
@@ -93,7 +95,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       6
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       8
 @extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
 
 // 13
@@ -152,6 +154,10 @@
 @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"
+
 // 54
 @extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_SPEC_VERSION 1
 @extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
@@ -209,45 +215,49 @@
 @extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
 
 // 72
-@extension("VK_KHX_external_memory_capabilities") define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHX_external_memory_capabilities") define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_memory_capabilities"
+@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_KHX_external_memory") define VK_KHX_EXTERNAL_MEMORY_SPEC_VERSION 1
-@extension("VK_KHX_external_memory") define VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHX_external_memory"
+@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_KHX_external_memory_win32") define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-@extension("VK_KHX_external_memory_win32") define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
+@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_KHX_external_memory_fd") define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
-@extension("VK_KHX_external_memory_fd") define VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHX_external_memory_fd"
+@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_KHX_win32_keyed_mutex") define VK_KHX_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-@extension("VK_KHX_win32_keyed_mutex") define VK_KHX_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHX_win32_keyed_mutex"
+@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_KHX_external_semaphore_capabilities") define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
-@extension("VK_KHX_external_semaphore_capabilities") define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_semaphore_capabilities"
+@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_KHX_external_semaphore") define VK_KHX_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
-@extension("VK_KHX_external_semaphore") define VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHX_external_semaphore"
+@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_KHX_external_semaphore_win32") define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
-@extension("VK_KHX_external_semaphore_win32") define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHX_external_semaphore_win32"
+@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_KHX_external_semaphore_fd") define VK_KHX_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
-@extension("VK_KHX_external_semaphore_fd") define VK_KHX_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHX_external_semaphore_fd"
+@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 1
 @extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
 
+// 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"
@@ -320,10 +330,30 @@
 @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"
 
-// 119
+// 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"
+
+// 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"
+
 // 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"
@@ -332,6 +362,42 @@
 @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"
 
+// 128
+@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 1
+@extension("VK_KHR_dedicated_allocation") define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
+
+// 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"
+
+// 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"
+
+// 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"
+
 /////////////
 //  Types  //
 /////////////
@@ -409,7 +475,7 @@
     //@extension("VK_KHR_swapchain") // 2
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR                      = 1000111000,
 }
 
@@ -554,6 +620,9 @@
     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 {
@@ -589,6 +658,54 @@
     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 {
@@ -947,6 +1064,9 @@
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
 
+    //@extension("VK_AMD_texture_gather_bias_lod") // 42
+    VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD  = 1000041000,
+
     //@extension("VK_KHX_multiview") // 54
     VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX     = 1000053000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX    = 1000053001,
@@ -999,51 +1119,52 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX      = 1000070000,
     VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX       = 1000070001,
 
-    //@extension("VK_KHX_external_memory_capabilities") // 72
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHX    = 1000071000,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHX      = 1000071001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX  = 1000071002,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX            = 1000071003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX         = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX          = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX             = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX   = 1000071007,
+    //@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_KHX_external_memory") // 73
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX    = 1000072000,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX     = 1000072001,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX           = 1000072002,
+    //@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_KHX_external_memory_win32") // 74
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHX       = 1000073000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHX       = 1000073001,
-    VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHX        = 1000073002,
+    //@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_KHX_external_memory_fd") // 75
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHX                 = 1000074000,
-    VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHX                  = 1000074001,
+    //@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_KHX_win32_keyed_mutex") // 76
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHX    = 1000075000,
+    //@extension("VK_KHR_win32_keyed_mutex") // 76
+    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR    = 1000075000,
 
-    //@extension("VK_KHX_external_semaphore_capabilities") // 77
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHX   = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHX         = 1000076001,
+    //@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_KHX_external_semaphore") // 78
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHX          = 1000077000,
+    //@extension("VK_KHR_external_semaphore") // 78
+    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR          = 1000077000,
 
-    //@extension("VK_KHX_external_semaphore_win32") // 79
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX    = 1000078000,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX    = 1000078001,
-    VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX               = 1000078002,
+    //@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_KHX_external_semaphore_fd") // 80
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX              = 1000079000,
+    //@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,
 
@@ -1086,19 +1207,64 @@
     //@extension("VK_EXT_hdr_metadata") // 106
     VK_STRUCTURE_TYPE_HDR_METADATA_EXT                          = 1000105000,
 
-    //@extension("VK_KHR_shared_presentable_image") // 111
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR   = 1000111000,
 
-    //@extension("VK_KHR_get_surface_capabilities2") // 119
+    //@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_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_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_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_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_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,
+
+    //@structure("VK_NV_framebuffer_mixed_samples") // 153
+    VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
 }
 
 enum VkSubpassContents {
@@ -1157,8 +1323,8 @@
     //@extension("VK_KHR_maintenance1") // 70
     VK_ERROR_OUT_OF_POOL_MEMORY_KHR                         = 0xC4642878, // -1000069000
 
-    //@extension("VK_KHX_external_memory") // 73
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX                    = 0xC4641CBD, // -1000072003
+    //@extension("VK_KHR_external_memory") // 73
+    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR                    = 0xC4641CBD, // -1000072003
 }
 
 enum VkDynamicState {
@@ -1179,6 +1345,55 @@
     VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT                  = 1000099000,
 }
 
+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,
+
+    //@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_KHR_surface") // 1
 enum VkPresentModeKHR {
     VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
@@ -1186,7 +1401,7 @@
     VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
     VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR               = 1000111000,
     VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR           = 1000111001,
 }
@@ -1209,6 +1424,7 @@
     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
@@ -1241,7 +1457,7 @@
     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_EXT            = 28,
+    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,
@@ -1251,12 +1467,6 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
 }
 
-@extension("VK_EXT_debug_report") // 12
-enum VkDebugReportErrorEXT {
-    VK_DEBUG_REPORT_ERROR_NONE_EXT                          = 0,
-    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT                  = 1,
-}
-
 @extension("VK_AMD_rasterization_order") // 19
 enum VkRasterizationOrderAMD {
     VK_RASTERIZATION_ORDER_STRICT_AMD                       = 0,
@@ -1266,6 +1476,7 @@
 @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
@@ -1276,23 +1487,23 @@
 
 @extension("VK_NVX_device_generated_commands") // 87
 enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX                 = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX           = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX             = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX            = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX            = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX             = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX                     = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX                 = 7,
+    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_DESCRIPTOR_SET_NVX                      = 0,
-    VK_OBJECT_ENTRY_PIPELINE_NVX                            = 1,
-    VK_OBJECT_ENTRY_INDEX_BUFFER_NVX                        = 2,
-    VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX                       = 3,
-    VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX                       = 4,
+    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
@@ -1330,6 +1541,28 @@
     VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 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,
+}
+
 /////////////////
 //  Bitfields  //
 /////////////////
@@ -1386,6 +1619,9 @@
     //@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,
 }
 
 /// Buffer usage flags
@@ -1524,6 +1760,9 @@
     //@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,
 }
 
 /// Query control flags
@@ -1974,45 +2213,52 @@
 //bitfield VkCommandPoolTrimFlagBitsKHR {
 //}
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryHandleTypeFlagsKHX
-@extension("VK_KHX_external_memory_capabilities") // 72
-bitfield VkExternalMemoryHandleTypeFlagBitsKHX {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX            = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX         = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX     = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHX        = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHX    = 0x00000010,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHX           = 0x00000020,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHX       = 0x00000040,
+@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_KHX_external_memory_capabilities") // 72
-type VkFlags VkExternalMemoryFeatureFlagsKHX
-@extension("VK_KHX_external_memory_capabilities") // 72
-bitfield VkExternalMemoryFeatureFlagBitsKHX {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHX           = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHX               = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHX               = 0x00000004,
+@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_KHX_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreHandleTypeFlagsKHX
-@extension("VK_KHX_external_semaphore_capabilities") // 77
-bitfield VkExternalSemaphoreHandleTypeFlagBitsKHX {
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX         = 0x00000001
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX      = 0x00000002
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX  = 0x00000004
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX       = 0x00000008
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX          = 0x00000010
+@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_KHX_external_semaphore_capabilities") // 77
-type VkFlags VkExternalSemaphoreFeatureFlagsKHX
-@extension("VK_KHX_external_semaphore_capabilities") // 77
-bitfield VkExternalSemaphoreFeatureFlagBitsKHX {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX            = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX            = 0x00000002,
+@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_KHR_descriptor_update_template") // 86
@@ -2058,6 +2304,31 @@
 //bitfield VkPipelineDiscardRectangleStateCreateFlagBitsEXT {
 //}
 
+@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
@@ -2070,6 +2341,18 @@
 //bitfield VkMacOSSurfaceCreateFlagBitsMVK {
 //}
 
+@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 {
+//}
+
 //////////////////
 //  Structures  //
 //////////////////
@@ -3451,6 +3734,13 @@
     VkBuffer                                    buffer
 }
 
+@extension("VK_AMD_texture_gather_bias_lod") // 42
+class VkTextureLODGatherFormatPropertiesAMD {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkBool32                                    supportsTextureGatherLODBiasAMD
+}
+
 @extension("VK_KHX_multiview") // 54
 class VkRenderPassMultiviewCreateInfoKHX {
     VkStructureType                             sType
@@ -3753,84 +4043,86 @@
     const VkPhysicalDevice*                     pPhysicalDevices
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkExternalMemoryPropertiesKHX {
-    VkExternalMemoryFeatureFlagsKHX             externalMemoryFeatures
-    VkExternalMemoryHandleTypeFlagsKHX          exportFromImportedHandleTypes
-    VkExternalMemoryHandleTypeFlagsKHX          compatibleHandleTypes
+@extension("VK_KHR_external_memory_capabilities") // 72
+class VkExternalMemoryPropertiesKHR {
+    VkExternalMemoryFeatureFlagsKHR             externalMemoryFeatures
+    VkExternalMemoryHandleTypeFlagsKHR          exportFromImportedHandleTypes
+    VkExternalMemoryHandleTypeFlagsKHR          compatibleHandleTypes
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalImageFormatInfoKHX {
+@extension("VK_KHR_external_memory_capabilities") // 72
+class VkPhysicalDeviceExternalImageFormatInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkExternalImageFormatPropertiesKHX {
+@extension("VK_KHR_external_memory_capabilities") // 72
+class VkExternalImageFormatPropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
-    VkExternalMemoryPropertiesKHX               externalMemoryProperties
+    VkExternalMemoryPropertiesKHR               externalMemoryProperties
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkPhysicalDeviceExternalBufferInfoKHX {
+@extension("VK_KHR_external_memory_capabilities") // 72
+class VkPhysicalDeviceExternalBufferInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     VkBufferCreateFlags                         flags
     VkBufferUsageFlags                          usage
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkExternalBufferPropertiesKHX {
+@extension("VK_KHR_external_memory_capabilities") // 72
+class VkExternalBufferPropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
-    VkExternalMemoryPropertiesKHX               externalMemoryProperties
+    VkExternalMemoryPropertiesKHR               externalMemoryProperties
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-class VkPhysicalDeviceIDPropertiesKHX {
+@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_KHX]                        deviceLUID
+    u8[VK_LUID_SIZE_KHR]                        deviceLUID
+    u32                                         deviceNodeMask
     VkBool32                                    deviceLUIDValid
 }
 
-@extension("VK_KHX_external_memory") // 73
-class VkExternalMemoryImageCreateInfoKHX {
+@extension("VK_KHR_external_memory") // 73
+class VkExternalMemoryImageCreateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHX          handleTypes
+    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
 }
 
-@extension("VK_KHX_external_memory") // 73
-class VkExternalMemoryBufferCreateInfoKHX {
+@extension("VK_KHR_external_memory") // 73
+class VkExternalMemoryBufferCreateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHX          handleTypes
+    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
 }
 
-@extension("VK_KHX_external_memory") // 73
-class VkExportMemoryAllocateInfoKHX {
+@extension("VK_KHR_external_memory") // 73
+class VkExportMemoryAllocateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagsKHX          handleTypes
+    VkExternalMemoryHandleTypeFlagsKHR          handleTypes
 }
 
-@extension("VK_KHX_external_memory_win32") // 74
-class VkImportMemoryWin32HandleInfoKHX {
+@extension("VK_KHR_external_memory_win32") // 74
+class VkImportMemoryWin32HandleInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
     platform.HANDLE                             handle
+    platform.LPCWSTR                            name
 }
 
-@extension("VK_KHX_external_memory_win32") // 74
-class VkExportMemoryWin32HandleInfoKHX {
+@extension("VK_KHR_external_memory_win32") // 74
+class VkExportMemoryWin32HandleInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     const platform.SECURITY_ATTRIBUTES*         pAttributes
@@ -3838,30 +4130,46 @@
     platform.LPCWSTR                            name
 }
 
-@extension("VK_KHX_external_memory_win32") // 74
-class VkMemoryWin32HandlePropertiesKHX {
+@extension("VK_KHR_external_memory_win32") // 74
+class VkMemoryWin32HandlePropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
     u32                                         memoryTypeBits
 }
 
-@extension("VK_KHX_external_memory_fd") // 75
-class VkImportMemoryFdInfoKHX {
+@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
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType
     int                                         fd
 }
 
-@extension("VK_KHX_external_memory_fd") // 75
-class VkMemoryFdPropertiesKHX {
+@extension("VK_KHR_external_memory_fd") // 75
+class VkMemoryFdPropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
     u32                                         memoryTypeBits
 }
 
-@extension("VK_KHX_win32_keyed_mutex") // 76
-class VkWin32KeyedMutexAcquireReleaseInfoKHX {
+@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
@@ -3873,40 +4181,42 @@
     const u64*                                  pReleaseKeys
 }
 
-@extension("VK_KHX_external_semaphore_capabilities") // 77
-class VkPhysicalDeviceExternalSemaphoreInfoKHX {
+@extension("VK_KHR_external_semaphore_capabilities") // 77
+class VkPhysicalDeviceExternalSemaphoreInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType
 }
 
-@extension("VK_KHX_external_semaphore_capabilities") // 77
-class VkExternalSemaphorePropertiesKHX {
+@extension("VK_KHR_external_semaphore_capabilities") // 77
+class VkExternalSemaphorePropertiesKHR {
     VkStructureType                             sType
     void*                                       pNext
-    VkExternalSemaphoreHandleTypeFlagsKHX       exportFromImportedHandleTypes
-    VkExternalSemaphoreHandleTypeFlagsKHX       compatibleHandleTypes
-    VkExternalSemaphoreFeatureFlagsKHX          externalSemaphoreFeatures
+    VkExternalSemaphoreHandleTypeFlagsKHR       exportFromImportedHandleTypes
+    VkExternalSemaphoreHandleTypeFlagsKHR       compatibleHandleTypes
+    VkExternalSemaphoreFeatureFlagsKHR          externalSemaphoreFeatures
 }
 
-@extension("VK_KHX_external_semaphore") // 78
-class VkExportSemaphoreCreateInfoKHX {
+@extension("VK_KHR_external_semaphore") // 78
+class VkExportSemaphoreCreateInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
-    VkExternalSemaphoreHandleTypeFlagsKHX       handleTypes
+    VkExternalSemaphoreHandleTypeFlagsKHR       handleTypes
 }
 
-@extension("VK_KHX_external_semaphore_win32") // 79
-class VkImportSemaphoreWin32HandleInfoKHX {
+@extension("VK_KHR_external_semaphore_win32") // 79
+class VkImportSemaphoreWin32HandleInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagsKHX       handleType
+    VkSemaphoreImportFlagsKHR                   flags
+    VkExternalSemaphoreHandleTypeFlagsKHR       handleType
     platform.HANDLE                             handle
+    platform.LPCWSTR                            name
 }
 
-@extension("VK_KHX_external_semaphore_win32") // 79
-class VkExportSemaphoreWin32HandleInfoKHX {
+@extension("VK_KHR_external_semaphore_win32") // 79
+class VkExportSemaphoreWin32HandleInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     const platform.SECURITY_ATTRIBUTES*         pAttributes
@@ -3914,8 +4224,8 @@
     platform.LPCWSTR                            name
 }
 
-@extension("VK_KHX_external_semaphore_win32") // 79
-class VkD3D12FenceSubmitInfoKHX {
+@extension("VK_KHR_external_semaphore_win32") // 79
+class VkD3D12FenceSubmitInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     u32                                         waitSemaphoreValuesCount
@@ -3924,15 +4234,32 @@
     const u64*                                  pSignalSemaphoreValues
 }
 
-@extension("VK_KHX_external_semaphore_fd") // 80
-class VkImportSemaphoreFdInfoKHX {
+@extension("VK_KHR_external_semaphore_win32") // 79
+class VkSemaphoreGetWin32HandleInfoKHR {
     VkStructureType                             sType
     const void*                                 pNext
     VkSemaphore                                 semaphore
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType
+    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
@@ -3940,6 +4267,16 @@
     u32                                         maxPushDescriptors
 }
 
+@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
@@ -4261,34 +4598,111 @@
     f32                                             maxFrameAverageLightLevel
 }
 
-@extension("VK_KHR_shared_presentable_image") // 111
+@extension("VK_KHR_shared_presentable_image") // 112
 class VkSharedPresentSurfaceCapabilitiesKHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkImageUsageFlags                               sharedPresentSupportedUsageFlags
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@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_get_surface_capabilities2") // 120
 class VkPhysicalDeviceSurfaceInfo2KHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkSurfaceKHR                                    surface
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkSurfaceCapabilities2KHR {
     VkStructureType                                 sType
     void*                                           pNext
     VkSurfaceCapabilitiesKHR                        surfaceCapabilities
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@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_MVK_ios_surface") // 123
 class VkIOSSurfaceCreateInfoMVK {
     VkStructureType                                 sType
@@ -4305,6 +4719,120 @@
     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_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_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_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
+}
+
 ////////////////
 //  Commands  //
 ////////////////
@@ -7144,84 +7672,80 @@
     return ?
 }
 
-@extension("VK_KHX_external_memory_capabilities") // 72
-cmd void vkGetPhysicalDeviceExternalBufferPropertiesKHX(
+@extension("VK_KHR_external_memory_capabilities") // 72
+cmd void vkGetPhysicalDeviceExternalBufferPropertiesKHR(
         VkPhysicalDevice                                physicalDevice,
-        const VkPhysicalDeviceExternalBufferInfoKHX*    pExternalBufferInfo,
-        VkExternalBufferPropertiesKHX*                  pExternalBufferProperties) {
+        const VkPhysicalDeviceExternalBufferInfoKHR*    pExternalBufferInfo,
+        VkExternalBufferPropertiesKHR*                  pExternalBufferProperties) {
 }
 
-@extension("VK_KHX_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandleKHX(
+@extension("VK_KHR_external_memory_win32") // 74
+cmd VkResult vkGetMemoryWin32HandleKHR(
         VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+        const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
         platform.HANDLE*                            pHandle) {
     return ?
 }
 
-@extension("VK_KHX_external_memory_win32") // 74
-cmd VkResult vkGetMemoryWin32HandlePropertiesKHX(
+@extension("VK_KHR_external_memory_win32") // 74
+cmd VkResult vkGetMemoryWin32HandlePropertiesKHR(
         VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
         platform.HANDLE                             handle,
-        VkMemoryWin32HandlePropertiesKHX*           pMemoryWin32HandleProperties) {
+        VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties) {
     return ?
 }
 
-@extension("VK_KHX_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdKHX(
+@extension("VK_KHR_external_memory_fd") // 75
+cmd VkResult vkGetMemoryFdKHR(
         VkDevice                                    device,
-        VkDeviceMemory                              memory,
-        VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+        const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
         s32*                                        pFd) {
     return ?
 }
 
-@extension("VK_KHX_external_memory_fd") // 75
-cmd VkResult vkGetMemoryFdPropertiesKHX(
+@extension("VK_KHR_external_memory_fd") // 75
+cmd VkResult vkGetMemoryFdPropertiesKHR(
         VkDevice                                    device,
-        VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
+        VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
         s32                                         fd,
-        VkMemoryFdPropertiesKHX*                    pMemoryFdProperties) {
+        VkMemoryFdPropertiesKHR*                    pMemoryFdProperties) {
     return ?
 }
 
-@extension("VK_KHX_external_semaphore_capabilities") // 77
-cmd void vkGetPhysicalDeviceExternalSemaphorePropertiesKHX(
+@extension("VK_KHR_external_semaphore_capabilities") // 77
+cmd void vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
         VkPhysicalDevice                            physicalDevice,
-        const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo,
-        VkExternalSemaphorePropertiesKHX*           pExternalSemaphoreProperties) {
+        const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
+        VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties) {
 }
 
-@extension("VK_KHX_external_semaphore_win32") // 79
-cmd VkResult vkImportSemaphoreWin32HandleKHX(
+@extension("VK_KHR_external_semaphore_win32") // 79
+cmd VkResult vkImportSemaphoreWin32HandleKHR(
         VkDevice                                    device,
-        const VkImportSemaphoreWin32HandleInfoKHX*  pImportSemaphoreWin32HandleInfo) {
+        const VkImportSemaphoreWin32HandleInfoKHR*  pImportSemaphoreWin32HandleInfo) {
     return ?
 }
 
-@extension("VK_KHX_external_semaphore_win32") // 79
-cmd VkResult vkGetSemaphoreWin32HandleKHX(
+@extension("VK_KHR_external_semaphore_win32") // 79
+cmd VkResult vkGetSemaphoreWin32HandleKHR(
         VkDevice                                    device,
-        VkSemaphore                                 semaphore,
-        VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType,
+        const VkSemaphoreGetWin32HandleInfoKHR*     pGetWin32HandleInfo,
         platform.HANDLE*                            pHandle) {
     return ?
 }
 
-@extension("VK_KHX_external_semaphore_fd") // 80
-cmd VkResult vkImportSemaphoreFdKHX(
+@extension("VK_KHR_external_semaphore_fd") // 80
+cmd VkResult vkImportSemaphoreFdKHR(
         VkDevice                                    device,
-        const VkImportSemaphoreFdInfoKHX*           pImportSemaphoreFdInfo) {
+        const VkImportSemaphoreFdInfoKHR*           pImportSemaphoreFdInfo) {
     return ?
 }
 
-@extension("VK_KHX_external_semaphore_fd") // 80
-cmd VkResult vkGetSemaphoreFdKHX(
+@extension("VK_KHR_external_semaphore_fd") // 80
+cmd VkResult vkGetSemaphoreFdKHR(
         VkDevice                                    device,
-        VkSemaphore                                 semaphore,
-        VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType,
+        const VkSemaphoreGetFdInfoKHR*              pGetFdInfo,
         s32*                                        pFd) {
     return ?
 }
@@ -7462,7 +7986,44 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@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,
@@ -7470,7 +8031,7 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
         VkPhysicalDevice                            physicalDevice,
         const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
@@ -7497,6 +8058,28 @@
     return ?
 }
 
+@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) {
+}
+
 ////////////////
 // Validation //
 ////////////////
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index 43a9a9c..d3e5f0f 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -17,7 +17,7 @@
 #ifndef __VK_ANDROID_NATIVE_BUFFER_H__
 #define __VK_ANDROID_NATIVE_BUFFER_H__
 
-#include <system/window.h>
+#include <cutils/native_handle.h>
 #include <vulkan/vulkan.h>
 
 #ifdef __cplusplus
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 67eba86..0271d38 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,11 +43,11 @@
 #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 46
+#define VK_HEADER_VERSION 54
 
 
 #define VK_NULL_HANDLE 0
-
+        
 
 
 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
@@ -60,7 +60,7 @@
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
 #endif
 #endif
-
+        
 
 
 typedef uint32_t VkFlags;
@@ -146,7 +146,7 @@
     VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
     VK_ERROR_INVALID_SHADER_NV = -1000012000,
     VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
-    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX = -1000072003,
+    VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = -1000072003,
     VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
     VK_RESULT_END_RANGE = VK_INCOMPLETE,
     VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
@@ -222,6 +222,7 @@
     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_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
     VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
@@ -256,31 +257,33 @@
     VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
     VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHX = 1000071000,
-    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHX = 1000071001,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX = 1000071002,
-    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX = 1000071003,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX = 1000071007,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX = 1000072000,
-    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX = 1000072001,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX = 1000072002,
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073000,
-    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073001,
-    VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHX = 1000073002,
-    VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHX = 1000074000,
-    VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHX = 1000074001,
-    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHX = 1000075000,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHX = 1000076000,
-    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHX = 1000076001,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHX = 1000077000,
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078000,
-    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078001,
-    VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX = 1000078002,
-    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX = 1000079000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = 1000071000,
+    VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = 1000071001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = 1000071002,
+    VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = 1000071003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = 1000071004,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = 1000072000,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = 1000072001,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = 1000072002,
+    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
+    VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
+    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_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = 1000076000,
+    VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = 1000076001,
+    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = 1000077000,
+    VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000,
+    VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001,
+    VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002,
+    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_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
     VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
@@ -302,11 +305,34 @@
     VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
     VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
     VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = 1000112000,
+    VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = 1000112001,
+    VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = 1000113000,
+    VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000,
+    VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001,
+    VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002,
+    VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000,
+    VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
     VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
     VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
     VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = 1000127000,
+    VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = 1000127001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
+    VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146000,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146001,
+    VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146002,
+    VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = 1000146003,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = 1000146004,
+    VK_STRUCTURE_TYPE_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_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),
@@ -660,6 +686,7 @@
     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),
@@ -760,6 +787,52 @@
     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),
@@ -901,6 +974,47 @@
     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_SURFACE_KHR = 1000000000,
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
+    VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
+    VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000,
+    VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
+    VK_OBJECT_TYPE_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 VkFlags VkInstanceCreateFlags;
 
 typedef enum VkFormatFeatureFlagBits {
@@ -920,6 +1034,7 @@
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
     VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
     VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000,
     VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkFormatFeatureFlagBits;
 typedef VkFlags VkFormatFeatureFlags;
@@ -1197,6 +1312,7 @@
     VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
     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_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAccessFlagBits;
 typedef VkFlags VkAccessFlags;
@@ -3317,6 +3433,7 @@
     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_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),
@@ -3823,7 +3940,7 @@
 #define VK_KHR_win32_surface 1
 #include <windows.h>
 
-#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 5
+#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6
 #define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
 
 typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
@@ -3988,6 +4105,377 @@
     VkCommandPoolTrimFlagsKHR                   flags);
 #endif
 
+#define VK_KHR_external_memory_capabilities 1
+#define VK_LUID_SIZE_KHR                  8
+#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
+
+
+typedef enum VkExternalMemoryHandleTypeFlagBitsKHR {
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = 0x00000008,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = 0x00000010,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = 0x00000020,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = 0x00000040,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBitsKHR;
+typedef VkFlags VkExternalMemoryHandleTypeFlagsKHR;
+
+typedef enum VkExternalMemoryFeatureFlagBitsKHR {
+    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = 0x00000004,
+    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBitsKHR;
+typedef VkFlags VkExternalMemoryFeatureFlagsKHR;
+
+typedef struct VkExternalMemoryPropertiesKHR {
+    VkExternalMemoryFeatureFlagsKHR       externalMemoryFeatures;
+    VkExternalMemoryHandleTypeFlagsKHR    exportFromImportedHandleTypes;
+    VkExternalMemoryHandleTypeFlagsKHR    compatibleHandleTypes;
+} VkExternalMemoryPropertiesKHR;
+
+typedef struct VkPhysicalDeviceExternalImageFormatInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+} VkPhysicalDeviceExternalImageFormatInfoKHR;
+
+typedef struct VkExternalImageFormatPropertiesKHR {
+    VkStructureType                  sType;
+    void*                            pNext;
+    VkExternalMemoryPropertiesKHR    externalMemoryProperties;
+} VkExternalImageFormatPropertiesKHR;
+
+typedef struct VkPhysicalDeviceExternalBufferInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkBufferCreateFlags                      flags;
+    VkBufferUsageFlags                       usage;
+    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+} VkPhysicalDeviceExternalBufferInfoKHR;
+
+typedef struct VkExternalBufferPropertiesKHR {
+    VkStructureType                  sType;
+    void*                            pNext;
+    VkExternalMemoryPropertiesKHR    externalMemoryProperties;
+} VkExternalBufferPropertiesKHR;
+
+typedef struct VkPhysicalDeviceIDPropertiesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    uint8_t            deviceUUID[VK_UUID_SIZE];
+    uint8_t            driverUUID[VK_UUID_SIZE];
+    uint8_t            deviceLUID[VK_LUID_SIZE_KHR];
+    uint32_t           deviceNodeMask;
+    VkBool32           deviceLUIDValid;
+} VkPhysicalDeviceIDPropertiesKHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo, VkExternalBufferPropertiesKHR* pExternalBufferProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo,
+    VkExternalBufferPropertiesKHR*              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      (~0U-1)
+
+typedef struct VkExternalMemoryImageCreateInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
+} VkExternalMemoryImageCreateInfoKHR;
+
+typedef struct VkExternalMemoryBufferCreateInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
+} VkExternalMemoryBufferCreateInfoKHR;
+
+typedef struct VkExportMemoryAllocateInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkExternalMemoryHandleTypeFlagsKHR    handleTypes;
+} VkExportMemoryAllocateInfoKHR;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHR_external_memory_win32 1
+#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
+
+typedef struct VkImportMemoryWin32HandleInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+    HANDLE                                   handle;
+    LPCWSTR                                  name;
+} VkImportMemoryWin32HandleInfoKHR;
+
+typedef struct VkExportMemoryWin32HandleInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    const SECURITY_ATTRIBUTES*    pAttributes;
+    DWORD                         dwAccess;
+    LPCWSTR                       name;
+} VkExportMemoryWin32HandleInfoKHR;
+
+typedef struct VkMemoryWin32HandlePropertiesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           memoryTypeBits;
+} VkMemoryWin32HandlePropertiesKHR;
+
+typedef struct VkMemoryGetWin32HandleInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkDeviceMemory                           memory;
+    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+} VkMemoryGetWin32HandleInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
+    VkDevice                                    device,
+    const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
+    HANDLE*                                     pHandle);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
+    VkDevice                                    device,
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
+    HANDLE                                      handle,
+    VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#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;
+    VkExternalMemoryHandleTypeFlagBitsKHR    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;
+    VkExternalMemoryHandleTypeFlagBitsKHR    handleType;
+} VkMemoryGetFdInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
+
+#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,
+    VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
+    int                                         fd,
+    VkMemoryFdPropertiesKHR*                    pMemoryFdProperties);
+#endif
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHR_win32_keyed_mutex 1
+#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
+
+typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
+    VkStructureType          sType;
+    const void*              pNext;
+    uint32_t                 acquireCount;
+    const VkDeviceMemory*    pAcquireSyncs;
+    const uint64_t*          pAcquireKeys;
+    const uint32_t*          pAcquireTimeouts;
+    uint32_t                 releaseCount;
+    const VkDeviceMemory*    pReleaseSyncs;
+    const uint64_t*          pReleaseKeys;
+} VkWin32KeyedMutexAcquireReleaseInfoKHR;
+
+
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#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 enum VkExternalSemaphoreHandleTypeFlagBitsKHR {
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = 0x00000008,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000010,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalSemaphoreHandleTypeFlagBitsKHR;
+typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHR;
+
+typedef enum VkExternalSemaphoreFeatureFlagBitsKHR {
+    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalSemaphoreFeatureFlagBitsKHR;
+typedef VkFlags VkExternalSemaphoreFeatureFlagsKHR;
+
+typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHR {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+} VkPhysicalDeviceExternalSemaphoreInfoKHR;
+
+typedef struct VkExternalSemaphorePropertiesKHR {
+    VkStructureType                          sType;
+    void*                                    pNext;
+    VkExternalSemaphoreHandleTypeFlagsKHR    exportFromImportedHandleTypes;
+    VkExternalSemaphoreHandleTypeFlagsKHR    compatibleHandleTypes;
+    VkExternalSemaphoreFeatureFlagsKHR       externalSemaphoreFeatures;
+} VkExternalSemaphorePropertiesKHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
+    VkExternalSemaphorePropertiesKHR*           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 enum VkSemaphoreImportFlagBitsKHR {
+    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
+    VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkSemaphoreImportFlagBitsKHR;
+typedef VkFlags VkSemaphoreImportFlagsKHR;
+
+typedef struct VkExportSemaphoreCreateInfoKHR {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkExternalSemaphoreHandleTypeFlagsKHR    handleTypes;
+} VkExportSemaphoreCreateInfoKHR;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHR_external_semaphore_win32 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
+
+typedef struct VkImportSemaphoreWin32HandleInfoKHR {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkSemaphore                                 semaphore;
+    VkSemaphoreImportFlagsKHR                   flags;
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+    HANDLE                                      handle;
+    LPCWSTR                                     name;
+} VkImportSemaphoreWin32HandleInfoKHR;
+
+typedef struct VkExportSemaphoreWin32HandleInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    const SECURITY_ATTRIBUTES*    pAttributes;
+    DWORD                         dwAccess;
+    LPCWSTR                       name;
+} VkExportSemaphoreWin32HandleInfoKHR;
+
+typedef struct VkD3D12FenceSubmitInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           waitSemaphoreValuesCount;
+    const uint64_t*    pWaitSemaphoreValues;
+    uint32_t           signalSemaphoreValuesCount;
+    const uint64_t*    pSignalSemaphoreValues;
+} VkD3D12FenceSubmitInfoKHR;
+
+typedef struct VkSemaphoreGetWin32HandleInfoKHR {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkSemaphore                                 semaphore;
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+} VkSemaphoreGetWin32HandleInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR(
+    VkDevice                                    device,
+    const VkImportSemaphoreWin32HandleInfoKHR*  pImportSemaphoreWin32HandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR(
+    VkDevice                                    device,
+    const VkSemaphoreGetWin32HandleInfoKHR*     pGetWin32HandleInfo,
+    HANDLE*                                     pHandle);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#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;
+    VkSemaphoreImportFlagsKHR                   flags;
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    handleType;
+    int                                         fd;
+} VkImportSemaphoreFdInfoKHR;
+
+typedef struct VkSemaphoreGetFdInfoKHR {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkSemaphore                                 semaphore;
+    VkExternalSemaphoreHandleTypeFlagBitsKHR    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 1
 #define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
@@ -4011,6 +4499,21 @@
     const VkWriteDescriptorSet*                 pDescriptorWrites);
 #endif
 
+#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 struct VkPhysicalDevice16BitStorageFeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           storageBuffer16BitAccess;
+    VkBool32           uniformAndStorageBuffer16BitAccess;
+    VkBool32           storagePushConstant16;
+    VkBool32           storageInputOutput16;
+} 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"
@@ -4107,12 +4610,311 @@
     const void*                                 pData);
 #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 enum VkExternalFenceHandleTypeFlagBitsKHR {
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000008,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalFenceHandleTypeFlagBitsKHR;
+typedef VkFlags VkExternalFenceHandleTypeFlagsKHR;
+
+typedef enum VkExternalFenceFeatureFlagBitsKHR {
+    VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
+    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
+    VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkExternalFenceFeatureFlagBitsKHR;
+typedef VkFlags VkExternalFenceFeatureFlagsKHR;
+
+typedef struct VkPhysicalDeviceExternalFenceInfoKHR {
+    VkStructureType                         sType;
+    const void*                             pNext;
+    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+} VkPhysicalDeviceExternalFenceInfoKHR;
+
+typedef struct VkExternalFencePropertiesKHR {
+    VkStructureType                      sType;
+    void*                                pNext;
+    VkExternalFenceHandleTypeFlagsKHR    exportFromImportedHandleTypes;
+    VkExternalFenceHandleTypeFlagsKHR    compatibleHandleTypes;
+    VkExternalFenceFeatureFlagsKHR       externalFenceFeatures;
+} VkExternalFencePropertiesKHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, VkExternalFencePropertiesKHR* pExternalFenceProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
+    VkExternalFencePropertiesKHR*               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 enum VkFenceImportFlagBitsKHR {
+    VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
+    VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkFenceImportFlagBitsKHR;
+typedef VkFlags VkFenceImportFlagsKHR;
+
+typedef struct VkExportFenceCreateInfoKHR {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkExternalFenceHandleTypeFlagsKHR    handleTypes;
+} VkExportFenceCreateInfoKHR;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHR_external_fence_win32 1
+#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
+
+typedef struct VkImportFenceWin32HandleInfoKHR {
+    VkStructureType                         sType;
+    const void*                             pNext;
+    VkFence                                 fence;
+    VkFenceImportFlagsKHR                   flags;
+    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+    HANDLE                                  handle;
+    LPCWSTR                                 name;
+} VkImportFenceWin32HandleInfoKHR;
+
+typedef struct VkExportFenceWin32HandleInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    const SECURITY_ATTRIBUTES*    pAttributes;
+    DWORD                         dwAccess;
+    LPCWSTR                       name;
+} VkExportFenceWin32HandleInfoKHR;
+
+typedef struct VkFenceGetWin32HandleInfoKHR {
+    VkStructureType                         sType;
+    const void*                             pNext;
+    VkFence                                 fence;
+    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+} VkFenceGetWin32HandleInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR(
+    VkDevice                                    device,
+    const VkImportFenceWin32HandleInfoKHR*      pImportFenceWin32HandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR(
+    VkDevice                                    device,
+    const VkFenceGetWin32HandleInfoKHR*         pGetWin32HandleInfo,
+    HANDLE*                                     pHandle);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#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;
+    VkFenceImportFlagsKHR                   flags;
+    VkExternalFenceHandleTypeFlagBitsKHR    handleType;
+    int                                     fd;
+} VkImportFenceFdInfoKHR;
+
+typedef struct VkFenceGetFdInfoKHR {
+    VkStructureType                         sType;
+    const void*                             pNext;
+    VkFence                                 fence;
+    VkExternalFenceHandleTypeFlagBitsKHR    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_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 struct VkPhysicalDeviceVariablePointerFeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           variablePointersStorageBuffer;
+    VkBool32           variablePointers;
+} VkPhysicalDeviceVariablePointerFeaturesKHR;
+
+
+
+#define VK_KHR_dedicated_allocation 1
+#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 1
+#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
+
+typedef struct VkMemoryDedicatedRequirementsKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           prefersDedicatedAllocation;
+    VkBool32           requiresDedicatedAllocation;
+} VkMemoryDedicatedRequirementsKHR;
+
+typedef struct VkMemoryDedicatedAllocateInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+    VkBuffer           buffer;
+} VkMemoryDedicatedAllocateInfoKHR;
+
+
+
+#define VK_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_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 struct VkBufferMemoryRequirementsInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           buffer;
+} VkBufferMemoryRequirementsInfo2KHR;
+
+typedef struct VkImageMemoryRequirementsInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+} VkImageMemoryRequirementsInfo2KHR;
+
+typedef struct VkImageSparseMemoryRequirementsInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkImage            image;
+} VkImageSparseMemoryRequirementsInfo2KHR;
+
+typedef struct VkMemoryRequirements2KHR {
+    VkStructureType         sType;
+    void*                   pNext;
+    VkMemoryRequirements    memoryRequirements;
+} VkMemoryRequirements2KHR;
+
+typedef struct VkSparseImageMemoryRequirements2KHR {
+    VkStructureType                    sType;
+    void*                              pNext;
+    VkSparseImageMemoryRequirements    memoryRequirements;
+} VkSparseImageMemoryRequirements2KHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
+    VkDevice                                    device,
+    const VkImageMemoryRequirementsInfo2KHR*    pInfo,
+    VkMemoryRequirements2KHR*                   pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR(
+    VkDevice                                    device,
+    const VkBufferMemoryRequirementsInfo2KHR*   pInfo,
+    VkMemoryRequirements2KHR*                   pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR(
+    VkDevice                                    device,
+    const VkImageSparseMemoryRequirementsInfo2KHR* pInfo,
+    uint32_t*                                   pSparseMemoryRequirementCount,
+    VkSparseImageMemoryRequirements2KHR*        pSparseMemoryRequirements);
+#endif
+
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  6
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  8
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
 #define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
+#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
 
 
 typedef enum VkDebugReportObjectTypeEXT {
@@ -4144,7 +4946,7 @@
     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_EXT = 28,
+    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,
@@ -4156,15 +4958,6 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
 } VkDebugReportObjectTypeEXT;
 
-typedef enum VkDebugReportErrorEXT {
-    VK_DEBUG_REPORT_ERROR_NONE_EXT = 0,
-    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1,
-    VK_DEBUG_REPORT_ERROR_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_ERROR_NONE_EXT,
-    VK_DEBUG_REPORT_ERROR_END_RANGE_EXT = VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT,
-    VK_DEBUG_REPORT_ERROR_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT - VK_DEBUG_REPORT_ERROR_NONE_EXT + 1),
-    VK_DEBUG_REPORT_ERROR_MAX_ENUM_EXT = 0x7FFFFFFF
-} VkDebugReportErrorEXT;
-
 
 typedef enum VkDebugReportFlagBitsEXT {
     VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001,
@@ -4394,6 +5187,18 @@
 #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_KHX_multiview 1
 #define VK_KHX_MULTIVIEW_SPEC_VERSION     1
 #define VK_KHX_MULTIVIEW_EXTENSION_NAME   "VK_KHX_multiview"
@@ -4749,9 +5554,10 @@
 
 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_ALL_EXT,
-    VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_ALL_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1),
+    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;
 
@@ -4829,341 +5635,6 @@
     VkPhysicalDeviceGroupPropertiesKHX*         pPhysicalDeviceGroupProperties);
 #endif
 
-#define VK_KHX_external_memory_capabilities 1
-#define VK_LUID_SIZE_KHX                  8
-#define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_memory_capabilities"
-
-
-typedef enum VkExternalMemoryHandleTypeFlagBitsKHX {
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHX = 0x00000008,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHX = 0x00000010,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHX = 0x00000020,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHX = 0x00000040,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkExternalMemoryHandleTypeFlagBitsKHX;
-typedef VkFlags VkExternalMemoryHandleTypeFlagsKHX;
-
-typedef enum VkExternalMemoryFeatureFlagBitsKHX {
-    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHX = 0x00000001,
-    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHX = 0x00000002,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHX = 0x00000004,
-    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkExternalMemoryFeatureFlagBitsKHX;
-typedef VkFlags VkExternalMemoryFeatureFlagsKHX;
-
-typedef struct VkExternalMemoryPropertiesKHX {
-    VkExternalMemoryFeatureFlagsKHX       externalMemoryFeatures;
-    VkExternalMemoryHandleTypeFlagsKHX    exportFromImportedHandleTypes;
-    VkExternalMemoryHandleTypeFlagsKHX    compatibleHandleTypes;
-} VkExternalMemoryPropertiesKHX;
-
-typedef struct VkPhysicalDeviceExternalImageFormatInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHX    handleType;
-} VkPhysicalDeviceExternalImageFormatInfoKHX;
-
-typedef struct VkExternalImageFormatPropertiesKHX {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkExternalMemoryPropertiesKHX    externalMemoryProperties;
-} VkExternalImageFormatPropertiesKHX;
-
-typedef struct VkPhysicalDeviceExternalBufferInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkBufferCreateFlags                      flags;
-    VkBufferUsageFlags                       usage;
-    VkExternalMemoryHandleTypeFlagBitsKHX    handleType;
-} VkPhysicalDeviceExternalBufferInfoKHX;
-
-typedef struct VkExternalBufferPropertiesKHX {
-    VkStructureType                  sType;
-    void*                            pNext;
-    VkExternalMemoryPropertiesKHX    externalMemoryProperties;
-} VkExternalBufferPropertiesKHX;
-
-typedef struct VkPhysicalDeviceIDPropertiesKHX {
-    VkStructureType    sType;
-    void*              pNext;
-    uint8_t            deviceUUID[VK_UUID_SIZE];
-    uint8_t            driverUUID[VK_UUID_SIZE];
-    uint8_t            deviceLUID[VK_LUID_SIZE_KHX];
-    VkBool32           deviceLUIDValid;
-} VkPhysicalDeviceIDPropertiesKHX;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHX)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo, VkExternalBufferPropertiesKHX* pExternalBufferProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHX(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo,
-    VkExternalBufferPropertiesKHX*              pExternalBufferProperties);
-#endif
-
-#define VK_KHX_external_memory 1
-#define VK_KHX_EXTERNAL_MEMORY_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHX_external_memory"
-#define VK_QUEUE_FAMILY_EXTERNAL_KHX      (~0U-1)
-
-typedef struct VkExternalMemoryImageCreateInfoKHX {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHX    handleTypes;
-} VkExternalMemoryImageCreateInfoKHX;
-
-typedef struct VkExternalMemoryBufferCreateInfoKHX {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHX    handleTypes;
-} VkExternalMemoryBufferCreateInfoKHX;
-
-typedef struct VkExportMemoryAllocateInfoKHX {
-    VkStructureType                       sType;
-    const void*                           pNext;
-    VkExternalMemoryHandleTypeFlagsKHX    handleTypes;
-} VkExportMemoryAllocateInfoKHX;
-
-
-
-#ifdef VK_USE_PLATFORM_WIN32_KHX
-#define VK_KHX_external_memory_win32 1
-#define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
-
-typedef struct VkImportMemoryWin32HandleInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHX    handleType;
-    HANDLE                                   handle;
-} VkImportMemoryWin32HandleInfoKHX;
-
-typedef struct VkExportMemoryWin32HandleInfoKHX {
-    VkStructureType               sType;
-    const void*                   pNext;
-    const SECURITY_ATTRIBUTES*    pAttributes;
-    DWORD                         dwAccess;
-    LPCWSTR                       name;
-} VkExportMemoryWin32HandleInfoKHX;
-
-typedef struct VkMemoryWin32HandlePropertiesKHX {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           memoryTypeBits;
-} VkMemoryWin32HandlePropertiesKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHX)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagBitsKHX handleType, HANDLE* pHandle);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHX)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHX handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHX(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory,
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
-    HANDLE*                                     pHandle);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHX(
-    VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
-    HANDLE                                      handle,
-    VkMemoryWin32HandlePropertiesKHX*           pMemoryWin32HandleProperties);
-#endif
-#endif /* VK_USE_PLATFORM_WIN32_KHX */
-
-#define VK_KHX_external_memory_fd 1
-#define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHX_external_memory_fd"
-
-typedef struct VkImportMemoryFdInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalMemoryHandleTypeFlagBitsKHX    handleType;
-    int                                      fd;
-} VkImportMemoryFdInfoKHX;
-
-typedef struct VkMemoryFdPropertiesKHX {
-    VkStructureType    sType;
-    void*              pNext;
-    uint32_t           memoryTypeBits;
-} VkMemoryFdPropertiesKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHX)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagBitsKHX handleType, int* pFd);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHX)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHX handleType, int fd, VkMemoryFdPropertiesKHX* pMemoryFdProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHX(
-    VkDevice                                    device,
-    VkDeviceMemory                              memory,
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
-    int*                                        pFd);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHX(
-    VkDevice                                    device,
-    VkExternalMemoryHandleTypeFlagBitsKHX       handleType,
-    int                                         fd,
-    VkMemoryFdPropertiesKHX*                    pMemoryFdProperties);
-#endif
-
-#ifdef VK_USE_PLATFORM_WIN32_KHR
-#define VK_KHX_win32_keyed_mutex 1
-#define VK_KHX_WIN32_KEYED_MUTEX_SPEC_VERSION 1
-#define VK_KHX_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHX_win32_keyed_mutex"
-
-typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHX {
-    VkStructureType          sType;
-    const void*              pNext;
-    uint32_t                 acquireCount;
-    const VkDeviceMemory*    pAcquireSyncs;
-    const uint64_t*          pAcquireKeys;
-    const uint32_t*          pAcquireTimeouts;
-    uint32_t                 releaseCount;
-    const VkDeviceMemory*    pReleaseSyncs;
-    const uint64_t*          pReleaseKeys;
-} VkWin32KeyedMutexAcquireReleaseInfoKHX;
-
-
-#endif /* VK_USE_PLATFORM_WIN32_KHR */
-
-#define VK_KHX_external_semaphore_capabilities 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_semaphore_capabilities"
-
-
-typedef enum VkExternalSemaphoreHandleTypeFlagBitsKHX {
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX = 0x00000008,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX = 0x00000010,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkExternalSemaphoreHandleTypeFlagBitsKHX;
-typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHX;
-
-typedef enum VkExternalSemaphoreFeatureFlagBitsKHX {
-    VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX = 0x00000001,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX = 0x00000002,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkExternalSemaphoreFeatureFlagBitsKHX;
-typedef VkFlags VkExternalSemaphoreFeatureFlagsKHX;
-
-typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHX {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType;
-} VkPhysicalDeviceExternalSemaphoreInfoKHX;
-
-typedef struct VkExternalSemaphorePropertiesKHX {
-    VkStructureType                          sType;
-    void*                                    pNext;
-    VkExternalSemaphoreHandleTypeFlagsKHX    exportFromImportedHandleTypes;
-    VkExternalSemaphoreHandleTypeFlagsKHX    compatibleHandleTypes;
-    VkExternalSemaphoreFeatureFlagsKHX       externalSemaphoreFeatures;
-} VkExternalSemaphorePropertiesKHX;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHX)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHX(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo,
-    VkExternalSemaphorePropertiesKHX*           pExternalSemaphoreProperties);
-#endif
-
-#define VK_KHX_external_semaphore 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHX_external_semaphore"
-
-typedef struct VkExportSemaphoreCreateInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkExternalSemaphoreHandleTypeFlagsKHX    handleTypes;
-} VkExportSemaphoreCreateInfoKHX;
-
-
-
-#ifdef VK_USE_PLATFORM_WIN32_KHX
-#define VK_KHX_external_semaphore_win32 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHX_external_semaphore_win32"
-
-typedef struct VkImportSemaphoreWin32HandleInfoKHX {
-    VkStructureType                          sType;
-    const void*                              pNext;
-    VkSemaphore                              semaphore;
-    VkExternalSemaphoreHandleTypeFlagsKHX    handleType;
-    HANDLE                                   handle;
-} VkImportSemaphoreWin32HandleInfoKHX;
-
-typedef struct VkExportSemaphoreWin32HandleInfoKHX {
-    VkStructureType               sType;
-    const void*                   pNext;
-    const SECURITY_ATTRIBUTES*    pAttributes;
-    DWORD                         dwAccess;
-    LPCWSTR                       name;
-} VkExportSemaphoreWin32HandleInfoKHX;
-
-typedef struct VkD3D12FenceSubmitInfoKHX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           waitSemaphoreValuesCount;
-    const uint64_t*    pWaitSemaphoreValues;
-    uint32_t           signalSemaphoreValuesCount;
-    const uint64_t*    pSignalSemaphoreValues;
-} VkD3D12FenceSubmitInfoKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHX)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHX* pImportSemaphoreWin32HandleInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHX)(VkDevice device, VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBitsKHX handleType, HANDLE* pHandle);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHX(
-    VkDevice                                    device,
-    const VkImportSemaphoreWin32HandleInfoKHX*  pImportSemaphoreWin32HandleInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHX(
-    VkDevice                                    device,
-    VkSemaphore                                 semaphore,
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType,
-    HANDLE*                                     pHandle);
-#endif
-#endif /* VK_USE_PLATFORM_WIN32_KHX */
-
-#define VK_KHX_external_semaphore_fd 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
-#define VK_KHX_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHX_external_semaphore_fd"
-
-typedef struct VkImportSemaphoreFdInfoKHX {
-    VkStructureType                             sType;
-    const void*                                 pNext;
-    VkSemaphore                                 semaphore;
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType;
-    int                                         fd;
-} VkImportSemaphoreFdInfoKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHX)(VkDevice device, const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHX)(VkDevice device, VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBitsKHX handleType, int* pFd);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHX(
-    VkDevice                                    device,
-    const VkImportSemaphoreFdInfoKHX*           pImportSemaphoreFdInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHX(
-    VkDevice                                    device,
-    VkSemaphore                                 semaphore,
-    VkExternalSemaphoreHandleTypeFlagBitsKHX    handleType,
-    int*                                        pFd);
-#endif
-
 #define VK_NVX_device_generated_commands 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
@@ -5173,29 +5644,29 @@
 
 
 typedef enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX = 7,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX + 1),
+    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_DESCRIPTOR_SET_NVX = 0,
-    VK_OBJECT_ENTRY_PIPELINE_NVX = 1,
-    VK_OBJECT_ENTRY_INDEX_BUFFER_NVX = 2,
-    VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX = 3,
-    VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX = 4,
-    VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX,
-    VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX,
-    VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX + 1),
+    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;
 
@@ -5733,7 +6204,7 @@
 #endif
 
 #define VK_EXT_swapchain_colorspace 1
-#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 2
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 3
 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
 
 
@@ -5770,66 +6241,6 @@
     const VkHdrMetadataEXT*                     pMetadata);
 #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_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
-
-
-
 #ifdef VK_USE_PLATFORM_IOS_MVK
 #define VK_MVK_ios_surface 1
 #define VK_MVK_IOS_SURFACE_SPEC_VERSION   2
@@ -5882,6 +6293,134 @@
 #endif
 #endif /* VK_USE_PLATFORM_MACOS_MVK */
 
+#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_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"
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 6149894..5f9b357 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -75,6 +75,7 @@
         "libbase",
         "liblog",
         "libui",
+        "libgraphicsenv",
         "libutils",
         "libcutils",
         "libz",
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 54c77f1..001eaf1 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -454,9 +454,10 @@
         "vkEnumeratePhysicalDeviceGroupsKHX",
         "vkEnumeratePhysicalDevices",
         "vkGetInstanceProcAddr",
-        "vkGetPhysicalDeviceExternalBufferPropertiesKHX",
+        "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
+        "vkGetPhysicalDeviceExternalFencePropertiesKHR",
         "vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
-        "vkGetPhysicalDeviceExternalSemaphorePropertiesKHX",
+        "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR",
         "vkGetPhysicalDeviceFeatures",
         "vkGetPhysicalDeviceFeatures2KHR",
         "vkGetPhysicalDeviceFormatProperties",
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 5bbe116..cb2d26a 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -1135,9 +1135,10 @@
   {{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_KHX_external_memory_win32"}}true
-  {{else if eq $ext "VK_KHX_win32_keyed_mutex"}}true
-  {{else if eq $ext "VK_KHX_external_semaphore_win32"}}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
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 6f425f5..947a2f7 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -28,9 +28,11 @@
 
 #include <android/dlext.h>
 #include <cutils/properties.h>
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
 #include <utils/Vector.h>
 
+#include "android-base/properties.h"
+
 #include "driver.h"
 #include "stubhal.h"
 
@@ -822,9 +824,9 @@
 
     // conditionally add VK_GOOGLE_display_timing if present timestamps are
     // supported by the driver:
-    char timestamp_property[PROPERTY_VALUE_MAX];
-    property_get("service.sf.present_timestamp", timestamp_property, "1");
-    if (strcmp(timestamp_property, "1") == 0) {
+    const std::string timestamp_property("service.sf.present_timestamp");
+    android::base::WaitForPropertyCreation(timestamp_property);
+    if (android::base::GetBoolProperty(timestamp_property, true)) {
         loader_extensions.push_back({
                 VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
                 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e2c8c06..665a32b 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -22,6 +22,7 @@
 #include <sync/sync.h>
 #include <utils/StrongPointer.h>
 #include <utils/Vector.h>
+#include <system/window.h>
 
 #include "driver.h"
 
@@ -429,6 +430,8 @@
             return HAL_DATASPACE_DISPLAY_P3;
         case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
             return HAL_DATASPACE_V0_SCRGB_LINEAR;
+        case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
+            return HAL_DATASPACE_V0_SCRGB;
         case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
             return HAL_DATASPACE_DCI_P3_LINEAR;
         case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
@@ -637,9 +640,9 @@
         instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
 
     const VkSurfaceFormatKHR kWideColorFormats[] = {
-        {VK_FORMAT_R16G16B16A16_SFLOAT,
-         VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT},
-        {VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+        {VK_FORMAT_R8G8B8A8_UNORM,
+         VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
+        {VK_FORMAT_R8G8B8A8_SRGB,
          VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT},
     };
     const uint32_t kNumWideColorFormats =
@@ -1014,7 +1017,7 @@
             return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
-    err = native_window_set_usage(surface.window.get(), gralloc_usage);
+    err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage));
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
@@ -1091,8 +1094,8 @@
         image_native_buffer.handle = img.buffer->handle;
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
-        image_native_buffer.usage = img.buffer->usage;
-        android_convertGralloc0To1Usage(img.buffer->usage,
+        image_native_buffer.usage = int(img.buffer->usage);
+        android_convertGralloc0To1Usage(int(img.buffer->usage),
             &image_native_buffer.usage2.producer,
             &image_native_buffer.usage2.consumer);
 
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 6714779..a3da651 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -19,12 +19,12 @@
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <algorithm>
 #include <array>
 
 #include <log/log.h>
-#include <utils/Errors.h>
 
 #include "null_driver_gen.h"