Merge changes Ica5f5f5c,Ifb7d2cec,Ia402b4bc,I9c3b6b7e,I36ba19c7, ... into oc-dev

* changes:
  libgui: Make IGraphicBufferConsumer a SafeInterface
  libbinder: Add vector<Parcelable> to SafeInterface
  libbinder: Add sp<NativeHandle> to SafeInterface
  libbinder: Support enums in SafeInterface
  libbinder: Support sp<Flattenable> in SafeInterface
  libbinder: Add int64_t/uint64_t to SafeInterface
  libgui: Normalize IGraphicBufferConsumer methods
  libgui: Format IGraphicBufferConsumer
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index cc4144a..f5dca47 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -836,7 +836,7 @@
                 continue;
             }
 
-            if (!should_dump_hal_interface(info.interfaceName)) {
+            if (!should_dump_hal_interface(info.interfaceName.c_str())) {
                 continue;
             }
 
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index be1a434..1d21b3c 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
 
 LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_HEADER_LIBRARIES := dex2oat_headers
 LOCAL_SHARED_LIBRARIES := \
     libbase \
     libcutils \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 20b960d..3e0f6f0 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1152,6 +1152,9 @@
         }
     }
 
+#if HACK_FOR_37193650
+    extStats->dataSize = extStats->dataSize;
+#else
     int extGid = multiuser_get_ext_gid(userId, appId);
     if (extGid != -1) {
         if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), extGid,
@@ -1166,6 +1169,7 @@
             extStats->dataSize += dq.dqb_curspace;
         }
     }
+#endif
 
     int sharedGid = multiuser_get_shared_gid(userId, appId);
     if (sharedGid != -1) {
@@ -1363,6 +1367,17 @@
         collectQuotaStats(device, userId, appId, &stats, &extStats);
         ATRACE_END();
 
+#if HACK_FOR_37193650
+        ATRACE_BEGIN("external");
+        for (size_t i = 0; i < packageNames.size(); i++) {
+            const char* pkgname = packageNames[i].c_str();
+            auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname);
+            calculate_tree_size(extPath, &extStats.dataSize);
+            auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname);
+            calculate_tree_size(mediaPath, &extStats.dataSize);
+        }
+        ATRACE_END();
+#endif
     } else {
         ATRACE_BEGIN("code");
         for (auto codePath : codePaths) {
@@ -1447,6 +1462,12 @@
         flags &= ~FLAG_USE_QUOTA;
     }
 
+#if HACK_FOR_37193650
+    if (userId != 0) {
+        flags &= ~FLAG_USE_QUOTA;
+    }
+#endif
+
     if (flags & FLAG_USE_QUOTA) {
         struct dqblk dq;
 
@@ -1508,6 +1529,7 @@
         for (auto appId : appIds) {
             if (appId >= AID_APP_START) {
                 collectQuotaStats(device, userId, appId, &stats, &extStats);
+
 #if MEASURE_DEBUG
                 // Sleep to make sure we don't lose logs
                 usleep(1);
@@ -1729,7 +1751,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>& sharedLibraries,
+        const std::unique_ptr<std::string>& seInfo) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     if (packageName && *packageName != "*") {
@@ -1744,9 +1767,9 @@
     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* 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);
+            oat_dir, dexFlags, compiler_filter, volume_uuid, shared_libraries, se_info);
     return res ? error(res, "Failed to dexopt") : ok();
 }
 
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f5b7142..fe8aa14 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -82,7 +82,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>& sharedLibraries,
+            const std::unique_ptr<std::string>& seInfo);
 
     binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
 
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 03ff96e..e738b81 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -50,7 +50,8 @@
             @utf8InCpp String instructionSet, int dexoptNeeded,
             @nullable @utf8InCpp String outputPath, int dexFlags,
             @utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
-            @nullable @utf8InCpp String sharedLibraries);
+            @nullable @utf8InCpp String sharedLibraries,
+            @nullable @utf8InCpp String seInfo);
 
     void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f7e8d13..63afdcd 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -36,6 +36,7 @@
 #include <cutils/sched_policy.h>
 #include <log/log.h>               // TODO: Move everything to base/logging.
 #include <private/android_filesystem_config.h>
+#include <selinux/android.h>
 #include <system/thread_defs.h>
 
 #include "dexopt.h"
@@ -1302,17 +1303,9 @@
     }
     std::string dex_dir = dex_path.substr(0, dirIndex);
 
-    // Assign the gid to the cache gid so that the oat file storage
-    // is counted towards the app cache.
-    int32_t cache_gid = multiuser_get_cache_gid(
-            multiuser_get_user_id(uid), multiuser_get_app_id(uid));
-    // If UID doesn't have a specific cache GID, use UID value
-    if (cache_gid == -1) {
-        cache_gid = uid;
-    }
-
     // Create oat file output directory.
-    if (prepare_app_cache_dir(dex_dir, "oat", 02711, uid, cache_gid) != 0) {
+    mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
+    if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
         LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
         return false;
     }
@@ -1322,7 +1315,7 @@
     oat_dir_out->assign(oat_dir);
 
     // Create oat/isa output directory.
-    if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) {
+    if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
         LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
         return false;
     }
@@ -1366,12 +1359,15 @@
 // Processes the dex_path as a secondary dex files and return true if the path dex file should
 // be compiled. Returns false for errors (logged) or true if the secondary dex path was process
 // successfully.
-// When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded
-// code and oat_dir_out is assigned the oat dir path where the oat file should be stored.
+// When returning true, the output parameters will be:
+//   - is_public_out: whether or not the oat file should not be made public
+//   - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
+//   - oat_dir_out: the oat dir path where the oat file should be stored
+//   - dex_path_out: the real path of the dex file
 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, int* dexopt_needed_out, std::string* oat_dir_out,
-        std::string* dex_path_out) {
+        const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
+        std::string* oat_dir_out, std::string* dex_path_out) {
     int storage_flag;
 
     if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
@@ -1407,7 +1403,8 @@
     }
 
     // Check if the path exist. If not, there's nothing to do.
-    if (access(dex_path.c_str(), F_OK) != 0) {
+    struct stat dex_path_stat;
+    if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
         if (errno == ENOENT) {
             // Secondary dex files might be deleted any time by the app.
             // Nothing to do if that's the case
@@ -1418,6 +1415,11 @@
         }
     }
 
+    // Check if we should make the oat file public.
+    // Note that if the dex file is not public the compiled code cannot be made public.
+    *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
+            ((dex_path_stat.st_mode & S_IROTH) != 0);
+
     // Prepare the oat directories.
     if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
         return false;
@@ -1458,14 +1460,14 @@
 
 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* volume_uuid, const char* shared_libraries, const char* se_info) {
     CHECK(pkgname != nullptr);
     CHECK(pkgname[0] != 0);
     if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
         LOG_FATAL("dexopt flags contains unknown fields\n");
     }
 
-    bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
+    bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
     bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
@@ -1477,7 +1479,8 @@
     std::string dex_real_path;
     if (is_secondary_dex) {
         if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
-                instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str, &dex_real_path)) {
+                instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
+                &dex_real_path)) {
             oat_dir = oat_dir_str.c_str();
             dex_path = dex_real_path.c_str();
             if (dexopt_needed == NO_DEXOPT_NEEDED) {
@@ -1516,6 +1519,19 @@
         return -1;
     }
 
+    // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
+    // selinux context (we generate them on the fly during the dexopt invocation and they don't
+    // fully inherit their parent context).
+    // Note that for primary apk the oat files are created before, in a separate installd
+    // call which also does the restorecon. TODO(calin): unify the paths.
+    if (is_secondary_dex) {
+        if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
+                SELINUX_ANDROID_RESTORECON_RECURSE)) {
+            LOG(ERROR) << "Failed to restorecon " << oat_dir;
+            return -1;
+        }
+    }
+
     // Create a swap file if necessary.
     unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
 
@@ -1857,8 +1873,9 @@
                   atoi(params[6]),              // dexopt_flags
                   params[7],                    // compiler_filter
                   parse_null(params[8]),        // volume_uuid
-                  parse_null(params[9]));       // shared_libraries
-    static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param count");
+                  parse_null(params[9]),        // shared_libraries
+                  parse_null(params[10]));       // se_info
+    static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param count");
 }
 
 }  // namespace installd
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index dbf3fae..88144b7 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -60,10 +60,10 @@
 
 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* volume_uuid, const char* shared_libraries, const char* se_info);
 
-static constexpr size_t DEXOPT_PARAM_COUNT = 10U;
-static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param size");
+static constexpr size_t DEXOPT_PARAM_COUNT = 11U;
+static_assert(DEXOPT_PARAM_COUNT == 11U, "Unexpected dexopt param size");
 
 // Helper for the above, converting arguments.
 int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 82b8cc2..e8e6b56 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -33,6 +33,7 @@
 #include <android-base/strings.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
+#include <dex2oat_return_codes.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
@@ -576,7 +577,11 @@
         }
 
         // If the dexopt failed, we may have a stale boot image from a previous OTA run.
-        // Try to delete and retry.
+        // Then regenerate and retry.
+        if (WEXITSTATUS(dexopt_result) !=
+                static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+            return dexopt_result;
+        }
 
         if (!PrepareBootImage(/* force */ true)) {
             LOG(ERROR) << "Forced boot image creating failed. Original error return was "
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 49605be..dab3236 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -547,7 +547,7 @@
 
 TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
     std::string expected =
-        create_primary_current_profile_package_dir_path(1, "com.example") + "/primary.prof";
+        create_primary_current_profile_package_dir_path(0, "com.example") + "/primary.prof";
     EXPECT_EQ(expected,
             create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
 }
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dd94da9..5db547e 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -32,6 +32,7 @@
 
 #define MEASURE_DEBUG 0
 #define FIXUP_DEBUG 0
+#define HACK_FOR_37193650 1
 
 namespace android {
 namespace installd {
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 420ec3c..4c57361 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -301,7 +301,6 @@
                 if (!manifest.add(vintf::ManifestHal{
                     .format = vintf::HalFormat::HIDL,
                     .name = fqName.package(),
-                    .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""},
                     .transportArch = {transport, arch}
                 })) {
                     mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index 8cffb3c..b703ed4 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -9,5 +9,18 @@
     ],
 
     cflags: ["-DXP_UNIX"],
-    //shared_libs: ["librt"],
+}
+
+cc_binary {
+    name: "vndservice",
+
+    proprietary: true,
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "libutils",
+        "libbinder",
+    ],
+
+    cflags: ["-DXP_UNIX", "-DVENDORSERVICES"],
 }
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 428b87c..bc11256 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -68,13 +68,6 @@
 
 int main(int argc, char* const argv[])
 {
-    sp<IServiceManager> sm = defaultServiceManager();
-    fflush(stdout);
-    if (sm == NULL) {
-        aerr << "service: Unable to get default service manager!" << endl;
-        return 20;
-    }
-    
     bool wantsUsage = false;
     int result = 0;
     
@@ -95,6 +88,15 @@
             break;
         }
     }
+#ifdef VENDORSERVICES
+    ProcessState::initWithDriver("/dev/vndbinder");
+#endif
+    sp<IServiceManager> sm = defaultServiceManager();
+    fflush(stdout);
+    if (sm == NULL) {
+        aerr << "service: Unable to get default service manager!" << endl;
+        return 20;
+    }
     
     if (optind >= argc) {
         wantsUsage = true;
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 68d39db..39d92a7 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -38,7 +38,7 @@
 cc_binary {
     name: "vndservicemanager",
     defaults: ["servicemanager_flags"],
-    proprietary: true,
+    vendor: true,
     srcs: [
         "service_manager.c",
         "binder.c",
@@ -46,6 +46,7 @@
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils", "libselinux"],
+    shared_libs: ["libcutils"],
+    static_libs: ["libselinux"],
     init_rc: ["vndservicemanager.rc"],
 }
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 45bb1d0..1f56a47 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -65,7 +65,11 @@
 static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
 {
     char *sctx = NULL;
+#ifdef VENDORSERVICEMANAGER
+    const char *class = "vndservice_manager";
+#else
     const char *class = "service_manager";
+#endif
     bool allowed;
     struct audit_data ad;
 
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index bd0b224..804afc9 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -6,6 +6,7 @@
 	vrscreencap.cpp
 
 LOCAL_STATIC_LIBRARIES := \
+	libbufferhub \
 	libdisplay \
 	libimageio \
 	libpdx_default_transport \
@@ -14,7 +15,8 @@
 	libcutils \
 	liblog \
 	libpng \
-	libsync
+	libsync \
+	libui \
 
 LOCAL_MODULE := vrscreencap
 
diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml
index 10b96b1..95da181 100644
--- a/data/etc/android.hardware.nfc.hce.xml
+++ b/data/etc/android.hardware.nfc.hce.xml
@@ -18,4 +18,5 @@
      NFC card emulation -->
 <permissions>
     <feature name="android.hardware.nfc.hce" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
index 0d03023..b86890d 100644
--- a/data/etc/android.hardware.nfc.hcef.xml
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -18,4 +18,5 @@
      NFC-F card emulation -->
 <permissions>
     <feature name="android.hardware.nfc.hcef" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.hardware.nfc.xml b/data/etc/android.hardware.nfc.xml
index 81c4a84..5201fa2 100644
--- a/data/etc/android.hardware.nfc.xml
+++ b/data/etc/android.hardware.nfc.xml
@@ -18,4 +18,5 @@
      using Near-Field Communications (NFC). -->
 <permissions>
     <feature name="android.hardware.nfc" />
+    <feature name="android.hardware.nfc.any" />
 </permissions>
diff --git a/data/etc/android.software.activities_on_secondary_displays.xml b/data/etc/android.software.activities_on_secondary_displays.xml
new file mode 100644
index 0000000..db1bdb5
--- /dev/null
+++ b/data/etc/android.software.activities_on_secondary_displays.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<permissions>
+    <feature name="android.software.activities_on_secondary_displays" />
+</permissions>
diff --git a/data/etc/android.software.autofill.xml b/data/etc/android.software.autofill.xml
new file mode 100644
index 0000000..c510d0c
--- /dev/null
+++ b/data/etc/android.software.autofill.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<permissions>
+    <feature name="android.software.autofill" />
+</permissions>
diff --git a/data/etc/android.software.cts.xml b/data/etc/android.software.cts.xml
new file mode 100644
index 0000000..0414c9a
--- /dev/null
+++ b/data/etc/android.software.cts.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.
+-->
+
+<permissions>
+    <!-- This is Android and fully CTS compatible.  Basically this is for CTS tests to use. -->
+    <feature name="android.software.cts" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index b5287ac..0d5d206 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -46,8 +46,10 @@
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
     <feature name="android.software.picture_in_picture" />
+    <feature name="android.software.activities_on_secondary_displays" />
     <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
+    <feature name="android.software.autofill" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 51ea1ca..9b88648 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -46,8 +46,10 @@
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
     <feature name="android.software.picture_in_picture" />
+    <feature name="android.software.activities_on_secondary_displays" />
     <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
+    <feature name="android.software.autofill" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
     <feature name="android.software.device_admin" />
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 186f62c..cdb3fff 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -484,8 +484,9 @@
  *
  * Configure sensor direct report on a direct channel: set rate to value other than
  * {@link ASENSOR_DIRECT_RATE_STOP} so that sensor event can be directly
- * written into the shared memory region used for creating the buffer; set rate to
- * {@link ASENSOR_DIRECT_RATE_STOP} will stop the sensor direct report.
+ * written into the shared memory region used for creating the buffer. It returns a positive token
+ * which can be used for identify sensor events from different sensors on success. Calling with rate
+ * {@link ASENSOR_DIRECT_RATE_STOP} will stop direct report of the sensor specified in the channel.
  *
  * To stop all active sensor direct report configured to a channel, set sensor to NULL and rate to
  * {@link ASENSOR_DIRECT_RATE_STOP}.
@@ -513,7 +514,7 @@
  *                  {@link ASensorManager_createSharedMemoryDirectChannel} or
  *                  {@link ASensorManager_createHardwareBufferDirectChannel}.
  *
- * \return 0 for success or negative integer for failure.
+ * \return positive token for success or negative error code.
  */
 int ASensorManager_configureDirectReport(
         ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index cf2fa47..5d36526 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -72,6 +72,8 @@
     status_t            appendFrom(const Parcel *parcel,
                                    size_t start, size_t len);
 
+    int                 compareData(const Parcel& other);
+
     bool                allowFds() const;
     bool                pushAllowFds(bool allowFds);
     void                restoreAllowFds(bool lastValue);
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index 05e9d09..1ef045d 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -69,6 +69,8 @@
             status_t            setThreadPoolMaxThreadCount(size_t maxThreads);
             void                giveThreadPoolName();
 
+            String8             getDriverName();
+
 private:
     friend class IPCThreadState;
     
@@ -86,6 +88,7 @@
 
             handle_entry*       lookupHandleLocked(int32_t handle);
 
+            String8             mDriverName;
             int                 mDriverFD;
             void*               mVMStart;
 
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index cb9b373..9557b4f 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -32,9 +32,12 @@
 
 // ----------------------------------------------------------------------------
 
-class BitTube;
 class IDisplayEventConnection;
 
+namespace gui {
+class BitTube;
+} // namespace gui
+
 static inline constexpr uint32_t fourcc(char c1, char c2, char c3, char c4) {
     return static_cast<uint32_t>(c1) << 24 |
         static_cast<uint32_t>(c2) << 16 |
@@ -108,15 +111,13 @@
      * should be destroyed and getEvents() shouldn't be called again.
      */
     ssize_t getEvents(Event* events, size_t count);
-    static ssize_t getEvents(const sp<BitTube>& dataChannel,
-            Event* events, size_t count);
+    static ssize_t getEvents(gui::BitTube* dataChannel, Event* events, size_t count);
 
     /*
      * sendEvents write events to the queue and returns how many events were
      * written.
      */
-    static ssize_t sendEvents(const sp<BitTube>& dataChannel,
-            Event const* events, size_t count);
+    static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count);
 
     /*
      * setVsyncRate() sets the Event::VSync delivery rate. A value of
@@ -134,7 +135,7 @@
 
 private:
     sp<IDisplayEventConnection> mEventConnection;
-    sp<BitTube> mDataChannel;
+    std::unique_ptr<gui::BitTube> mDataChannel;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
     static constexpr auto EVENT_COUNT =
             static_cast<size_t>(FrameEvent::EVENT_COUNT);
     static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
-    static constexpr nsecs_t TIMESTAMP_PENDING =
-            std::numeric_limits<nsecs_t>::max();
+    static constexpr nsecs_t TIMESTAMP_PENDING = -2;
 
     static inline bool isValidTimestamp(nsecs_t time) {
         return time != TIMESTAMP_PENDING;
diff --git a/include/gui/IDisplayEventConnection.h b/include/gui/IDisplayEventConnection.h
index 848368c..d783f74 100644
--- a/include/gui/IDisplayEventConnection.h
+++ b/include/gui/IDisplayEventConnection.h
@@ -14,60 +14,52 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-#define ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
+#pragma once
 
 #include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
+
+#include <utils/Errors.h>
+
+#include <cstdint>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
+namespace gui {
 class BitTube;
+} // namespace gui
 
-class IDisplayEventConnection : public IInterface
-{
+class IDisplayEventConnection : public IInterface {
 public:
-
     DECLARE_META_INTERFACE(DisplayEventConnection)
 
     /*
-     * getDataChannel() returns a BitTube where to receive the events from
+     * stealReceiveChannel() returns a BitTube to receive events from. Only the receive file
+     * descriptor of outChannel will be initialized, and this effectively "steals" the receive
+     * channel from the remote end (such that the remote end can only use its send channel).
      */
-    virtual sp<BitTube> getDataChannel() const = 0;
+    virtual status_t stealReceiveChannel(gui::BitTube* outChannel) = 0;
 
     /*
-     * setVsyncRate() sets the vsync event delivery rate. A value of
-     * 1 returns every vsync events. A value of 2 returns every other events,
-     * etc... a value of 0 returns no event unless  requestNextVsync() has
-     * been called.
+     * setVsyncRate() sets the vsync event delivery rate. A value of 1 returns every vsync event.
+     * A value of 2 returns every other event, etc. A value of 0 returns no event unless
+     * requestNextVsync() has been called.
      */
-    virtual void setVsyncRate(uint32_t count) = 0;
+    virtual status_t setVsyncRate(uint32_t count) = 0;
 
     /*
-     * requestNextVsync() schedules the next vsync event. It has no effect
-     * if the vsync rate is > 0.
+     * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
      */
-    virtual void requestNextVsync() = 0;    // asynchronous
+    virtual void requestNextVsync() = 0; // Asynchronous
 };
 
-// ----------------------------------------------------------------------------
-
-class BnDisplayEventConnection : public BnInterface<IDisplayEventConnection>
-{
+class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
 public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
+    BnDisplayEventConnection()
+          : SafeBnInterface<IDisplayEventConnection>("BnDisplayEventConnection") {}
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                        uint32_t flags = 0) override;
 };
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IDISPLAY_EVENT_CONNECTION_H
+} // namespace android
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 2fbe07a..9870ba0 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -126,6 +126,11 @@
     virtual bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& surface) const = 0;
 
+    /* Returns the frame timestamps supported by SurfaceFlinger.
+     */
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const = 0;
+
     /* set display power mode. depending on the mode, it can either trigger
      * screen on, off or low power mode and wait for it to complete.
      * requires ACCESS_SURFACE_FLINGER permission.
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 88ef010..8b1d106 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -426,6 +426,10 @@
     uint64_t mNextFrameNumber = 1;
     uint64_t mLastFrameNumber = 0;
 
+    // Mutable because ANativeWindow::query needs this class const.
+    mutable bool mQueriedSupportedTimestamps;
+    mutable bool mFrameTimestampsSupportsPresent;
+
     // A cached copy of the FrameEventHistory maintained by the consumer.
     bool mEnableFrameTimestamps = false;
     std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a..ec310cf 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@
     status_t    setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
     status_t    setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
     status_t    setLayer(const sp<IBinder>& id, int32_t layer);
+    status_t    setRelativeLayer(const sp<IBinder>& id,
+            const sp<IBinder>& relativeTo, int32_t layer);
     status_t    setAlpha(const sp<IBinder>& id, float alpha=1.0f);
     status_t    setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
     status_t    setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 3cff7df..712a323 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@
 
     status_t    setLayerStack(uint32_t layerStack);
     status_t    setLayer(int32_t layer);
+
+    // Sets a Z order relative to the Surface specified by "relativeTo" but
+    // without becoming a full child of the relative. Z-ordering works exactly
+    // as if it were a child however.
+    //
+    // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+    //
+    // This overrides any previous and is overriden by any future calls
+    // to setLayer.
+    //
+    // If the relative dissapears, the Surface will have no layer and be
+    // invisible, until the next time set(Relative)Layer is called.
+    //
+    // TODO: This is probably a hack. Currently it exists only to work around
+    // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
+    // which allows inserting a window between a SurfaceView and it's main application
+    // window. However, since we are using child windows for the SurfaceView, but not using
+    // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
+    // This is only used by the "TvInputService" and following the port of ViewRootImpl
+    // to child surfaces, we can then port this and remove this method.
+    status_t    setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
     status_t    setPosition(float x, float y);
     status_t    setSize(uint32_t w, uint32_t h);
     status_t    hide();
diff --git a/include/media/cas/CasAPI.h b/include/media/cas/CasAPI.h
index 0e88019..67f4511 100644
--- a/include/media/cas/CasAPI.h
+++ b/include/media/cas/CasAPI.h
@@ -81,23 +81,12 @@
     virtual status_t setPrivateData(
             const CasData &privateData) = 0;
 
-    // Open a session for descrambling a program. The session will receive the
-    // ECM stream corresponding to the CA_PID for the program.
-    virtual status_t openSession(
-            uint16_t program_number,
-            CasSessionId *sessionId) = 0;
-
-    // Open a session for descrambling an elementary stream inside a program.
-    // The session will receive the ECM stream corresponding to the CA_PID for
-    // the stream.
-    virtual status_t openSession(
-            uint16_t program_number,
-            uint16_t elementary_PID,
-            CasSessionId *sessionId) = 0;
+    // Open a session for descrambling a program, or one or more elementary
+    // streams.
+    virtual status_t openSession(CasSessionId *sessionId) = 0;
 
     // Close a previously opened session.
-    virtual status_t closeSession(
-            const CasSessionId &sessionId) = 0;
+    virtual status_t closeSession(const CasSessionId &sessionId) = 0;
 
     // Provide the CA private data from a CA_descriptor in the program map
     // table to a CasPlugin.
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 6b21979..56d7cc8 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -557,6 +557,7 @@
         case OMX_IndexConfigPriority:                   return "ConfigPriority";
         case OMX_IndexConfigOperatingRate:              return "ConfigOperatingRate";
         case OMX_IndexParamConsumerUsageBits:           return "ParamConsumerUsageBits";
+        case OMX_IndexConfigLatency:                    return "ConfigLatency";
         default:                                        return asString((OMX_INDEXTYPE)i, def);
     }
 }
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index eccecaa..5a029d0 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -96,6 +96,7 @@
     OMX_IndexConfigPriority,                        /**< reference: OMX_PARAM_U32TYPE */
     OMX_IndexConfigOperatingRate,                   /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
     OMX_IndexParamConsumerUsageBits,                /**< reference: OMX_PARAM_U32TYPE */
+    OMX_IndexConfigLatency,                         /**< reference: OMX_PARAM_U32TYPE */
     OMX_IndexExtOtherEndUnused,
 
     /* Time configurations */
diff --git a/include/private/gui/BitTube.h b/include/private/gui/BitTube.h
deleted file mode 100644
index 9d65fad..0000000
--- a/include/private/gui/BitTube.h
+++ /dev/null
@@ -1,94 +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.
- */
-
-#ifndef ANDROID_GUI_SENSOR_CHANNEL_H
-#define ANDROID_GUI_SENSOR_CHANNEL_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <android/log.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-class Parcel;
-
-class BitTube : public RefBase
-{
-public:
-
-    // creates a BitTube with a default (4KB) send buffer
-    BitTube();
-
-    // creates a BitTube with a a specified send and receive buffer size
-    explicit BitTube(size_t bufsize);
-
-    explicit BitTube(const Parcel& data);
-    virtual ~BitTube();
-
-    // check state after construction
-    status_t initCheck() const;
-
-    // get receive file-descriptor
-    int getFd() const;
-
-    // get the send file-descriptor.
-    int getSendFd() const;
-
-    // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
-    template <typename T>
-    static ssize_t sendObjects(const sp<BitTube>& tube,
-            T const* events, size_t count) {
-        return sendObjects(tube, events, count, sizeof(T));
-    }
-
-    // receive objects (sized blobs). If the receiving buffer isn't large enough,
-    // excess messages are silently discarded.
-    template <typename T>
-    static ssize_t recvObjects(const sp<BitTube>& tube,
-            T* events, size_t count) {
-        return recvObjects(tube, events, count, sizeof(T));
-    }
-
-    // parcels this BitTube
-    status_t writeToParcel(Parcel* reply) const;
-
-private:
-    void init(size_t rcvbuf, size_t sndbuf);
-
-    // send a message. The write is guaranteed to send the whole message or fail.
-    ssize_t write(void const* vaddr, size_t size);
-
-    // receive a message. the passed buffer must be at least as large as the
-    // write call used to send the message, excess data is silently discarded.
-    ssize_t read(void* vaddr, size_t size);
-
-    int mSendFd;
-    mutable int mReceiveFd;
-
-    static ssize_t sendObjects(const sp<BitTube>& tube,
-            void const* events, size_t count, size_t objSize);
-
-    static ssize_t recvObjects(const sp<BitTube>& tube,
-            void* events, size_t count, size_t objSize);
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SENSOR_CHANNEL_H
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 20f51a5..307c764 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@
         eOverrideScalingModeChanged = 0x00000800,
         eGeometryAppliesWithResize  = 0x00001000,
         eReparentChildren           = 0x00002000,
-        eDetachChildren             = 0x00004000
+        eDetachChildren             = 0x00004000,
+        eRelativeLayerChanged       = 0x00008000
     };
 
     layer_state_t()
@@ -104,6 +105,8 @@
 
             sp<IGraphicBufferProducer> barrierGbp;
 
+            sp<IBinder>     relativeLayerHandle;
+
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
diff --git a/include/ui/DebugUtils.h b/include/ui/DebugUtils.h
new file mode 100644
index 0000000..8483808
--- /dev/null
+++ b/include/ui/DebugUtils.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/graphics.h>
+
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace);
+std::string decodeTransfer(android_dataspace dataspace);
+std::string decodeRange(android_dataspace dataspace);
+std::string dataspaceDetails(android_dataspace dataspace);
+std::string decodeColorMode(android_color_mode colormode);
diff --git a/include/ui/Gralloc2.h b/include/ui/Gralloc2.h
new file mode 100644
index 0000000..c59d327
--- /dev/null
+++ b/include/ui/Gralloc2.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC2_H
+#define ANDROID_UI_GRALLOC2_H
+
+#include <string>
+
+#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 {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::IAllocator;
+using hardware::graphics::common::V1_0::BufferUsage;
+using hardware::graphics::common::V1_0::PixelFormat;
+using hardware::graphics::mapper::V2_0::BufferDescriptor;
+using hardware::graphics::mapper::V2_0::Error;
+using hardware::graphics::mapper::V2_0::IMapper;
+using hardware::graphics::mapper::V2_0::YCbCrLayout;
+
+// A wrapper to IMapper
+class Mapper {
+public:
+    Mapper();
+
+    // this will be removed and Mapper will be always valid
+    bool valid() const { return (mMapper != nullptr); }
+
+    Error createDescriptor(
+            const IMapper::BufferDescriptorInfo& descriptorInfo,
+            BufferDescriptor* outDescriptor) const;
+
+    // Import a buffer that is from another HAL, another process, or is
+    // cloned.
+    //
+    // The returned handle must be freed with freeBuffer.
+    Error importBuffer(const hardware::hidl_handle& rawHandle,
+            buffer_handle_t* outBufferHandle) const;
+
+    void freeBuffer(buffer_handle_t bufferHandle) const;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+            const IMapper::Rect& accessRegion,
+            int acquireFence, void** outData) const;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+            const IMapper::Rect& accessRegion,
+            int acquireFence, YCbCrLayout* outLayout) const;
+
+    // unlock returns a fence sync object (or -1) and the fence sync object is
+    // owned by the caller
+    int unlock(buffer_handle_t bufferHandle) const;
+
+private:
+    sp<IMapper> mMapper;
+};
+
+// A wrapper to IAllocator
+class Allocator {
+public:
+    // An allocator relies on a mapper, and that mapper must be alive at all
+    // time.
+    Allocator(const Mapper& mapper);
+
+    // this will be removed and Allocator will be always valid
+    bool valid() const { return (mAllocator != nullptr); }
+
+    std::string dumpDebugInfo() const;
+
+    /*
+     * The returned buffers are already imported and must not be imported
+     * again.  outBufferHandles must point to a space that can contain at
+     * least "count" buffer_handle_t.
+     */
+    Error allocate(BufferDescriptor descriptor, uint32_t count,
+            uint32_t* outStride, buffer_handle_t* outBufferHandles) const;
+
+    Error allocate(BufferDescriptor descriptor,
+            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+    {
+        return allocate(descriptor, 1, outStride, outBufferHandle);
+    }
+
+    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
+            uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+    {
+        BufferDescriptor descriptor;
+        Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
+        if (error == Error::NONE) {
+            error = allocate(descriptor, count, outStride, outBufferHandles);
+        }
+        return error;
+    }
+
+    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+    {
+        return allocate(descriptorInfo, 1, outStride, outBufferHandle);
+    }
+
+private:
+    const Mapper& mMapper;
+    sp<IAllocator> mAllocator;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC2_H
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
deleted file mode 100644
index dd0f9e0..0000000
--- a/include/ui/GrallocAllocator.h
+++ /dev/null
@@ -1,68 +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.
- */
-
-#ifndef ANDROID_UI_GRALLOC_ALLOCATOR_H
-#define ANDROID_UI_GRALLOC_ALLOCATOR_H
-
-#include <string>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::allocator::V2_0::BufferDescriptor;
-using hardware::graphics::allocator::V2_0::Buffer;
-using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::allocator::V2_0::IAllocatorClient;
-using hardware::graphics::common::V1_0::PixelFormat;
-
-// Allocator is a wrapper to IAllocator, a proxy to server-side allocator.
-class Allocator {
-public:
-    Allocator();
-
-    // this will be removed and Allocator will be always valid
-    bool valid() const { return (mAllocator != nullptr); }
-
-    std::string dumpDebugInfo() const;
-
-    Error createBufferDescriptor(
-            const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor* outDescriptor) const;
-    void destroyBufferDescriptor(BufferDescriptor descriptor) const;
-
-    Error allocate(BufferDescriptor descriptor, Buffer* outBuffer) const;
-    void free(Buffer buffer) const;
-
-    Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
-            native_handle_t** outBufferHandle) const;
-
-private:
-    sp<IAllocator> mAllocator;
-    sp<IAllocatorClient> mClient;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_ALLOCATOR_H
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
deleted file mode 100644
index 5a0d64b..0000000
--- a/include/ui/GrallocMapper.h
+++ /dev/null
@@ -1,74 +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.
- */
-
-#ifndef ANDROID_UI_GRALLOC_MAPPER_H
-#define ANDROID_UI_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::common::V1_0::PixelFormat;
-using hardware::graphics::mapper::V2_0::FlexLayout;
-using hardware::graphics::mapper::V2_0::BackingStore;
-using hardware::graphics::mapper::V2_0::IMapper;
-
-// Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
-class Mapper {
-public:
-    Mapper();
-
-    // this will be removed and Mapper will be always valid
-    bool valid() const { return (mMapper != nullptr); }
-
-    Error retain(buffer_handle_t handle) const;
-    void release(buffer_handle_t handle) const;
-
-    Error getDimensions(buffer_handle_t handle,
-            uint32_t* outWidth, uint32_t* outHeight) const;
-    Error getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-    Error getLayerCount(buffer_handle_t handle, uint32_t* outLayerCount) const;
-    Error getProducerUsage(buffer_handle_t handle,
-            uint64_t* outProducerUsage) const;
-    Error getConsumerUsage(buffer_handle_t handle,
-            uint64_t* outConsumerUsage) const;
-    Error getBackingStore(buffer_handle_t handle,
-            uint64_t* outBackingStore) const;
-    Error getStride(buffer_handle_t handle, uint32_t* outStride) const;
-
-    Error lock(buffer_handle_t handle, uint64_t producerUsage,
-            uint64_t consumerUsage, const IMapper::Rect& accessRegion,
-            int acquireFence, void** outData) const;
-    Error lock(buffer_handle_t handle, uint64_t producerUsage,
-            uint64_t consumerUsage, const IMapper::Rect& accessRegion,
-            int acquireFence, FlexLayout* outLayout) const;
-    int unlock(buffer_handle_t handle) const;
-
-private:
-    sp<IMapper> mMapper;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_MAPPER_H
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index e97122b..95eb8fd 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -96,8 +96,8 @@
     GraphicBufferAllocator();
     ~GraphicBufferAllocator();
 
-    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
     GraphicBufferMapper& mMapper;
+    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
 
     std::unique_ptr<Gralloc1::Loader> mLoader;
     std::unique_ptr<Gralloc1::Device> mDevice;
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index b6d4021..d69f8fc 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -47,31 +47,15 @@
 public:
     static inline GraphicBufferMapper& get() { return getInstance(); }
 
-    // This may NOT work on devices without a valid Gralloc2::Mapper.
-    status_t registerBuffer(buffer_handle_t handle);
+    // The imported outHandle must be freed with freeBuffer when no longer
+    // needed. rawHandle is owned by the caller.
+    status_t importBuffer(buffer_handle_t rawHandle,
+            buffer_handle_t* outHandle);
 
-    status_t registerBuffer(const GraphicBuffer* buffer);
+    // This is temporary and will be removed soon
+    status_t importBuffer(const GraphicBuffer* buffer);
 
-    status_t unregisterBuffer(buffer_handle_t handle);
-
-    status_t getDimensions(buffer_handle_t handle,
-            uint32_t* outWidth, uint32_t* outHeight) const;
-
-    status_t getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-
-    status_t getLayerCount(buffer_handle_t handle,
-            uint32_t* outLayerCount) const;
-
-    status_t getProducerUsage(buffer_handle_t handle,
-            uint64_t* outProducerUsage) const;
-
-    status_t getConsumerUsage(buffer_handle_t handle,
-            uint64_t* outConsumerUsage) const;
-
-    status_t getBackingStore(buffer_handle_t handle,
-            uint64_t* outBackingStore) const;
-
-    status_t getStride(buffer_handle_t handle, uint32_t* outStride) const;
+    status_t freeBuffer(buffer_handle_t handle);
 
     status_t lock(buffer_handle_t handle,
             uint32_t usage, const Rect& bounds, void** vaddr);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3aeff2e..c7a0f43 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -23,6 +23,7 @@
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
+#include <utils/CallStack.h>
 
 #include <private/binder/Static.h>
 
@@ -136,7 +137,12 @@
         unsigned n;
         for (n = 0; n < 5; n++){
             if (n > 0) {
-                ALOGI("Waiting for service %s...", String8(name).string());
+                if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
+                    ALOGI("Waiting for vendor service %s...", String8(name).string());
+                    CallStack stack(LOG_TAG);
+                } else {
+                    ALOGI("Waiting for service %s...", String8(name).string());
+                }
                 sleep(1);
             }
             sp<IBinder> svc = checkService(name);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index da94305..39bb078 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -553,6 +553,14 @@
     return err;
 }
 
+int Parcel::compareData(const Parcel& other) {
+    size_t size = dataSize();
+    if (size != other.dataSize()) {
+        return size < other.dataSize() ? -1 : 1;
+    }
+    return memcmp(data(), other.data(), size);
+}
+
 bool Parcel::allowFds() const
 {
     return mAllowFds;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5c4cfe2..9ccf07c 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -317,6 +317,10 @@
     androidSetThreadName( makeBinderThreadName().string() );
 }
 
+String8 ProcessState::getDriverName() {
+    return mDriverName;
+}
+
 static int open_driver(const char *driver)
 {
     int fd = open(driver, O_RDWR | O_CLOEXEC);
@@ -346,7 +350,8 @@
 }
 
 ProcessState::ProcessState(const char *driver)
-    : mDriverFD(open_driver(driver))
+    : mDriverName(String8(driver))
+    , mDriverFD(open_driver(driver))
     , mVMStart(MAP_FAILED)
     , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
@@ -367,6 +372,7 @@
             ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
             close(mDriverFD);
             mDriverFD = -1;
+            mDriverName.clear();
         }
     }
 
diff --git a/libs/binder/tests/binderValueTypeTest.cpp b/libs/binder/tests/binderValueTypeTest.cpp
index 1a05a52..c8f4697 100644
--- a/libs/binder/tests/binderValueTypeTest.cpp
+++ b/libs/binder/tests/binderValueTypeTest.cpp
@@ -106,6 +106,6 @@
     value_a.swap(value_b);
     ASSERT_FALSE(value_b.empty());
     ASSERT_TRUE(value_a.empty());
-    ASSERT_TRUE(value_a.getInt(&int_x));
+    ASSERT_TRUE(value_b.getInt(&int_x));
     ASSERT_EQ(31337, int_x);
 }
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 2732071..fe9e05a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -15,6 +15,7 @@
 #include <pthread.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <fstream>
 
 using namespace std;
 using namespace android;
@@ -41,6 +42,8 @@
 
 #define DUMP_PRICISION 3
 
+string trace_path = "/sys/kernel/debug/tracing";
+
 // the default value
 int no_process = 2;
 int iterations = 100;
@@ -48,6 +51,23 @@
 int no_inherent = 0;
 int no_sync = 0;
 int verbose = 0;
+int trace;
+
+bool traceIsOn() {
+  fstream file;
+  file.open(trace_path + "/tracing_on", ios::in);
+  char on;
+  file >> on;
+  file.close();
+  return on == '1';
+}
+
+void traceStop() {
+  ofstream file;
+  file.open(trace_path + "/tracing_on", ios::out | ios::trunc);
+  file << '0' << endl;
+  file.close();
+}
 
 // the deadline latency that we are interested in
 uint64_t deadline_us = 2500;
@@ -197,13 +217,29 @@
   uint64_t m_transactions = 0;
   uint64_t m_total_time = 0;
   uint64_t m_miss = 0;
-
+  bool tracing;
+  Results(bool _tracing) : tracing(_tracing) {
+  }
+  inline bool miss_deadline(uint64_t nano) {
+    return nano > deadline_us * 1000;
+  }
   void add_time(uint64_t nano) {
     m_best = min(nano, m_best);
     m_worst = max(nano, m_worst);
     m_transactions += 1;
     m_total_time += nano;
-    if (nano > deadline_us * 1000) m_miss++;
+    if (miss_deadline(nano)) m_miss++;
+    if (miss_deadline(nano) && tracing) {
+      // There might be multiple process pair running the test concurrently
+      // each may execute following statements and only the first one actually
+      // stop the trace and any traceStop() afterthen has no effect.
+      traceStop();
+      cout << endl;
+      cout << "deadline triggered: halt & stop trace" << endl;
+      cout << "log:" + trace_path + "/trace" << endl;
+      cout << endl;
+      exit(1);
+    }
   }
   void dump() {
     double best = (double)m_best / 1.0E6;
@@ -212,8 +248,9 @@
     // FIXME: libjson?
     cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
          << average << ", \"wst\":" << setw(5) << left << worst
-         << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << m_miss
-         << "}";
+         << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << setw(5)
+         << left << m_miss << ", \"meetR\":" << setw(3) << left
+         << (1.0 - (double)m_miss / m_transactions) << "}";
   }
 };
 
@@ -272,7 +309,7 @@
 void worker_fx(int num, int no_process, int iterations, int payload_size,
                Pipe p) {
   int dummy;
-  Results results_other, results_fifo;
+  Results results_other(false), results_fifo(trace);
 
   // Create BinderWorkerService and for go.
   ProcessState::self()->startThreadPool();
@@ -389,8 +426,28 @@
     }
     if (string(argv[i]) == "-v") {
       verbose = 1;
-      i++;
     }
+    // The -trace argument is used like that:
+    //
+    // First start trace with atrace command as usual
+    // >atrace --async_start sched freq
+    //
+    // then use schd-dbg with -trace arguments
+    //./schd-dbg -trace -deadline_us 2500
+    //
+    // This makes schd-dbg to stop trace once it detects a transaction
+    // duration over the deadline. By writing '0' to
+    // /sys/kernel/debug/tracing and halt the process. The tracelog is
+    // then available on /sys/kernel/debug/trace
+    if (string(argv[i]) == "-trace") {
+      trace = 1;
+    }
+  }
+  if (trace && !traceIsOn()) {
+    cout << "trace is not running" << endl;
+    cout << "check " << trace_path + "/tracing_on" << endl;
+    cout << "use atrace --async_start first" << endl;
+    exit(-1);
   }
   vector<Pipe> pipes;
   thread_dump("main");
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 28c2a48..90ab286 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -126,6 +126,10 @@
         "android.hidl.token@1.0-utils",
         "android.hardware.graphics.bufferqueue@1.0",
     ],
+
+    export_include_dirs: [
+        "include",
+    ],
 }
 
 subdirs = ["tests"]
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 51a8d67..ef7a6f5 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -17,8 +17,8 @@
 #include <private/gui/BitTube.h>
 
 #include <stdint.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -27,45 +27,21 @@
 
 #include <binder/Parcel.h>
 
-
 namespace android {
-// ----------------------------------------------------------------------------
+namespace gui {
 
-// Socket buffer size.  The default is typically about 128KB, which is much larger than
-// we really need.  So we make it smaller.
+// Socket buffer size.  The default is typically about 128KB, which is much larger than we really
+// need. So we make it smaller.
 static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
 
-
-BitTube::BitTube()
-    : mSendFd(-1), mReceiveFd(-1)
-{
-    init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
-}
-
-BitTube::BitTube(size_t bufsize)
-    : mSendFd(-1), mReceiveFd(-1)
-{
+BitTube::BitTube(size_t bufsize) {
     init(bufsize, bufsize);
 }
 
-BitTube::BitTube(const Parcel& data)
-    : mSendFd(-1), mReceiveFd(-1)
-{
-    mReceiveFd = dup(data.readFileDescriptor());
-    if (mReceiveFd < 0) {
-        mReceiveFd = -errno;
-        ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
-                strerror(-mReceiveFd));
-    }
-}
+BitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {}
 
-BitTube::~BitTube()
-{
-    if (mSendFd >= 0)
-        close(mSendFd);
-
-    if (mReceiveFd >= 0)
-        close(mReceiveFd);
+BitTube::BitTube(const Parcel& data) {
+    readFromParcel(&data);
 }
 
 void BitTube::init(size_t rcvbuf, size_t sndbuf) {
@@ -74,39 +50,43 @@
         size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
         setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
         setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
-        // sine we don't use the "return channel", we keep it small...
+        // since we don't use the "return channel", we keep it small...
         setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
         setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
-        mReceiveFd = sockets[0];
-        mSendFd = sockets[1];
+        mReceiveFd.reset(sockets[0]);
+        mSendFd.reset(sockets[1]);
     } else {
-        mReceiveFd = -errno;
-        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
+        mReceiveFd.reset();
+        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
     }
 }
 
-status_t BitTube::initCheck() const
-{
+status_t BitTube::initCheck() const {
     if (mReceiveFd < 0) {
         return status_t(mReceiveFd);
     }
     return NO_ERROR;
 }
 
-int BitTube::getFd() const
-{
+int BitTube::getFd() const {
     return mReceiveFd;
 }
 
-int BitTube::getSendFd() const
-{
+int BitTube::getSendFd() const {
     return mSendFd;
 }
 
-ssize_t BitTube::write(void const* vaddr, size_t size)
-{
+base::unique_fd BitTube::moveReceiveFd() {
+    return std::move(mReceiveFd);
+}
+
+void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
+    mReceiveFd = std::move(receiveFd);
+}
+
+ssize_t BitTube::write(void const* vaddr, size_t size) {
     ssize_t err, len;
     do {
         len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
@@ -116,62 +96,66 @@
     return err == 0 ? len : -err;
 }
 
-ssize_t BitTube::read(void* vaddr, size_t size)
-{
+ssize_t BitTube::read(void* vaddr, size_t size) {
     ssize_t err, len;
     do {
         len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
         err = len < 0 ? errno : 0;
     } while (err == EINTR);
     if (err == EAGAIN || err == EWOULDBLOCK) {
-        // EAGAIN means that we have non-blocking I/O but there was
-        // no data to be read. Nothing the client should care about.
+        // EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the
+        // client should care about.
         return 0;
     }
     return err == 0 ? len : -err;
 }
 
-status_t BitTube::writeToParcel(Parcel* reply) const
-{
-    if (mReceiveFd < 0)
-        return -EINVAL;
+status_t BitTube::writeToParcel(Parcel* reply) const {
+    if (mReceiveFd < 0) return -EINVAL;
 
     status_t result = reply->writeDupFileDescriptor(mReceiveFd);
-    close(mReceiveFd);
-    mReceiveFd = -1;
+    mReceiveFd.reset();
     return result;
 }
 
+status_t BitTube::readFromParcel(const Parcel* parcel) {
+    mReceiveFd.reset(dup(parcel->readFileDescriptor()));
+    if (mReceiveFd < 0) {
+        mReceiveFd.reset();
+        int error = errno;
+        ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error));
+        return -error;
+    }
+    return NO_ERROR;
+}
 
-ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
-        void const* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
     const char* vaddr = reinterpret_cast<const char*>(events);
-    ssize_t size = tube->write(vaddr, count*objSize);
+    ssize_t size = tube->write(vaddr, count * objSize);
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
-            "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
-            count, objSize, size);
+                        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
+                        "sent!)",
+                        count, objSize, size);
 
-    //ALOGE_IF(size<0, "error %d sending %d events", size, count);
+    // ALOGE_IF(size<0, "error %d sending %d events", size, count);
     return size < 0 ? size : size / static_cast<ssize_t>(objSize);
 }
 
-ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
-        void* events, size_t count, size_t objSize)
-{
+ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
     char* vaddr = reinterpret_cast<char*>(events);
-    ssize_t size = tube->read(vaddr, count*objSize);
+    ssize_t size = tube->read(vaddr, count * objSize);
 
     // should never happen because of SOCK_SEQPACKET
     LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
-            "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
-            count, objSize, size);
+                        "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were "
+                        "received!)",
+                        count, objSize, size);
 
-    //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
+    // ALOGE_IF(size<0, "error %d receiving %d events", size, count);
     return size < 0 ? size : size / static_cast<ssize_t>(objSize);
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 07e07e0..1507d51 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -37,7 +37,8 @@
     if (sf != NULL) {
         mEventConnection = sf->createDisplayEventConnection();
         if (mEventConnection != NULL) {
-            mDataChannel = mEventConnection->getDataChannel();
+            mDataChannel = std::make_unique<gui::BitTube>();
+            mEventConnection->stealReceiveChannel(mDataChannel.get());
         }
     }
 }
@@ -80,19 +81,19 @@
 
 ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
         size_t count) {
-    return DisplayEventReceiver::getEvents(mDataChannel, events, count);
+    return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
 }
 
-ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
         Event* events, size_t count)
 {
-    return BitTube::recvObjects(dataChannel, events, count);
+    return gui::BitTube::recvObjects(dataChannel, events, count);
 }
 
-ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
+ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
         Event const* events, size_t count)
 {
-    return BitTube::sendObjects(dataChannel, events, count);
+    return gui::BitTube::sendObjects(dataChannel, events, count);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index e5c3c48..c0e246f 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -14,89 +14,67 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-#include <binder/Parcel.h>
-
 #include <gui/IDisplayEventConnection.h>
 
 #include <private/gui/BitTube.h>
 
 namespace android {
-// ----------------------------------------------------------------------------
 
-enum {
-    GET_DATA_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+namespace { // Anonymous
+
+enum class Tag : uint32_t {
+    STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
     SET_VSYNC_RATE,
-    REQUEST_NEXT_VSYNC
+    REQUEST_NEXT_VSYNC,
+    LAST = REQUEST_NEXT_VSYNC,
 };
 
-class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
-{
+} // Anonymous namespace
+
+class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
 public:
     explicit BpDisplayEventConnection(const sp<IBinder>& impl)
-        : BpInterface<IDisplayEventConnection>(impl)
-    {
+          : SafeBpInterface<IDisplayEventConnection>(impl, "BpDisplayEventConnection") {}
+
+    ~BpDisplayEventConnection() override;
+
+    status_t stealReceiveChannel(gui::BitTube* outChannel) override {
+        return callRemote<decltype(
+                &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
+                                                                outChannel);
     }
 
-    virtual ~BpDisplayEventConnection();
-
-    virtual sp<BitTube> getDataChannel() const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        remote()->transact(GET_DATA_CHANNEL, data, &reply);
-        return new BitTube(reply);
+    status_t setVsyncRate(uint32_t count) override {
+        return callRemote<decltype(&IDisplayEventConnection::setVsyncRate)>(Tag::SET_VSYNC_RATE,
+                                                                            count);
     }
 
-    virtual void setVsyncRate(uint32_t count) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        data.writeUint32(count);
-        remote()->transact(SET_VSYNC_RATE, data, &reply);
-    }
-
-    virtual void requestNextVsync() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
-        remote()->transact(REQUEST_NEXT_VSYNC, data, &reply, IBinder::FLAG_ONEWAY);
+    void requestNextVsync() override {
+        callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
+                Tag::REQUEST_NEXT_VSYNC);
     }
 };
 
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpDisplayEventConnection::~BpDisplayEventConnection() {}
+// Out-of-line virtual method definition to trigger vtable emission in this translation unit (see
+// clang warning -Wweak-vtables)
+BpDisplayEventConnection::~BpDisplayEventConnection() = default;
 
 IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
 
-// ----------------------------------------------------------------------------
-
-status_t BnDisplayEventConnection::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GET_DATA_CHANNEL: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            sp<BitTube> channel(getDataChannel());
-            channel->writeToParcel(reply);
-            return NO_ERROR;
-        }
-        case SET_VSYNC_RATE: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            setVsyncRate(data.readUint32());
-            return NO_ERROR;
-        }
-        case REQUEST_NEXT_VSYNC: {
-            CHECK_INTERFACE(IDisplayEventConnection, data, reply);
-            requestNextVsync();
-            return NO_ERROR;
-        }
+status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                              uint32_t flags) {
+    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+        return BBinder::onTransact(code, data, reply, flags);
     }
-    return BBinder::onTransact(code, data, reply, flags);
+    auto tag = static_cast<Tag>(code);
+    switch (tag) {
+        case Tag::STEAL_RECEIVE_CHANNEL:
+            return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
+        case Tag::SET_VSYNC_RATE:
+            return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
+        case Tag::REQUEST_NEXT_VSYNC:
+            return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
+    }
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5a32d05..4d2692f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -166,6 +166,50 @@
         return result != 0;
     }
 
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const {
+        if (!outSupported) {
+            return UNEXPECTED_NULL;
+        }
+        outSupported->clear();
+
+        Parcel data, reply;
+
+        status_t err = data.writeInterfaceToken(
+                ISurfaceComposer::getInterfaceDescriptor());
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        err = remote()->transact(
+                BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
+                data, &reply);
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        int32_t result = 0;
+        err = reply.readInt32(&result);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        if (result != NO_ERROR) {
+            return result;
+        }
+
+        std::vector<int32_t> supported;
+        err = reply.readInt32Vector(&supported);
+        if (err != NO_ERROR) {
+            return err;
+        }
+
+        outSupported->reserve(supported.size());
+        for (int32_t s : supported) {
+            outSupported->push_back(static_cast<FrameEvent>(s));
+        }
+        return NO_ERROR;
+    }
+
     virtual sp<IDisplayEventConnection> createDisplayEventConnection()
     {
         Parcel data, reply;
@@ -536,6 +580,25 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case GET_SUPPORTED_FRAME_TIMESTAMPS: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            std::vector<FrameEvent> supportedTimestamps;
+            status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
+            status_t err = reply->writeInt32(result);
+            if (err != NO_ERROR) {
+                return err;
+            }
+            if (result != NO_ERROR) {
+                return result;
+            }
+
+            std::vector<int32_t> supported;
+            supported.reserve(supportedTimestamps.size());
+            for (FrameEvent s : supportedTimestamps) {
+                supported.push_back(static_cast<int32_t>(s));
+            }
+            return reply->writeInt32Vector(supported);
+        }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IDisplayEventConnection> connection(createDisplayEventConnection());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2461cba..9b06e63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@
     output.writeUint64(frameNumber);
     output.writeInt32(overrideScalingMode);
     output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+    output.writeStrongBinder(relativeLayerHandle);
     output.write(transparentRegion);
     return NO_ERROR;
 }
@@ -75,6 +76,7 @@
     overrideScalingMode = input.readInt32();
     barrierGbp =
         interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
+    relativeLayerHandle = input.readStrongBinder();
     input.read(transparentRegion);
     return NO_ERROR;
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1149b89..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,6 +52,8 @@
       mAutoRefresh(false),
       mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
       mSharedBufferHasBeenQueued(false),
+      mQueriedSupportedTimestamps(false),
+      mFrameTimestampsSupportsPresent(false),
       mEnableFrameTimestamps(false),
       mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
 {
@@ -209,8 +211,8 @@
     bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
             !e->hasDisplayPresentInfo();
 
-    // LastRefreshStart, DequeueReady, and Release are never
-    // available for the last frame.
+    // LastRefreshStart, DequeueReady, and Release are never available for the
+    // last frame.
     bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
             !e->hasLastRefreshStartInfo() &&
             (e->frameNumber != lastFrameNumber);
@@ -227,14 +229,26 @@
 
 static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
     if (dst != nullptr) {
-        *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+        // We always get valid timestamps for these eventually.
+        *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+                NATIVE_WINDOW_TIMESTAMP_PENDING : src;
     }
 }
 
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+        const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
     if (dst != nullptr) {
+        if (!fenceShouldBeKnown) {
+            *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+            return;
+        }
+
         nsecs_t signalTime = src->getSignalTime();
-        *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+        *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+                    NATIVE_WINDOW_TIMESTAMP_PENDING :
+                (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+                    NATIVE_WINDOW_TIMESTAMP_INVALID :
+                signalTime;
     }
 }
 
@@ -252,6 +266,12 @@
         return INVALID_OPERATION;
     }
 
+    // Verify the requested timestamps are supported.
+    querySupportedTimestampsLocked();
+    if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
+        return BAD_VALUE;
+    }
+
     FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
     if (events == nullptr) {
         // If the entry isn't available in the producer, it's definitely not
@@ -282,12 +302,15 @@
     getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
     getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
 
-    getFrameTimestampFence(outAcquireTime, events->acquireFence);
-    getFrameTimestampFence(
-            outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
-    getFrameTimestampFence(
-            outDisplayPresentTime, events->displayPresentFence);
-    getFrameTimestampFence(outReleaseTime, events->releaseFence);
+    getFrameTimestampFence(outAcquireTime, events->acquireFence,
+            events->hasAcquireInfo());
+    getFrameTimestampFence(outGpuCompositionDoneTime,
+            events->gpuCompositionDoneFence,
+            events->hasGpuCompositionDoneInfo());
+    getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+            events->hasDisplayPresentInfo());
+    getFrameTimestampFence(outReleaseTime, events->releaseFence,
+            events->hasReleaseInfo());
 
     return NO_ERROR;
 }
@@ -739,6 +762,29 @@
     return err;
 }
 
+void Surface::querySupportedTimestampsLocked() const {
+    // mMutex must be locked when calling this method.
+
+    if (mQueriedSupportedTimestamps) {
+        return;
+    }
+    mQueriedSupportedTimestamps = true;
+
+    std::vector<FrameEvent> supportedFrameTimestamps;
+    status_t err = composerService()->getSupportedFrameTimestamps(
+            &supportedFrameTimestamps);
+
+    if (err != NO_ERROR) {
+        return;
+    }
+
+    for (auto sft : supportedFrameTimestamps) {
+        if (sft == FrameEvent::DISPLAY_PRESENT) {
+            mFrameTimestampsSupportsPresent = true;
+        }
+    }
+}
+
 int Surface::query(int what, int* value) const {
     ATRACE_CALL();
     ALOGV("Surface::query");
@@ -800,6 +846,11 @@
                         static_cast<int>(durationUs);
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT: {
+                querySupportedTimestampsLocked();
+                *value = mFrameTimestampsSupportsPresent ? 1 : 0;
+                return NO_ERROR;
+            }
             case NATIVE_WINDOW_IS_VALID: {
                 *value = mGraphicBufferProducer != nullptr ? 1 : 0;
                 return NO_ERROR;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 56c7586..8c83843 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@
             uint32_t w, uint32_t h);
     status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
             int32_t z);
+    status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+            const sp<IBinder>& relativeTo, int32_t z);
     status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
             uint32_t flags, uint32_t mask);
     status_t setTransparentRegionHint(
@@ -343,6 +345,20 @@
     return NO_ERROR;
 }
 
+status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
+        const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+        int32_t z) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+    s->what |= layer_state_t::eRelativeLayerChanged;
+    s->relativeLayerHandle = relativeTo;
+    s->z = z;
+    return NO_ERROR;
+}
+
 status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
         const sp<IBinder>& id, uint32_t flags,
         uint32_t mask) {
@@ -760,6 +776,11 @@
     return getComposer().setLayer(this, id, z);
 }
 
+status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
+        const sp<IBinder>& relativeTo, int32_t z) {
+    return getComposer().setRelativeLayer(this, id, relativeTo, z);
+}
+
 status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
     return getComposer().setFlags(this, id,
             layer_state_t::eLayerHidden,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7a68f11..bf8a815 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@
     if (err < 0) return err;
     return mClient->setLayerStack(mHandle, layerStack);
 }
+
 status_t SurfaceControl::setLayer(int32_t layer) {
     status_t err = validate();
     if (err < 0) return err;
     return mClient->setLayer(mHandle, layer);
 }
+
+status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->setRelativeLayer(mHandle, relativeTo, layer);
+}
+
 status_t SurfaceControl::setPosition(float x, float y) {
     status_t err = validate();
     if (err < 0) return err;
diff --git a/libs/gui/include/private/gui/BitTube.h b/libs/gui/include/private/gui/BitTube.h
new file mode 100644
index 0000000..13c0162
--- /dev/null
+++ b/libs/gui/include/private/gui/BitTube.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/Parcelable.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Parcel;
+
+namespace gui {
+
+class BitTube : public Parcelable {
+public:
+    // creates an uninitialized BitTube (to unparcel into)
+    BitTube() = default;
+
+    // creates a BitTube with a a specified send and receive buffer size
+    explicit BitTube(size_t bufsize);
+
+    // creates a BitTube with a default (4KB) send buffer
+    struct DefaultSizeType {};
+    static constexpr DefaultSizeType DefaultSize{};
+    explicit BitTube(DefaultSizeType);
+
+    explicit BitTube(const Parcel& data);
+
+    virtual ~BitTube() = default;
+
+    // check state after construction
+    status_t initCheck() const;
+
+    // get receive file-descriptor
+    int getFd() const;
+
+    // get the send file-descriptor.
+    int getSendFd() const;
+
+    // moves the receive file descriptor out of this BitTube
+    base::unique_fd moveReceiveFd();
+
+    // resets this BitTube's receive file descriptor to receiveFd
+    void setReceiveFd(base::unique_fd&& receiveFd);
+
+    // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
+    template <typename T>
+    static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {
+        return sendObjects(tube, events, count, sizeof(T));
+    }
+
+    // receive objects (sized blobs). If the receiving buffer isn't large enough, excess messages
+    // are silently discarded.
+    template <typename T>
+    static ssize_t recvObjects(BitTube* tube, T* events, size_t count) {
+        return recvObjects(tube, events, count, sizeof(T));
+    }
+
+    // implement the Parcelable protocol. Only parcels the receive file descriptor
+    status_t writeToParcel(Parcel* reply) const;
+    status_t readFromParcel(const Parcel* parcel);
+
+private:
+    void init(size_t rcvbuf, size_t sndbuf);
+
+    // send a message. The write is guaranteed to send the whole message or fail.
+    ssize_t write(void const* vaddr, size_t size);
+
+    // receive a message. the passed buffer must be at least as large as the write call used to send
+    // the message, excess data is silently discarded.
+    ssize_t read(void* vaddr, size_t size);
+
+    base::unique_fd mSendFd;
+    mutable base::unique_fd mReceiveFd;
+
+    static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize);
+
+    static ssize_t recvObjects(BitTube* tube, void* events, size_t count, size_t objSize);
+};
+
+} // namespace gui
+} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce11486..cf3d1b2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -368,6 +368,10 @@
 public:
     ~FakeSurfaceComposer() override {}
 
+    void setSupportsPresent(bool supportsPresent) {
+        mSupportsPresent = supportsPresent;
+    }
+
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
     sp<ISurfaceComposerClient> createScopedConnection(
             const sp<IGraphicBufferProducer>& /* parent */) override {
@@ -391,6 +395,26 @@
             const sp<IGraphicBufferProducer>& /*surface*/) const override {
         return false;
     }
+
+    status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
+            const override {
+        *outSupported = {
+                FrameEvent::REQUESTED_PRESENT,
+                FrameEvent::ACQUIRE,
+                FrameEvent::LATCH,
+                FrameEvent::FIRST_REFRESH_START,
+                FrameEvent::LAST_REFRESH_START,
+                FrameEvent::GPU_COMPOSITION_DONE,
+                FrameEvent::DEQUEUE_READY,
+                FrameEvent::RELEASE
+        };
+        if (mSupportsPresent) {
+            outSupported->push_back(
+                        FrameEvent::DISPLAY_PRESENT);
+        }
+        return NO_ERROR;
+    }
+
     void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
     status_t getDisplayConfigs(const sp<IBinder>& /*display*/,
             Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
@@ -435,7 +459,6 @@
 
 private:
     bool mSupportsPresent{true};
-    bool mSupportsRetire{true};
 };
 
 class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
@@ -864,6 +887,28 @@
     EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
 }
 
+TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
+    bool displayPresentSupported = true;
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+    // Verify supported bits are forwarded.
+    int supportsPresent = -1;
+    mWindow.get()->query(mWindow.get(),
+            NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+    EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
+    bool displayPresentSupported = false;
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+    // Verify supported bits are forwarded.
+    int supportsPresent = -1;
+    mWindow.get()->query(mWindow.get(),
+            NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+    EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
 TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
     nsecs_t phase = 4000;
     nsecs_t interval = 1000;
@@ -1139,8 +1184,8 @@
     EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
             outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 }
 
 // This test verifies the acquire fence recorded by the consumer is not sent
@@ -1163,7 +1208,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[0].signalQueueFences();
@@ -1192,7 +1237,7 @@
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
-    EXPECT_EQ(0, outAcquireTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
 
     // Signal acquire fences. Verify a sync call still isn't necessary.
     mFrames[1].signalQueueFences();
@@ -1228,8 +1273,8 @@
     // Verify a request for no timestamps doesn't result in a sync call.
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
     int result = native_window_get_frame_timestamps(mWindow.get(), fId2,
-            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-            nullptr, nullptr, nullptr);
+            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+            nullptr, nullptr);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
 }
@@ -1265,10 +1310,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Verify available timestamps are correct for frame 1 again, before any
     // fence has been signaled.
@@ -1283,10 +1328,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1342,10 +1387,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     // Signal the fences for frame 1.
     mFrames[0].signalRefreshFences();
@@ -1363,7 +1408,7 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
     EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1371,7 +1416,7 @@
 
 // This test verifies that if the certain timestamps can't possibly exist for
 // the most recent frame, then a sync call is not done.
-TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
+TEST_F(GetFrameTimestampsTest, NoReleaseNoSync) {
     enableFrameTimestamps();
 
     // Dequeue and queue frame 1.
@@ -1401,10 +1446,10 @@
     EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
-    EXPECT_EQ(0, outDisplayPresentTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
     EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
 
     mFrames[0].signalRefreshFences();
     mFrames[0].signalReleaseFences();
@@ -1425,10 +1470,33 @@
     EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
     EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
-    EXPECT_EQ(0, outGpuCompositionDoneTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
     EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
-    EXPECT_EQ(0, outDequeueReadyTime);
-    EXPECT_EQ(0, outReleaseTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+    EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
+}
+
+// This test verifies there are no sync calls for present times
+// when they aren't supported and that an error is returned.
+
+TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
+    enableFrameTimestamps();
+    mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+
+    // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
+    dequeueAndQueue(0);
+
+    // Verify a query for the Present times do not trigger a sync call if they
+    // are not supported.
+    resetTimestamps();
+    int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+    int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
+            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+            &outDisplayPresentTime, nullptr, nullptr);
+    EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(BAD_VALUE, result);
+    EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
 }
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 438d3f5..5d7f660 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,6 +14,7 @@
 
 cc_library_shared {
     name: "libhwc2on1adapter",
+    vendor_available: true,
 
     clang: true,
     cppflags: [
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index e35bfc9..8c6ef69 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2246,6 +2246,11 @@
             mHwc1SupportsBackgroundColor = true;
         }
     }
+
+    // Some devices might have HWC1 retire fences that accurately emulate
+    // HWC2 present fences when they are deferred, but it's not very reliable.
+    // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+    mCapabilities.insert(Capability::PresentFenceIsNotReliable);
 }
 
 HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 90fb4b6..6c8221d 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -21,7 +21,7 @@
 }
 
 ndk_library {
-    name: "libnativewindow.ndk",
+    name: "libnativewindow",
     symbol_file: "libnativewindow.map.txt",
 
     // Android O
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 63d1ad1..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -186,6 +186,12 @@
      * if it is safe (i.e. no crash will occur) to call any method on it.
      */
     NATIVE_WINDOW_IS_VALID = 17,
+
+    /*
+     * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display
+     * present info, 0 if it won't.
+     */
+    NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
 };
 
 /* Valid operations for the (*perform)() hook.
@@ -305,6 +311,14 @@
  */
 static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
 
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
 struct ANativeWindow
 {
 #ifdef __cplusplus
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index f41f187..74186df 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -40,6 +40,7 @@
     ENABLE_DATA_INJECTION,
     GET_DYNAMIC_SENSOR_LIST,
     CREATE_SENSOR_DIRECT_CONNECTION,
+    SET_OPERATION_PARAMETER,
 };
 
 class BpSensorServer : public BpInterface<ISensorServer>
@@ -117,6 +118,23 @@
         remote()->transact(CREATE_SENSOR_DIRECT_CONNECTION, data, &reply);
         return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
     }
+
+    virtual int setOperationParameter(
+            int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+        data.writeInt32(type);
+        data.writeUint32(static_cast<uint32_t>(floats.size()));
+        for (auto i : floats) {
+            data.writeFloat(i);
+        }
+        data.writeUint32(static_cast<uint32_t>(ints.size()));
+        for (auto i : ints) {
+            data.writeInt32(i);
+        }
+        remote()->transact(SET_OPERATION_PARAMETER, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -183,6 +201,26 @@
             reply->writeStrongBinder(IInterface::asBinder(ch));
             return NO_ERROR;
         }
+        case SET_OPERATION_PARAMETER: {
+            CHECK_INTERFACE(ISensorServer, data, reply);
+            int32_t type;
+            Vector<float> floats;
+            Vector<int32_t> ints;
+
+            type = data.readInt32();
+            floats.resize(data.readUint32());
+            for (auto &i : floats) {
+                i = data.readFloat();
+            }
+            ints.resize(data.readUint32());
+            for (auto &i : ints) {
+                i = data.readInt32();
+            }
+
+            int32_t ret = setOperationParameter(type, floats, ints);
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index d6d3304..3fbc5eb 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -304,5 +304,14 @@
     return ret;
 }
 
+int SensorManager::setOperationParameter(
+        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);
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index f922307..8d50062 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -50,6 +50,9 @@
 
     virtual sp<ISensorEventConnection> createSensorDirectConnection(const String16& opPackageName,
             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;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 92c9823..5fc85d3 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -64,6 +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);
 
 private:
     // DeathRecipient interface
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 80fb064..ba37391 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -45,13 +45,13 @@
 
     srcs: [
         "ColorSpace.cpp",
+        "DebugUtils.cpp",
         "Fence.cpp",
         "FenceTime.cpp",
         "FrameStats.cpp",
         "Gralloc1.cpp",
         "Gralloc1On0Adapter.cpp",
-        "GrallocAllocator.cpp",
-        "GrallocMapper.cpp",
+        "Gralloc2.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
@@ -66,6 +66,9 @@
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.configstore@1.0",
+	"android.hardware.configstore-utils",
+        "libbase",
         "libnativeloader",
         "libcutils",
         "libhardware",
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
new file mode 100644
index 0000000..882bd7c
--- /dev/null
+++ b/libs/ui/DebugUtils.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/DebugUtils.h>
+
+#include <android-base/stringprintf.h>
+#include <string>
+
+std::string decodeStandard(android_dataspace dataspace) {
+    const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
+    switch (dataspaceSelect) {
+        case HAL_DATASPACE_STANDARD_BT709:
+            return std::string("BT709");
+
+        case HAL_DATASPACE_STANDARD_BT601_625:
+            return std::string("BT601_625");
+
+        case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+            return std::string("BT601_625_UNADJUSTED");
+
+        case HAL_DATASPACE_STANDARD_BT601_525:
+            return std::string("BT601_525");
+
+        case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+            return std::string("BT601_525_UNADJUSTED");
+
+        case HAL_DATASPACE_STANDARD_BT2020:
+            return std::string("BT2020");
+
+        case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+            return std::string("BT2020 (constant luminance)");
+
+        case HAL_DATASPACE_STANDARD_BT470M:
+            return std::string("BT470M");
+
+        case HAL_DATASPACE_STANDARD_FILM:
+            return std::string("FILM");
+
+        case HAL_DATASPACE_STANDARD_DCI_P3:
+            return std::string("DCI-P3");
+
+        case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+            return std::string("AdobeRGB");
+
+        case 0:
+            switch (dataspace & 0xffff) {
+                case HAL_DATASPACE_JFIF:
+                    return std::string("(deprecated) JFIF (BT601_625, SMPTE_170M Full range)");
+
+                case HAL_DATASPACE_BT601_625:
+                    return std::string("(deprecated) BT601_625 (BT601_625, SMPTE_170M Limited "
+                                       "range)");
+
+                case HAL_DATASPACE_BT601_525:
+                    return std::string("(deprecated) BT601_525 (BT601_525, SMPTE_170M Limited "
+                                       "range)");
+
+                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)");
+
+                case HAL_DATASPACE_ARBITRARY:
+                    return std::string("ARBITRARY");
+
+                case HAL_DATASPACE_UNKNOWN:
+                // Fallthrough
+                default:
+                    return android::base::StringPrintf("Unknown deprecated dataspace code %d",
+                                                       dataspaceSelect);
+            }
+    }
+
+    return android::base::StringPrintf("Unknown dataspace code %d", dataspaceSelect);
+}
+
+std::string decodeTransfer(android_dataspace dataspace) {
+    const uint32_t dataspaceTransfer = (dataspace & HAL_DATASPACE_TRANSFER_MASK);
+    switch (dataspaceTransfer) {
+        case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
+            return std::string("Unspecified");
+
+        case HAL_DATASPACE_TRANSFER_LINEAR:
+            return std::string("Linear");
+
+        case HAL_DATASPACE_TRANSFER_SRGB:
+            return std::string("sRGB");
+
+        case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+            return std::string("SMPTE_170M");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+            return std::string("gamma 2.2");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_6:
+            return std::string("gamma 2.6");
+
+        case HAL_DATASPACE_TRANSFER_GAMMA2_8:
+            return std::string("gamma 2.8");
+
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            return std::string("SMPTE 2084");
+
+        case HAL_DATASPACE_TRANSFER_HLG:
+            return std::string("STD-B67");
+    }
+
+    return android::base::StringPrintf("Unknown dataspace transfer %d", dataspaceTransfer);
+}
+
+std::string decodeRange(android_dataspace dataspace) {
+    const uint32_t dataspaceRange = (dataspace & HAL_DATASPACE_RANGE_MASK);
+    switch (dataspaceRange) {
+        case HAL_DATASPACE_RANGE_UNSPECIFIED:
+            return std::string("Range Unspecified");
+
+        case HAL_DATASPACE_RANGE_FULL:
+            return std::string("Full range");
+
+        case HAL_DATASPACE_RANGE_LIMITED:
+            return std::string("Limited range");
+
+        case HAL_DATASPACE_RANGE_EXTENDED:
+            return std::string("Extended range");
+    }
+
+    return android::base::StringPrintf("Unknown dataspace range %d", dataspaceRange);
+}
+
+std::string dataspaceDetails(android_dataspace dataspace) {
+    return android::base::StringPrintf("%s %s %s", decodeStandard(dataspace).c_str(),
+                                       decodeTransfer(dataspace).c_str(),
+                                       decodeRange(dataspace).c_str());
+}
+
+std::string decodeColorMode(android_color_mode colorMode) {
+    switch (colorMode) {
+        case HAL_COLOR_MODE_NATIVE:
+            return std::string("HAL_COLOR_MODE_NATIVE");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_625:
+            return std::string("HAL_COLOR_MODE_BT601_625");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
+            return std::string("HAL_COLOR_MODE_BT601_625_UNADJUSTED");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_525:
+            return std::string("HAL_COLOR_MODE_BT601_525");
+
+        case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
+            return std::string("HAL_COLOR_MODE_BT601_525_UNADJUSTED");
+
+        case HAL_COLOR_MODE_STANDARD_BT709:
+            return std::string("HAL_COLOR_MODE_BT709");
+
+        case HAL_COLOR_MODE_DCI_P3:
+            return std::string("HAL_COLOR_MODE_DCI_P3");
+
+        case HAL_COLOR_MODE_SRGB:
+            return std::string("HAL_COLOR_MODE_SRGB");
+
+        case HAL_COLOR_MODE_ADOBE_RGB:
+            return std::string("HAL_COLOR_MODE_ADOBE_RGB");
+
+        case HAL_COLOR_MODE_DISPLAY_P3:
+            return std::string("HAL_COLOR_MODE_DISPLAY_P3");
+    }
+
+    return android::base::StringPrintf("Unknown color mode %d", colorMode);
+}
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index bd7c6a1..9ee9838 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -20,6 +20,9 @@
 
 #include <ui/Gralloc1On0Adapter.h>
 
+#include <algorithm>
+#include <array>
+
 #include <grallocusage/GrallocUsageConversion.h>
 
 #include <hardware/gralloc.h>
@@ -67,13 +70,18 @@
 void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
         int32_t* outCapabilities)
 {
+    constexpr std::array<int32_t, 2> supportedCapabilities = {{
+        GRALLOC1_CAPABILITY_ON_ADAPTER,
+        GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE,
+    }};
+
     if (outCapabilities == nullptr) {
-        *outCount = 1;
-        return;
-    }
-    if (*outCount >= 1) {
-        *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
-        *outCount = 1;
+        *outCount = supportedCapabilities.size();
+    } else {
+        *outCount = std::min(*outCount, static_cast<uint32_t>(
+                    supportedCapabilities.size()));
+        std::copy_n(supportedCapabilities.begin(),
+                *outCount, outCapabilities);
     }
 }
 
@@ -325,6 +333,9 @@
         if (result != 0) {
             ALOGE("gralloc0 unregister failed: %d", result);
         }
+
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle_t*>(handle));
     }
 
     mBuffers.erase(handle);
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
new file mode 100644
index 0000000..75f5686
--- /dev/null
+++ b/libs/ui/Gralloc2.cpp
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Gralloc2"
+
+#include <ui/Gralloc2.h>
+
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+namespace android {
+
+namespace Gralloc2 {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+Mapper::Mapper()
+{
+    mMapper = IMapper::getService();
+    if (mMapper != nullptr && mMapper->isRemote()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+    }
+}
+
+Error Mapper::createDescriptor(
+        const IMapper::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor* outDescriptor) const
+{
+    Error error;
+    auto ret = mMapper->createDescriptor(descriptorInfo,
+            [&](const auto& tmpError, const auto& tmpDescriptor)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outDescriptor = tmpDescriptor;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+        buffer_handle_t* outBufferHandle) const
+{
+    Error error;
+    auto ret = mMapper->importBuffer(rawHandle,
+            [&](const auto& tmpError, const auto& tmpBuffer)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->freeBuffer(buffer);
+
+    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+    ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
+            buffer, error);
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, void** outData) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpData)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outData = tmpData;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, YCbCrLayout* outLayout) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
+            acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outLayout = tmpLayout;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+int Mapper::unlock(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    Error error;
+    auto ret = mMapper->unlock(buffer,
+            [&](const auto& tmpError, const auto& tmpReleaseFence)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle && fenceHandle->numFds == 1) {
+                    int fd = dup(fenceHandle->data[0]);
+                    if (fd >= 0) {
+                        releaseFence = fd;
+                    } else {
+                        ALOGD("failed to dup unlock release fence");
+                        sync_wait(fenceHandle->data[0], -1);
+                    }
+                }
+            });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", buffer, error);
+    }
+
+    return releaseFence;
+}
+
+Allocator::Allocator(const Mapper& mapper)
+    : mMapper(mapper)
+{
+    if (mMapper.valid()) {
+        mAllocator = IAllocator::getService();
+    }
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+    std::string debugInfo;
+
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
+        debugInfo = tmpDebugInfo.c_str();
+    });
+
+    return debugInfo;
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
+        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+{
+    Error error;
+    auto ret = mAllocator->allocate(descriptor, count,
+            [&](const auto& tmpError, const auto& tmpStride,
+                const auto& tmpBuffers) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                // import buffers
+                for (uint32_t i = 0; i < count; i++) {
+                    error = mMapper.importBuffer(tmpBuffers[i],
+                            &outBufferHandles[i]);
+                    if (error != Error::NONE) {
+                        for (uint32_t j = 0; j < i; j++) {
+                            mMapper.freeBuffer(outBufferHandles[j]);
+                            outBufferHandles[j] = nullptr;
+                        }
+                        return;
+                    }
+                }
+
+                *outStride = tmpStride;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
deleted file mode 100644
index 7af55e7..0000000
--- a/libs/ui/GrallocAllocator.cpp
+++ /dev/null
@@ -1,127 +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.
- */
-
-#define LOG_TAG "GrallocAllocator"
-
-#include <ui/GrallocAllocator.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Allocator::Allocator()
-{
-    mAllocator = IAllocator::getService();
-    if (mAllocator != nullptr) {
-        mAllocator->createClient(
-                [&](const auto& tmpError, const auto& tmpClient) {
-                    if (tmpError == Error::NONE) {
-                        mClient = tmpClient;
-                    }
-                });
-        if (mClient == nullptr) {
-            mAllocator.clear();
-        }
-    }
-}
-
-std::string Allocator::dumpDebugInfo() const
-{
-    std::string info;
-
-    mAllocator->dumpDebugInfo([&](const auto& tmpInfo) {
-        info = tmpInfo.c_str();
-    });
-
-    return info;
-}
-
-Error Allocator::createBufferDescriptor(
-        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor) const
-{
-    Error error = kDefaultError;
-    mClient->createDescriptor(descriptorInfo,
-            [&](const auto& tmpError, const auto& tmpDescriptor) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outDescriptor = tmpDescriptor;
-            });
-
-    return error;
-}
-
-void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
-{
-    mClient->destroyDescriptor(descriptor);
-}
-
-Error Allocator::allocate(BufferDescriptor descriptor,
-        Buffer* outBuffer) const
-{
-    hardware::hidl_vec<BufferDescriptor> descriptors;
-    descriptors.setToExternal(&descriptor, 1);
-
-    Error error = kDefaultError;
-    auto status = mClient->allocate(descriptors,
-            [&](const auto& tmpError, const auto& tmpBuffers) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBuffer = tmpBuffers[0];
-            });
-
-    return error;
-}
-
-void Allocator::free(Buffer buffer) const
-{
-    mClient->free(buffer);
-}
-
-Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
-        native_handle_t** outBufferHandle) const
-{
-    Error error = kDefaultError;
-    auto status = mClient->exportHandle(descriptor, buffer,
-            [&](const auto& tmpError, const auto& tmpBufferHandle) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBufferHandle = native_handle_clone(tmpBufferHandle);
-                if (!*outBufferHandle) {
-                    error = Error::NO_RESOURCES;
-                }
-            });
-
-    return error;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
deleted file mode 100644
index 8095247..0000000
--- a/libs/ui/GrallocMapper.cpp
+++ /dev/null
@@ -1,284 +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.
- */
-
-#define LOG_TAG "GrallocMapper"
-
-#include <ui/GrallocMapper.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-static constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Mapper::Mapper()
-{
-    mMapper = IMapper::getService();
-    if (mMapper != nullptr && mMapper->isRemote()) {
-        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
-    }
-}
-
-Error Mapper::retain(buffer_handle_t handle) const
-{
-    auto ret = mMapper->retain(handle);
-    return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-}
-
-void Mapper::release(buffer_handle_t handle) const
-{
-    auto ret = mMapper->release(handle);
-
-    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-    ALOGE_IF(error != Error::NONE,
-            "release(%p) failed with %d", handle, error);
-}
-
-Error Mapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    Error error = kDefaultError;
-    mMapper->getDimensions(handle,
-            [&](const auto& tmpError, const auto& tmpWidth,
-                    const auto& tmpHeight)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outWidth = tmpWidth;
-                *outHeight = tmpHeight;
-            });
-
-    return error;
-}
-
-Error Mapper::getFormat(buffer_handle_t handle, int32_t* outFormat) const
-{
-    Error error = kDefaultError;
-    mMapper->getFormat(handle,
-            [&](const auto& tmpError, const auto& tmpFormat)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outFormat = static_cast<int32_t>(tmpFormat);
-            });
-
-    return error;
-}
-
-Error Mapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    Error error = kDefaultError;
-    mMapper->getLayerCount(handle,
-            [&](const auto& tmpError, const auto& tmpLayerCount)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayerCount = tmpLayerCount;
-            });
-
-    return error;
-}
-
-Error Mapper::getProducerUsage(buffer_handle_t handle,
-    uint64_t* outProducerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getProducerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpProducerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outProducerUsage = tmpProducerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getConsumerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpConsumerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outConsumerUsage = tmpConsumerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    Error error = kDefaultError;
-    mMapper->getBackingStore(handle,
-            [&](const auto& tmpError, const auto& tmpStore)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outBackingStore = tmpStore;
-            });
-
-    return error;
-}
-
-Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
-{
-    Error error = kDefaultError;
-    mMapper->getStride(handle,
-            [&](const auto& tmpError, const auto& tmpStride)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outStride = tmpStride;
-            });
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, void** outData) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lock(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpData)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outData = tmpData;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, FlexLayout* outLayout) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lockFlex(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpLayout)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayout = tmpLayout;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-int Mapper::unlock(buffer_handle_t handle) const
-{
-    int releaseFence = -1;
-
-    Error error = kDefaultError;
-    mMapper->unlock(handle,
-            [&](const auto& tmpError, const auto& tmpReleaseFence)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                auto fenceHandle = tmpReleaseFence.getNativeHandle();
-                if (fenceHandle && fenceHandle->numFds == 1) {
-                    int fd = dup(fenceHandle->data[0]);
-                    if (fd >= 0) {
-                        releaseFence = fd;
-                    } else {
-                        error = Error::NO_RESOURCES;
-                    }
-                } else {
-                    releaseFence = -1;
-                }
-            });
-
-    if (error != Error::NONE) {
-        ALOGE("unlock(%p) failed with %d", handle, error);
-        releaseFence = -1;
-    }
-
-    return releaseFence;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index d21758d..eb5c7b6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,7 @@
 
 #include <grallocusage/GrallocUsageConversion.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
 
@@ -104,11 +104,7 @@
 void GraphicBuffer::free_handle()
 {
     if (mOwner == ownHandle) {
-        mBufferMapper.unregisterBuffer(handle);
-        if (!mBufferMapper.getGrallocMapper().valid()) {
-            native_handle_close(handle);
-            native_handle_delete(const_cast<native_handle*>(handle));
-        }
+        mBufferMapper.freeBuffer(handle);
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
@@ -217,7 +213,7 @@
     mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
 
     if (method == TAKE_UNREGISTERED_HANDLE) {
-        status_t err = mBufferMapper.registerBuffer(this);
+        status_t err = mBufferMapper.importBuffer(this);
         if (err != NO_ERROR) {
             // clean up cloned handle
             if (clone) {
@@ -451,7 +447,7 @@
     mOwner = ownHandle;
 
     if (handle != 0) {
-        status_t err = mBufferMapper.registerBuffer(this);
+        status_t err = mBufferMapper.importBuffer(this);
         if (err != NO_ERROR) {
             width = height = stride = format = layerCount = usage = 0;
             handle = NULL;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 3f18bbc..1f6c537 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -22,13 +22,14 @@
 
 #include <stdio.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 #include <log/log.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocAllocator.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferMapper.h>
 
 namespace android {
@@ -41,8 +42,9 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-  : mAllocator(std::make_unique<Gralloc2::Allocator>()),
-    mMapper(GraphicBufferMapper::getInstance())
+  : mMapper(GraphicBufferMapper::getInstance()),
+    mAllocator(std::make_unique<Gralloc2::Allocator>(
+                mMapper.getGrallocMapper()))
 {
     if (!mAllocator->valid()) {
         mLoader = std::make_unique<Gralloc1::Loader>();
@@ -102,109 +104,6 @@
     ALOGD("%s", s.string());
 }
 
-namespace {
-
-class HalBuffer {
-public:
-    HalBuffer(const Gralloc2::Allocator* allocator,
-            uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-            uint64_t consumerUsage)
-        : mAllocator(allocator), mBufferValid(false)
-    {
-        Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
-        info.width = width;
-        info.height = height;
-        info.format = static_cast<Gralloc2::PixelFormat>(format);
-        info.layerCount = layerCount;
-        info.producerUsageMask = producerUsage;
-        info.consumerUsageMask = consumerUsage;
-
-        Gralloc2::BufferDescriptor descriptor;
-        auto error = mAllocator->createBufferDescriptor(info, &descriptor);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            return;
-        }
-
-        error = mAllocator->allocate(descriptor, &mBuffer);
-        if (error == Gralloc2::Error::NOT_SHARED) {
-            error = Gralloc2::Error::NONE;
-        }
-
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to export handle");
-            mAllocator->free(mBuffer);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        mAllocator->destroyBufferDescriptor(descriptor);
-
-        mBufferValid = true;
-    }
-
-    ~HalBuffer()
-    {
-        if (mBufferValid) {
-            if (mHandle) {
-                native_handle_close(mHandle);
-                native_handle_delete(mHandle);
-            }
-
-            mAllocator->free(mBuffer);
-        }
-    }
-
-    bool exportHandle(GraphicBufferMapper& mapper,
-            buffer_handle_t* handle, uint32_t* stride)
-    {
-        if (!mBufferValid) {
-            return false;
-        }
-
-        if (mapper.registerBuffer(mHandle)) {
-            return false;
-        }
-
-        *handle = mHandle;
-
-        auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGW("Failed to get stride from buffer: %d", error);
-            *stride = 0;
-        }
-
-        mHandle = nullptr;
-        mAllocator->free(mBuffer);
-        mBufferValid = false;
-
-        return true;
-    }
-
-private:
-    const Gralloc2::Allocator* mAllocator;
-
-    bool mBufferValid;
-    Gralloc2::Buffer mBuffer;
-    native_handle_t* mHandle;
-};
-
-} // namespace
-
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
         PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
         uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
@@ -223,12 +122,18 @@
 
     gralloc1_error_t error;
     if (mAllocator->valid()) {
-        HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
-                producerUsage, consumerUsage);
-        if (!buffer.exportHandle(mMapper, handle, stride)) {
+        Gralloc2::IMapper::BufferDescriptorInfo info = {};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = static_cast<Gralloc2::PixelFormat>(format);
+        info.usage = static_cast<uint64_t>(android_convertGralloc1To0Usage(
+                producerUsage, consumerUsage));
+        error = static_cast<gralloc1_error_t>(mAllocator->allocate(info,
+                    stride, handle));
+        if (error != GRALLOC1_ERROR_NONE) {
             return NO_MEMORY;
         }
-        error = GRALLOC1_ERROR_NONE;
     } else {
         auto descriptor = mDevice->createDescriptor();
         error = descriptor->setDimensions(width, height);
@@ -310,8 +215,7 @@
 
     gralloc1_error_t error;
     if (mAllocator->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper.unregisterBuffer(handle));
+        error = static_cast<gralloc1_error_t>(mMapper.freeBuffer(handle));
     } else {
         error = mDevice->release(handle);
     }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 656472f..87519bf 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
 
 #include <ui/GraphicBufferMapper.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 // We would eliminate the non-conforming zero-length array, but we can't since
 // this is effectively included from the Linux kernel
 #pragma clang diagnostic push
@@ -30,7 +32,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBuffer.h>
 
 #include <system/graphics.h>
@@ -49,63 +51,84 @@
     }
 }
 
-
-
-status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+        buffer_handle_t* outHandle)
 {
     ATRACE_CALL();
 
+    Gralloc2::Error error;
+    if (mMapper->valid()) {
+        error = mMapper->importBuffer(hardware::hidl_handle(rawHandle),
+                outHandle);
+    } else {
+        error = Gralloc2::Error::UNSUPPORTED;
+    }
+
+    ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
+            rawHandle, error);
+
+    return static_cast<status_t>(error);
+}
+
+status_t GraphicBufferMapper::importBuffer(const GraphicBuffer* buffer)
+{
+    ATRACE_CALL();
+
+    ANativeWindowBuffer* nativeBuffer = buffer->getNativeBuffer();
+    buffer_handle_t rawHandle = nativeBuffer->handle;
+
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+        buffer_handle_t importedHandle;
+        error = static_cast<gralloc1_error_t>(mMapper->importBuffer(
+                    hardware::hidl_handle(rawHandle), &importedHandle));
+        if (error == GRALLOC1_ERROR_NONE) {
+            nativeBuffer->handle = importedHandle;
+        }
     } else {
-        // This always returns GRALLOC1_BAD_HANDLE when handle is from a
-        // remote process and mDevice is backed by Gralloc1On0Adapter.
-        error = mDevice->retain(handle);
-        if (error == GRALLOC1_ERROR_BAD_HANDLE &&
-                mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-            ALOGE("registerBuffer by handle is not supported with "
-                  "Gralloc1On0Adapter");
+        native_handle_t* clonedHandle = native_handle_clone(rawHandle);
+        if (clonedHandle) {
+            nativeBuffer->handle = clonedHandle;
+            error = mDevice->retain(buffer);
+            if (error != GRALLOC1_ERROR_NONE) {
+                nativeBuffer->handle = rawHandle;
+                native_handle_close(clonedHandle);
+                native_handle_delete(clonedHandle);
+            }
+        } else {
+            error = GRALLOC1_ERROR_NO_RESOURCES;
         }
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper->retain(buffer->getNativeBuffer()->handle));
-    } else {
-        error = mDevice->retain(buffer);
+    // the raw handle is owned by GraphicBuffer and is now replaced
+    if (error == GRALLOC1_ERROR_NONE) {
+        native_handle_close(rawHandle);
+        native_handle_delete(const_cast<native_handle_t*>(rawHandle));
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            buffer->getNativeBuffer()->handle, error);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "importBuffer(%p) failed: %d",
+            rawHandle, error);
 
     return error;
 }
 
-status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
 {
     ATRACE_CALL();
 
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        mMapper->release(handle);
+        mMapper->freeBuffer(handle);
         error = GRALLOC1_ERROR_NONE;
     } else {
         error = mDevice->release(handle);
+        if (!mDevice->hasCapability(GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE)) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle_t*>(handle));
+        }
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "freeBuffer(%p): failed %d",
             handle, error);
 
     return error;
@@ -120,138 +143,13 @@
     return outRect;
 }
 
-
-status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getDimensions(handle, outWidth, outHeight);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getDimensions(handle, outWidth, outHeight);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
-        int32_t* outFormat) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getFormat(handle, outFormat);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getFormat(handle, outFormat);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getLayerCount(handle, outLayerCount);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getLayerCount(handle, outLayerCount);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
-        uint64_t* outProducerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getProducerUsage(handle, outProducerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getProducerUsage(handle, outProducerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getProducerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getConsumerUsage(handle, outConsumerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getConsumerUsage(handle, outConsumerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getConsumerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getBackingStore(handle, outBackingStore);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getBackingStore(handle, outBackingStore);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getBackingStore(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
-        uint32_t* outStride) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getStride(handle, outStride);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getStride(handle, outStride);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
-            handle, error);
-
-    return error;
+static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
+    Gralloc2::IMapper::Rect outRect{};
+    outRect.left = rect.left;
+    outRect.top = rect.top;
+    outRect.width = rect.width();
+    outRect.height = rect.height();
+    return outRect;
 }
 
 status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
@@ -289,15 +187,15 @@
 {
     ATRACE_CALL();
 
-    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, producerUsage, consumerUsage, accessRect,
-                    fenceFd, vaddr));
+        const uint64_t usage =
+            static_cast<uint64_t>(android_convertGralloc1To0Usage(
+                        producerUsage, consumerUsage));
+        error = static_cast<gralloc1_error_t>(mMapper->lock(handle,
+                usage, asGralloc2Rect(bounds), fenceFd, vaddr));
     } else {
+        gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
         sp<Fence> fence = new Fence(fenceFd);
         error = mDevice->lock(handle,
                 static_cast<gralloc1_producer_usage_t>(producerUsage),
@@ -346,22 +244,19 @@
     gralloc1_error_t error;
 
     if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        Gralloc2::FlexLayout layout{};
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, usage, usage, accessRect, fenceFd, &layout));
-
+        Gralloc2::YCbCrLayout layout;
+        error = static_cast<gralloc1_error_t>(mMapper->lock(handle, usage,
+                asGralloc2Rect(bounds), fenceFd, &layout));
         if (error == GRALLOC1_ERROR_NONE) {
-            planes.resize(layout.planes.size());
-            memcpy(planes.data(), layout.planes.data(),
-                    sizeof(planes[0]) * planes.size());
-
-            flexLayout.format = static_cast<android_flex_format_t>(
-                    layout.format);
-            flexLayout.num_planes = static_cast<uint32_t>(planes.size());
-            flexLayout.planes = planes.data();
+            ycbcr->y = layout.y;
+            ycbcr->cb = layout.cb;
+            ycbcr->cr = layout.cr;
+            ycbcr->ystride = static_cast<size_t>(layout.yStride);
+            ycbcr->cstride = static_cast<size_t>(layout.cStride);
+            ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
         }
+
+        return error;
     } else {
         sp<Fence> fence = new Fence(fenceFd);
 
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b55c212..6733505 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -25,9 +25,3 @@
     shared_libs: ["libui"],
     srcs: ["colorspace_test.cpp"],
 }
-
-cc_test {
-    name: "Gralloc1Mapper_test",
-    shared_libs: ["libui", "libutils"],
-    srcs: ["Gralloc1Mapper_test.cpp"],
-}
diff --git a/libs/ui/tests/Gralloc1Mapper_test.cpp b/libs/ui/tests/Gralloc1Mapper_test.cpp
deleted file mode 100644
index b7c9f0f..0000000
--- a/libs/ui/tests/Gralloc1Mapper_test.cpp
+++ /dev/null
@@ -1,105 +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.
- */
-
-#define LOG_TAG "Gralloc1Mapper_test"
-//#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <utils/Errors.h>
-
-#include <gtest/gtest.h>
-
-using namespace android;
-
-class Gralloc1MapperTest : public ::testing::Test
-{
-public:
-    ~Gralloc1MapperTest() override = default;
-
-protected:
-    void SetUp() override {
-        buffer = new GraphicBuffer(4, 8, HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
-                GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, "Gralloc1MapperTest");
-        ASSERT_NE(nullptr, buffer.get());
-
-        handle = static_cast<buffer_handle_t>(buffer->handle);
-
-        mapper = &GraphicBufferMapper::get();
-    }
-
-    sp<GraphicBuffer> buffer;
-    buffer_handle_t handle;
-    GraphicBufferMapper* mapper;
-};
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getDimensions) {
-    uint32_t width = 0;
-    uint32_t height = 0;
-    status_t err = mapper->getDimensions(handle, &width, &height);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(4U, width);
-    EXPECT_EQ(8U, height);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getFormat) {
-    int32_t value = 0;
-    status_t err = mapper->getFormat(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getLayerCount) {
-    uint32_t value = 0;
-    status_t err = mapper->getLayerCount(handle, &value);
-    if (err != GRALLOC1_ERROR_UNSUPPORTED) {
-        EXPECT_EQ(1U, value);
-    }
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getProducerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getProducerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getConsumerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getConsumerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getBackingStore) {
-    uint64_t value = 0;
-    status_t err = mapper->getBackingStore(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getStride) {
-    uint32_t value = 0;
-    status_t err = mapper->getStride(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    // The stride should be at least the width of the buffer.
-    EXPECT_LE(4U, value);
-}
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 2749fd1..a1f952e 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -20,6 +20,7 @@
 
 namespace {
 
+// TODO(hendrikw): These flags can not be hard coded.
 constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
                                         GRALLOC_USAGE_SW_WRITE_RARELY |
                                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -110,6 +111,7 @@
 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
   int width = static_cast<int>(size);
   int height = 1;
+  // TODO(hendrikw): These flags can not be hard coded.
   constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
                         GRALLOC_USAGE_SW_WRITE_RARELY |
                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -196,18 +198,27 @@
       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
 }
 
-BufferProducer::BufferProducer(int width, int height, int format, int usage,
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                               uint32_t usage, size_t metadata_size,
+                               size_t slice_count)
+    : BufferProducer(width, height, format, usage, usage, metadata_size,
+                     slice_count) {}
+
+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 slice_count)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
-           "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
-           "usage=%d, metadata_size=%zu, slice_count=%zu",
-           event_fd(), width, height, format, usage, metadata_size,
-           slice_count);
+           "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " metadata_size=%zu slice_count=%zu",
+           event_fd(), width, height, format, producer_usage, consumer_usage,
+           metadata_size, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, metadata_size, slice_count);
+      width, height, format, producer_usage, consumer_usage, metadata_size,
+      slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -226,21 +237,29 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int width, int height, int format,
-                               int usage, size_t meta_size_bytes,
+                               int group_id, uint32_t width, uint32_t height,
+                               uint32_t format, uint32_t usage,
+                               size_t meta_size_bytes, size_t slice_count)
+    : BufferProducer(name, user_id, group_id, width, height, format, usage,
+                     usage, meta_size_bytes, slice_count) {}
+
+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,
                                size_t slice_count)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
-           "group_id=%d width=%d height=%d format=%d usage=%d, "
-           "meta_size_bytes=%zu, slice_count=%zu",
+           "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
            event_fd(), name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,18 +279,25 @@
   }
 }
 
-BufferProducer::BufferProducer(int usage, size_t size)
+BufferProducer::BufferProducer(uint32_t usage, size_t size)
+    : BufferProducer(usage, usage, size) {}
+
+BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
+                               size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
-  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
-           size);
+  ALOGD_IF(TRACE,
+           "BufferProducer::BufferProducer: producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " size=%zu",
+           producer_usage, consumer_usage, size);
   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 slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, meta_size_bytes, slice_count);
+      width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+      slice_count);
   if (!status) {
     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
           status.GetErrorMessage().c_str());
@@ -289,21 +315,27 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int usage, size_t size)
+                               int group_id, uint32_t usage, size_t size)
+    : BufferProducer(name, user_id, group_id, usage, usage, size) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+                               int group_id, uint64_t producer_usage,
+                               uint64_t consumer_usage, size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
-           "usage=%d size=%zu",
-           name.c_str(), user_id, group_id, usage, size);
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
+           name.c_str(), user_id, group_id, producer_usage, consumer_usage,
+           size);
   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 slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create persistent "
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 aacc385..c772ed3 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -94,9 +94,12 @@
   }
 
   IonBuffer* buffer() { return &slices_[0]; }
+  const IonBuffer* buffer() const { return &slices_[0]; }
+
   // If index is greater than or equal to slice_count(), the result is
   // undefined.
   IonBuffer* slice(size_t index) { return &slices_[index]; }
+  const IonBuffer* slice(size_t index) const { return &slices_[index]; }
 
   int slice_count() const { return static_cast<int>(slices_.size()); }
   int id() const { return id_; }
@@ -104,11 +107,14 @@
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
-  int width() const { return slices_[0].width(); }
-  int height() const { return slices_[0].height(); }
-  int stride() const { return slices_[0].stride(); }
-  int format() const { return slices_[0].format(); }
-  int usage() const { return slices_[0].usage(); }
+  uint32_t width() const { return slices_[0].width(); }
+  uint32_t height() const { return slices_[0].height(); }
+  uint32_t stride() const { return slices_[0].stride(); }
+  uint32_t format() const { return slices_[0].format(); }
+  uint32_t usage() const { return slices_[0].usage(); }
+  uint32_t layer_count() const { return slices_[0].layer_count(); }
+  uint64_t producer_usage() const { return slices_[0].producer_usage(); }
+  uint64_t consumer_usage() const { return slices_[0].consumer_usage(); }
 
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -171,9 +177,8 @@
   int Post(const LocalHandle& ready_fence) {
     return Post(ready_fence, nullptr, 0);
   }
-  template <
-      typename Meta,
-      typename = typename std::enable_if<!std::is_void<Meta>::value>::type>
+  template <typename Meta, typename = typename std::enable_if<
+                               !std::is_void<Meta>::value>::type>
   int Post(const LocalHandle& ready_fence, const Meta& meta) {
     return Post(ready_fence, &meta, sizeof(meta));
   }
@@ -216,8 +221,12 @@
   // arguments as the constructors.
 
   // Constructs a buffer with the given geometry and parameters.
-  BufferProducer(int width, int height, int format, int usage,
-                 size_t metadata_size = 0, size_t slice_count = 1);
+  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                 uint32_t usage, size_t metadata_size = 0,
+                 size_t slice_count = 1);
+  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                 uint64_t producer_usage, uint64_t consumer_usage,
+                 size_t metadata_size, size_t slice_count);
 
   // Constructs a persistent buffer with the given geometry and parameters and
   // binds it to |name| in one shot. If a persistent buffer with the same name
@@ -231,16 +240,24 @@
   // created and cannot be changed. A user or group id of -1 disables checks for
   // that respective id. A user or group id of 0 is substituted with the
   // effective user or group id of the calling process.
-  BufferProducer(const std::string& name, int user_id, int group_id, int width,
-                 int height, int format, int usage, size_t metadata_size = 0,
+  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 metadata_size = 0,
                  size_t slice_count = 1);
+  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 metadata_size, size_t slice_count);
 
   // Constructs a blob (flat) buffer with the given usage flags.
-  BufferProducer(int usage, size_t size);
+  BufferProducer(uint32_t usage, size_t size);
+  BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a persistent blob (flat) buffer and binds it to |name|.
-  BufferProducer(const std::string& name, int user_id, int group_id, int usage,
-                 size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint32_t usage, size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a channel to persistent buffer by name only. The buffer must
   // have been previously created or made persistent.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ed11551..b6302f1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,7 +24,8 @@
         width_(buffer.width()),
         height_(buffer.height()),
         format_(buffer.format()),
-        usage_(buffer.usage()) {
+        producer_usage_(buffer.producer_usage()),
+        consumer_usage_(buffer.consumer_usage()) {
     // Populate the fd and int vectors: native_handle->data[] is an array of fds
     // followed by an array of opaque ints.
     const int fd_count = buffer.handle()->numFds;
@@ -37,6 +38,7 @@
     }
   }
   NativeBufferHandle(NativeBufferHandle&& other) = default;
+  NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
 
   // Imports the native handle into the given IonBuffer instance.
   int Import(IonBuffer* buffer) {
@@ -46,9 +48,10 @@
     for (const auto& fd : fds_)
       fd_ints.push_back(fd.Get());
 
-    const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
-                                   opaque_ints_.data(), opaque_ints_.size(),
-                                   width_, height_, stride_, format_, usage_);
+    const int ret =
+        buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+                       opaque_ints_.size(), width_, height_, stride_, format_,
+                       producer_usage_, consumer_usage_);
     if (ret < 0)
       return ret;
 
@@ -68,24 +71,32 @@
 
  private:
   int id_;
-  int stride_;
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
+  uint32_t stride_;
+  uint32_t width_;
+  uint32_t height_;
+  uint32_t format_;
+  uint64_t producer_usage_;
+  uint64_t consumer_usage_;
   std::vector<int> opaque_ints_;
   std::vector<FileHandleType> fds_;
 
-  void Clear() { id_ = stride_ = width_ = height_ = format_ = usage_ = -1; }
+  void Clear() {
+    id_ = -1;
+    stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
+        0;
+  }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, usage_, opaque_ints_,
-                           fds_);
+                           width_, height_, format_, producer_usage_,
+                           consumer_usage_, opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
 };
 
+using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
+using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
+
 template <typename FileHandleType>
 class FenceHandle {
  public:
@@ -119,6 +130,31 @@
 using LocalFence = FenceHandle<pdx::LocalHandle>;
 using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
 
+struct QueueInfo {
+  size_t meta_size_bytes;
+  int id;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
+};
+
+struct UsagePolicy {
+  uint64_t producer_set_mask;
+  uint64_t producer_clear_mask;
+  uint64_t producer_deny_set_mask;
+  uint64_t producer_deny_clear_mask;
+  uint64_t consumer_set_mask;
+  uint64_t consumer_clear_mask;
+  uint64_t consumer_deny_set_mask;
+  uint64_t consumer_deny_clear_mask;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
+                           producer_deny_set_mask, producer_deny_clear_mask,
+                           consumer_set_mask, consumer_clear_mask,
+                           consumer_deny_set_mask, consumer_deny_clear_mask);
+};
+
 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
 // type signatures supported by bufferhubd.
 struct BufferHubRPC {
@@ -151,6 +187,7 @@
     kOpConsumerSetIgnore,
     kOpCreateProducerQueue,
     kOpCreateConsumerQueue,
+    kOpGetQueueInfo,
     kOpProducerQueueAllocateBuffers,
     kOpProducerQueueDetachBuffer,
     kOpConsumerQueueImportBuffers,
@@ -164,46 +201,49 @@
 
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
-                    int(int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    void(uint32_t width, uint32_t height, uint32_t format,
+                         uint64_t producer_usage, uint64_t consumer_usage,
+                         size_t meta_size_bytes, size_t slice_count));
   PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
-                    int(const std::string& name, int user_id, int group_id,
-                        int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    void(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 slice_count));
   PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
-                    int(const std::string& name));
+                    void(const std::string& name));
   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
                     NativeBufferHandle<LocalHandle>(unsigned index));
   PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
                     std::vector<NativeBufferHandle<LocalHandle>>(Void));
   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
-                    int(const std::string& name, int user_id, int group_id));
+                    void(const std::string& name, int user_id, int group_id));
   PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
-                    int(Void));
+                    void(Void));
   PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
-                    int(LocalFence acquire_fence, MetaData));
+                    void(LocalFence acquire_fence, MetaData));
   PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
   PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
                     std::pair<LocalFence, MetaData>(std::size_t metadata_size));
   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
-                    int(LocalFence release_fence));
-  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, int(bool ignore));
+                    void(LocalFence release_fence));
+  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    int(size_t meta_size_bytes, int usage_set_mask,
-                        int usage_clear_mask, int usage_deny_set_mask,
-                        int usage_deny_clear_mask));
+                    QueueInfo(size_t meta_size_bytes,
+                              const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
-                    std::pair<LocalChannelHandle, size_t>(Void));
+                    LocalChannelHandle(Void));
+  PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
-                        int width, int height, int format, int usage,
+                        uint32_t width, uint32_t height, uint32_t format,
+                        uint64_t producer_usage, uint64_t consumer_usage,
                         size_t slice_count, size_t buffer_count));
   PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
-                    int(size_t slot));
+                    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/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index e449cbd..e167a17 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,11 +12,20 @@
 class IonBuffer {
  public:
   IonBuffer();
-  IonBuffer(int width, int height, int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-            int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int layer_count,
-            int stride, int layer_stride, int format, int usage);
+  IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+  IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+            uint64_t producer_usage, uint64_t consumer_usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t format, uint32_t usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t format, uint64_t producer_usage,
+            uint64_t consumer_usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+            uint32_t format, uint32_t usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+            uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -30,25 +39,36 @@
   // previous native handle if necessary. Returns 0 on success or a negative
   // errno code otherwise. If allocation fails the previous native handle is
   // left intact.
-  int Alloc(int width, int height, int format, int usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t format,
+            uint64_t producer_usage, uint64_t consumer_usage);
 
   // Resets the underlying native handle and parameters, freeing the previous
   // native handle if necessary.
-  void Reset(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage);
+  void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint32_t usage);
+  void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint64_t producer_usage,
+             uint64_t consumer_usage);
 
   // Like Reset but also registers the native handle, which is necessary for
   // native handles received over IPC. Returns 0 on success or a negative errno
   // code otherwise. If import fails the previous native handle is left intact.
-  int Import(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage);
+  int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint32_t usage);
+  int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint64_t producer_usage,
+             uint64_t consumer_usage);
 
   // Like Reset but imports a native handle from raw fd and int arrays. Returns
   // 0 on success or a negative errno code otherwise. If import fails the
   // previous native handle is left intact.
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int stride, int format,
-             int usage);
+             int int_count, uint32_t width, uint32_t height, uint32_t stride,
+             uint32_t format, uint32_t usage);
+  int Import(const int* fd_array, int fd_count, const int* int_array,
+             int int_count, uint32_t width, uint32_t height, uint32_t stride,
+             uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
 
   // Duplicates the native handle underlying |other| and then imports it. This
   // is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -56,29 +76,38 @@
   // duplication or import fail the previous native handle is left intact.
   int Duplicate(const IonBuffer* other);
 
-  int Lock(int usage, int x, int y, int width, int height, void** address);
-  int LockYUV(int usage, int x, int y, int width, int height,
+  int Lock(uint32_t usage, int x, int y, int width, int height, void** address);
+  int LockYUV(uint32_t usage, int x, int y, int width, int height,
               struct android_ycbcr* yuv);
   int Unlock();
-  buffer_handle_t handle() const { if (buffer_.get()) return buffer_->handle;
-                                   else return nullptr; }
-  int width() const { if (buffer_.get()) return buffer_->getWidth();
-                      else return 0; }
-  int height() const { if (buffer_.get()) return buffer_->getHeight();
-                       else return 0; }
-  int layer_count() const { if (buffer_.get()) return buffer_->getLayerCount();
-                            else return 0; }
-  int stride() const { if (buffer_.get()) return buffer_->getStride();
-                       else return 0; }
-  int layer_stride() const { return 0; }
-  int format() const { if (buffer_.get()) return buffer_->getPixelFormat();
-                       else return 0; }
-  int usage() const { if (buffer_.get()) return buffer_->getUsage();
-                      else return 0; }
+
+  const sp<GraphicBuffer>& buffer() const { return buffer_; }
+  buffer_handle_t handle() const {
+    return buffer_.get() ? buffer_->handle : nullptr;
+  }
+  uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+  uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+  uint32_t layer_count() const {
+    return buffer_.get() ? buffer_->getLayerCount() : 0;
+  }
+  uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
+  uint32_t layer_stride() const { return 0; }
+  uint32_t format() const {
+    return buffer_.get() ? buffer_->getPixelFormat() : 0;
+  }
+  uint64_t producer_usage() const { return producer_usage_; }
+  uint64_t consumer_usage() const { return consumer_usage_; }
+  uint32_t usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
 
  private:
   sp<GraphicBuffer> buffer_;
 
+  // GraphicBuffer doesn't expose these separately. Keep these values cached for
+  // BufferHub to check policy against. Clients that import these buffers won't
+  // get the full picture, which is okay.
+  uint64_t producer_usage_;
+  uint64_t consumer_usage_;
+
   IonBuffer(const IonBuffer&) = delete;
   void operator=(const IonBuffer&) = delete;
 };
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index e5a56c1..df9ae81 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -6,40 +6,59 @@
 
 #include <mutex>
 
+namespace {
+
+constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
+
+}  // anonymous namespace
+
 namespace android {
 namespace dvr {
 
 IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
 
-IonBuffer::IonBuffer(int width, int height, int format, int usage)
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage)
+    : IonBuffer(width, height, format, usage, usage) {}
+
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage)
     : IonBuffer() {
-  Alloc(width, height, format, usage);
+  Alloc(width, height, format, producer_usage, consumer_usage);
 }
 
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-                     int format, int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t stride, uint32_t format, uint32_t usage)
     : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
 
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t layer_count, uint32_t stride,
+                     uint32_t layer_stride, uint32_t format, uint32_t usage)
+    : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
+                format, usage, usage) {}
 
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
-                     int layer_count, int stride, int layer_stride, int format,
-                     int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t layer_count, uint32_t stride,
+                     uint32_t layer_stride, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage)
     : buffer_(nullptr) {
   ALOGD_IF(TRACE,
-         "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
-         "stride=%d layer stride=%d format=%d usage=%d",
-         handle, width, height, layer_count, stride, layer_stride,
-         format, usage);
+           "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u layer stride=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64,
+           handle, width, height, layer_count, stride, layer_stride, format,
+           producer_usage, consumer_usage);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, usage);
+    Import(handle, width, height, stride, format, producer_usage,
+           consumer_usage);
   }
 }
 
 IonBuffer::~IonBuffer() {
   ALOGD_IF(TRACE,
-           "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
-           "format=%d usage=%d",
-           handle() , width(), height(), stride(), format(), usage());
+           "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
+           "format=%u usage=%x",
+           handle(), width(), height(), stride(), format(), usage());
   FreeHandle();
 }
 
@@ -62,55 +81,101 @@
   if (buffer_.get()) {
     // GraphicBuffer unregisters and cleans up the handle if needed
     buffer_ = nullptr;
+    producer_usage_ = 0;
+    consumer_usage_ = 0;
   }
 }
 
-int IonBuffer::Alloc(int width, int height, int format, int usage) {
-  ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
-           width, height, format, usage);
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage) {
+  return Alloc(width, height, format, usage, usage);
+}
 
-  buffer_ = new GraphicBuffer(width, height, format, usage);
-  if (buffer_->initCheck() != OK) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage) {
+  ALOGD_IF(
+      TRACE,
+      "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
+      " consumer_usage=%" PRIx64,
+      width, height, format, producer_usage, consumer_usage);
+
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
+                        producer_usage, consumer_usage);
+  if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
+    return -EINVAL;
+  } else {
+    buffer_ = buffer;
+    producer_usage_ = producer_usage;
+    consumer_usage_ = consumer_usage;
+    return 0;
   }
-  return 0;
 }
 
-void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int usage) {
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  Reset(handle, width, height, stride, format, usage, usage);
+}
+
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
-           "usage=%d",
-           handle, width, height, stride, format, usage);
-  Import(handle, width, height, stride, format, usage);
+           "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+           handle, width, height, stride, format, producer_usage,
+           consumer_usage);
+  Import(handle, width, height, stride, format, producer_usage, consumer_usage);
 }
 
-int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int usage) {
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  return Import(handle, width, height, stride, format, usage, usage);
+}
+
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ATRACE_NAME("IonBuffer::Import1");
   ALOGD_IF(
       TRACE,
-      "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
-      "usage=%d",
-      handle, width, height, stride, format, usage);
+      "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
+      "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+      handle, width, height, stride, format, producer_usage, consumer_usage);
   FreeHandle();
-  buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
-          width, height, format, 1, usage, stride);
-  if (buffer_->initCheck() != OK) {
+  sp<GraphicBuffer> buffer = new GraphicBuffer(
+      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
+      kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
+  if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Import: Failed to import buffer");
     return -EINVAL;
+  } else {
+    buffer_ = buffer;
+    producer_usage_ = producer_usage;
+    consumer_usage_ = consumer_usage;
+    return 0;
   }
-  return 0;
 }
 
 int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
-                      int int_count, int width, int height, int stride,
-                      int format, int usage) {
+                      int int_count, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
+                format, usage, usage);
+}
+
+int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
+                      int int_count, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ATRACE_NAME("IonBuffer::Import2");
   ALOGD_IF(TRACE,
-           "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
-           "stride=%d format=%d usage=%d",
-           fd_count, int_count, width, height, stride, format, usage);
+           "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
+           "stride=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64,
+           fd_count, int_count, width, height, stride, format, producer_usage,
+           consumer_usage);
 
   if (fd_count < 0 || int_count < 0) {
     ALOGE("IonBuffer::Import: invalid arguments.");
@@ -128,7 +193,8 @@
   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
 
-  int ret = Import(handle, width, height, stride, format, usage);
+  const int ret = Import(handle, width, height, stride, format, producer_usage,
+                         consumer_usage);
   if (ret < 0) {
     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
           strerror(-ret));
@@ -163,8 +229,9 @@
   memcpy(handle->data + fd_count, other->handle()->data + fd_count,
          sizeof(int) * int_count);
 
-  const int ret = Import(handle, other->width(), other->height(),
-                         other->stride(), other->format(), other->usage());
+  const int ret =
+      Import(handle, other->width(), other->height(), other->stride(),
+             other->format(), other->producer_usage(), other->consumer_usage());
   if (ret < 0) {
     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
           strerror(-ret));
@@ -175,7 +242,7 @@
   return ret;
 }
 
-int IonBuffer::Lock(int usage, int x, int y, int width, int height,
+int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
                     void** address) {
   ATRACE_NAME("IonBuffer::Lock");
   ALOGD_IF(TRACE,
@@ -183,23 +250,23 @@
            "address=%p",
            handle(), usage, x, y, width, height, address);
 
-  status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
-                               address);
+  status_t err =
+      buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
   if (err != NO_ERROR)
     return -EINVAL;
   else
     return 0;
 }
 
-int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
+int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
                        struct android_ycbcr* yuv) {
   ATRACE_NAME("IonBuffer::LockYUV");
   ALOGD_IF(TRACE,
            "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
            handle(), usage, x, y, width, height);
 
-  status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
-                                    yuv);
+  status_t err =
+      buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
   if (err != NO_ERROR)
     return -EINVAL;
   else
@@ -216,5 +283,5 @@
   else
     return 0;
 }
-} // namespace dvr
-} // namespace android
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 031401a..b431d2f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -11,34 +11,36 @@
 #include <pdx/file_handle.h>
 #include <private/dvr/bufferhub_rpc.h>
 
+using android::pdx::ErrorStatus;
+using android::pdx::LocalChannelHandle;
+using android::pdx::Status;
+
 namespace android {
 namespace dvr {
 
-BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle,
-                               size_t meta_size)
+BufferHubQueue::BufferHubQueue(LocalChannelHandle channel_handle)
     : Client{pdx::default_transport::ClientChannel::Create(
           std::move(channel_handle))},
-      meta_size_(meta_size),
-      meta_buffer_tmp_(meta_size ? new uint8_t[meta_size] : nullptr),
+      meta_size_(0),
       buffers_(BufferHubQueue::kMaxQueueCapacity),
       epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
       available_buffers_(BufferHubQueue::kMaxQueueCapacity),
       fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0) {
+      capacity_(0),
+      id_(-1) {
   Initialize();
 }
 
-BufferHubQueue::BufferHubQueue(const std::string& endpoint_path,
-                               size_t meta_size)
+BufferHubQueue::BufferHubQueue(const std::string& endpoint_path)
     : Client{pdx::default_transport::ClientChannelFactory::Create(
           endpoint_path)},
-      meta_size_(meta_size),
-      meta_buffer_tmp_(meta_size ? new uint8_t[meta_size] : nullptr),
+      meta_size_(0),
       buffers_(BufferHubQueue::kMaxQueueCapacity),
       epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
       available_buffers_(BufferHubQueue::kMaxQueueCapacity),
       fences_(BufferHubQueue::kMaxQueueCapacity),
-      capacity_(0) {
+      capacity_(0),
+      id_(-1) {
   Initialize();
 }
 
@@ -55,26 +57,47 @@
                                     BufferHubQueue::kEpollQueueEventIndex)}};
   ret = epoll_fd_.Control(EPOLL_CTL_ADD, event_fd(), &event);
   if (ret < 0) {
-    ALOGE("Failed to register ConsumerQueue into epoll event: %s",
+    ALOGE("BufferHubQueue::Initialize: Failed to add event fd to epoll set: %s",
           strerror(-ret));
   }
 }
 
-std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
-  Status<std::pair<LocalChannelHandle, size_t>> status =
-      InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
-
+Status<void> BufferHubQueue::ImportQueue() {
+  auto status = InvokeRemoteMethod<BufferHubRPC::GetQueueInfo>();
   if (!status) {
-    ALOGE("Cannot create ConsumerQueue: %s", status.GetErrorMessage().c_str());
+    ALOGE("BufferHubQueue::ImportQueue: Failed to import queue: %s",
+          status.GetErrorMessage().c_str());
+    return ErrorStatus(status.error());
+  } else {
+    SetupQueue(status.get().meta_size_bytes, status.get().id);
+    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);
+}
+
+std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
+  if (auto status = CreateConsumerQueueHandle())
+    return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
+  else
     return nullptr;
+}
+
+Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
+  auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
+  if (!status) {
+    ALOGE(
+        "BufferHubQueue::CreateConsumerQueue: Failed to create consumer queue: "
+        "%s",
+        status.GetErrorMessage().c_str());
+    return ErrorStatus(status.error());
   }
 
-  auto return_value = status.take();
-
-  ALOGD_IF(TRACE, "BufferHubQueue::CreateConsumerQueue: meta_size_bytes=%zu",
-           return_value.second);
-  return ConsumerQueue::Create(std::move(return_value.first),
-                               return_value.second);
+  return status;
 }
 
 bool BufferHubQueue::WaitForBuffers(int timeout) {
@@ -89,7 +112,8 @@
     }
 
     if (ret < 0 && ret != -EINTR) {
-      ALOGE("Failed to wait for buffers: %s", strerror(-ret));
+      ALOGE("BufferHubQueue::WaitForBuffers: Failed to wait for buffers: %s",
+            strerror(-ret));
       return false;
     }
 
@@ -108,7 +132,8 @@
       } else if (is_queue_event_index(index)) {
         HandleQueueEvent(events[i]);
       } else {
-        ALOGW("Unknown event index: %" PRId64, index);
+        ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
+              index);
       }
     }
   }
@@ -134,7 +159,8 @@
   if (events & EPOLLIN) {
     int ret = OnBufferReady(buffer, &fences_[slot]);
     if (ret < 0) {
-      ALOGE("Failed to set buffer ready: %s", strerror(-ret));
+      ALOGE("BufferHubQueue::HandleBufferEvent: Failed to set buffer ready: %s",
+            strerror(-ret));
       return;
     }
     Enqueue(buffer, slot);
@@ -144,8 +170,8 @@
     // epoll FD is cleaned up when the replacement consumer client is imported,
     // we shouldn't detach again if |epollhub_pending_[slot]| is set.
     ALOGW(
-        "Receives EPOLLHUP at slot: %zu, buffer event fd: %d, EPOLLHUP "
-        "pending: %d",
+        "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;
@@ -153,7 +179,10 @@
       DetachBuffer(slot);
     }
   } else {
-    ALOGW("Unknown event, slot=%zu, epoll events=%d", slot, events);
+    ALOGW(
+        "BufferHubQueue::HandleBufferEvent: Unknown event, slot=%zu, epoll "
+        "events=%d",
+        slot, events);
   }
 }
 
@@ -169,12 +198,13 @@
   if (events & EPOLLIN) {
     // Note that after buffer imports, if |count()| still returns 0, epoll
     // wait will be tried again to acquire the newly imported buffer.
-    int ret = OnBufferAllocated();
-    if (ret < 0) {
-      ALOGE("Failed to import buffer: %s", strerror(-ret));
+    auto buffer_status = OnBufferAllocated();
+    if (!buffer_status) {
+      ALOGE("BufferHubQueue::HandleQueueEvent: Failed to import buffer: %s",
+            buffer_status.GetErrorMessage().c_str());
     }
   } else {
-    ALOGW("Unknown epoll events=%d", events);
+    ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%d", events);
   }
 }
 
@@ -233,7 +263,7 @@
 void BufferHubQueue::Enqueue(std::shared_ptr<BufferHubBuffer> buf,
                              size_t slot) {
   if (count() == capacity_) {
-    ALOGE("Buffer queue is full!");
+    ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
     return;
   }
 
@@ -274,7 +304,7 @@
   available_buffers_.PopFront();
 
   if (!buf) {
-    ALOGE("Dequeue: Buffer to be dequeued is nullptr");
+    ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
     return nullptr;
   }
 
@@ -287,30 +317,57 @@
 }
 
 ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+    : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
 
-ProducerQueue::ProducerQueue(LocalChannelHandle handle, size_t meta_size)
-    : BASE(std::move(handle), meta_size) {}
+ProducerQueue::ProducerQueue(LocalChannelHandle handle)
+    : BASE(std::move(handle)) {
+  auto status = ImportQueue();
+  if (!status) {
+    ALOGE("ProducerQueue::ProducerQueue: Failed to import queue: %s",
+          status.GetErrorMessage().c_str());
+    Close(-status.error());
+  }
+}
 
-ProducerQueue::ProducerQueue(size_t meta_size, int usage_set_mask,
-                             int usage_clear_mask, int usage_deny_set_mask,
-                             int usage_deny_clear_mask)
-    : BASE(BufferHubRPC::kClientPath, meta_size) {
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+                             uint64_t producer_usage_clear_mask,
+                             uint64_t producer_usage_deny_set_mask,
+                             uint64_t producer_usage_deny_clear_mask,
+                             uint64_t consumer_usage_set_mask,
+                             uint64_t consumer_usage_clear_mask,
+                             uint64_t consumer_usage_deny_set_mask,
+                             uint64_t consumer_usage_deny_clear_mask)
+    : BASE(BufferHubRPC::kClientPath) {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size_, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
-      usage_deny_clear_mask);
+      meta_size,
+      UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
+                  producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
+                  consumer_usage_set_mask, consumer_usage_clear_mask,
+                  consumer_usage_deny_set_mask,
+                  consumer_usage_deny_clear_mask});
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
     Close(-status.error());
     return;
   }
+
+  SetupQueue(status.get().meta_size_bytes, status.get().id);
 }
 
-int ProducerQueue::AllocateBuffer(int width, int height, int format, int usage,
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                  uint32_t format, uint32_t usage,
                                   size_t slice_count, size_t* out_slot) {
+  return AllocateBuffer(width, height, format, usage, usage, slice_count,
+                        out_slot);
+}
+
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                  uint32_t format, uint64_t producer_usage,
+                                  uint64_t consumer_usage, size_t slice_count,
+                                  size_t* out_slot) {
   if (out_slot == nullptr) {
-    ALOGE("Parameter out_slot cannot be null.");
+    ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
     return -EINVAL;
   }
 
@@ -324,7 +381,8 @@
 
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, usage, slice_count, kBufferCount);
+          width, height, format, producer_usage, consumer_usage, slice_count,
+          kBufferCount);
   if (!status) {
     ALOGE(
         "ProducerQueue::AllocateBuffer failed to create producer buffer "
@@ -362,7 +420,7 @@
 }
 
 int ProducerQueue::DetachBuffer(size_t slot) {
-  Status<int> status =
+  auto status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
   if (!status) {
     ALOGE(
@@ -378,7 +436,9 @@
 std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(
     int timeout, size_t* slot, LocalHandle* release_fence) {
   if (slot == nullptr || release_fence == nullptr) {
-    ALOGE("invalid parameter, slot=%p, release_fence=%p", slot, release_fence);
+    ALOGE(
+        "ProducerQueue::Dequeue: invalid parameter, slot=%p, release_fence=%p",
+        slot, release_fence);
     return nullptr;
   }
 
@@ -392,21 +452,27 @@
   return buffer->Gain(release_fence);
 }
 
-ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, size_t meta_size)
-    : BASE(std::move(handle), meta_size) {
-  // TODO(b/34387835) Import consumer queue in case the ProducerQueue we are
+ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
+    : BufferHubQueue(std::move(handle)) {
+  auto status = ImportQueue();
+  if (!status) {
+    ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
+          status.GetErrorMessage().c_str());
+    Close(-status.error());
+  }
+
+  // TODO(b/34387835) Import buffers in case the ProducerQueue we are
   // based on was not empty.
 }
 
-int ConsumerQueue::ImportBuffers() {
-  Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
-      InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
+Status<size_t> ConsumerQueue::ImportBuffers() {
+  auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
   if (!status) {
     ALOGE(
         "ConsumerQueue::ImportBuffers failed to import consumer buffer through "
         "BufferBub, error: %s",
         status.GetErrorMessage().c_str());
-    return -status.error();
+    return ErrorStatus(status.error());
   }
 
   int last_error = 0;
@@ -431,7 +497,10 @@
     }
   }
 
-  return imported_buffers > 0 ? imported_buffers : last_error;
+  if (imported_buffers > 0)
+    return {imported_buffers};
+  else
+    return ErrorStatus(-last_error);
 }
 
 int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
@@ -445,15 +514,17 @@
     LocalHandle* acquire_fence) {
   if (meta_size != meta_size_) {
     ALOGE(
-        "metadata size (%zu) for the dequeuing buffer does not match metadata "
-        "size (%zu) for the queue.",
+        "ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
+        "does not match metadata size (%zu) for the queue.",
         meta_size, meta_size_);
     return nullptr;
   }
 
   if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
-    ALOGE("invalid parameter, slot=%p, meta=%p, acquire_fence=%p", slot, meta,
-          acquire_fence);
+    ALOGE(
+        "ConsumerQueue::Dequeue: Invalid parameter, slot=%p, meta=%p, "
+        "acquire_fence=%p",
+        slot, meta, acquire_fence);
     return nullptr;
   }
 
@@ -467,15 +538,19 @@
   return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
 }
 
-int ConsumerQueue::OnBufferAllocated() {
-  const int ret = ImportBuffers();
-  if (ret == 0) {
-    ALOGW("No new buffer can be imported on buffer allocated event.");
-  } else if (ret < 0) {
-    ALOGE("Failed to import buffers on buffer allocated event.");
+Status<void> ConsumerQueue::OnBufferAllocated() {
+  auto status = ImportBuffers();
+  if (!status) {
+    ALOGE("ConsumerQueue::OnBufferAllocated: Failed to import buffers: %s",
+          status.GetErrorMessage().c_str());
+    return ErrorStatus(status.error());
+  } else if (status.get() == 0) {
+    ALOGW("ConsumerQueue::OnBufferAllocated: No new buffers allocated!");
+    return ErrorStatus(ENOBUFS);
+  } else {
+    ALOGD_IF(TRACE, "Imported %zu consumer buffers.", status.get());
+    return {};
   }
-  ALOGD_IF(TRACE, "Imported %d consumer buffers.", ret);
-  return ret;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 3fe7642..ebd7da0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -38,22 +38,8 @@
   }
 
   const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+  sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
 
-  // Create new GraphicBuffer based on the newly created |buffer_producer|. Here
-  // we have to cast |buffer_handle_t| to |native_handle_t|, it's OK because
-  // internally, GraphicBuffer is still an |ANativeWindowBuffer| and |handle|
-  // is still type of |buffer_handle_t| and bears const property.
-  sp<GraphicBuffer> graphic_buffer(new GraphicBuffer(
-      buffer_producer->width(), buffer_producer->height(),
-      buffer_producer->format(),
-      1, /* layer count */
-      buffer_producer->usage(),
-      buffer_producer->stride(),
-      const_cast<native_handle_t*>(buffer_producer->buffer()->handle()),
-      false));
-
-  LOG_ALWAYS_FATAL_IF(NO_ERROR != graphic_buffer->initCheck(),
-                      "Failed to init GraphicBuffer.");
   core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
   core_->buffers_[slot].mRequestBufferCalled = true;
 
@@ -155,9 +141,9 @@
     if (!buffer_producer)
       return NO_MEMORY;
 
-    if (static_cast<int>(width) == buffer_producer->width() &&
-        static_cast<int>(height) == buffer_producer->height() &&
-        static_cast<int>(format) == buffer_producer->format()) {
+    if (width == buffer_producer->width() &&
+        height == buffer_producer->height() &&
+        static_cast<uint32_t>(format) == buffer_producer->format()) {
       // The producer queue returns a buffer producer matches the request.
       break;
     }
@@ -165,8 +151,8 @@
     // Needs reallocation.
     // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
     ALOGI(
-        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%d) is different "
-        "from the buffer returned at slot: %zu (w=%d, h=%d, format=%d). Need "
+        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+        "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
         "re-allocattion.",
         width, height, format, slot, buffer_producer->width(),
         buffer_producer->height(), buffer_producer->format());
@@ -322,7 +308,7 @@
 
   output->width = buffer_producer->width();
   output->height = buffer_producer->height();
-  output->transformHint = 0; // default value, we don't use it yet.
+  output->transformHint = 0;  // default value, we don't use it yet.
 
   // |numPendingBuffers| counts of the number of buffers that has been enqueued
   // by the producer but not yet acquired by the consumer. Due to the nature
@@ -456,7 +442,7 @@
   return NO_ERROR;
 }
 
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode mode) {
+status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
   // Consumer interaction are actually handled by buffer hub, and we need
   // to maintain consumer operations here.  We only need to perform basic input
   // parameter checks here.
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 a020dca..255793f 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
@@ -4,6 +4,7 @@
 #include <gui/BufferQueueDefs.h>
 
 #include <pdx/client.h>
+#include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/epoll_file_descriptor.h>
 #include <private/dvr/ring_buffer.h>
@@ -41,6 +42,9 @@
   // Return the default buffer format of this buffer queue.
   int32_t default_format() const { return default_format_; }
 
+  // Create a new consumer in handle form for immediate transport over RPC.
+  Status<LocalChannelHandle> CreateConsumerQueueHandle();
+
   // Return the number of buffers avaiable for dequeue.
   size_t count() const { return available_buffers_.GetSize(); }
 
@@ -51,7 +55,7 @@
   size_t metadata_size() const { return meta_size_; }
 
   // Return whether the buffer queue is alrady full.
-  bool is_full() const { return  available_buffers_.IsFull(); }
+  bool is_full() const { return available_buffers_.IsFull(); }
 
   explicit operator bool() const { return epoll_fd_.IsValid(); }
 
@@ -83,9 +87,18 @@
   // timeout.
   static constexpr int kNoTimeOut = -1;
 
+  int id() const { return id_; }
+
  protected:
-  BufferHubQueue(LocalChannelHandle channel, size_t meta_size);
-  BufferHubQueue(const std::string& endpoint_path, size_t meta_size);
+  BufferHubQueue(LocalChannelHandle channel);
+  BufferHubQueue(const std::string& endpoint_path);
+
+  // Imports the queue parameters by querying BufferHub for the parameters for
+  // this channel.
+  Status<void> ImportQueue();
+
+  // Sets up the queue with the given parameters.
+  void SetupQueue(size_t meta_size_bytes_, int id);
 
   // Called by ProducerQueue::AddBuffer and ConsumerQueue::AddBuffer only. to
   // register a buffer for epoll and internal bookkeeping.
@@ -112,7 +125,7 @@
                             LocalHandle* fence) = 0;
 
   // Called when a buffer is allocated remotely.
-  virtual int OnBufferAllocated() = 0;
+  virtual 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
@@ -235,6 +248,9 @@
   // Epoll fd used to wait for BufferHub events.
   EpollFileDescriptor epoll_fd_;
 
+  // Global id for the queue that is consistent across processes.
+  int id_;
+
   BufferHubQueue(const BufferHubQueue&) = delete;
   void operator=(BufferHubQueue&) = delete;
 };
@@ -258,18 +274,32 @@
   // |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(int usage_set_mask,
-                                               int usage_clear_mask,
-                                               int usage_deny_set_mask,
-                                               int usage_deny_clear_mask) {
+  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);
+                        usage_deny_set_mask, usage_deny_clear_mask,
+                        usage_set_mask, usage_clear_mask, usage_deny_set_mask,
+                        usage_deny_clear_mask);
+  }
+  template <typename Meta>
+  static std::unique_ptr<ProducerQueue> Create(
+      uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
+      uint64_t producer_usage_deny_set_mask,
+      uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
+      uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
+      uint64_t consumer_usage_deny_clear_mask) {
+    return BASE::Create(sizeof(Meta), producer_usage_set_mask,
+                        producer_usage_clear_mask, producer_usage_deny_set_mask,
+                        producer_usage_deny_clear_mask, consumer_usage_set_mask,
+                        consumer_usage_clear_mask, consumer_usage_deny_set_mask,
+                        consumer_usage_deny_clear_mask);
   }
 
   // Import a |ProducerQueue| from a channel handle.
-  template <typename Meta>
   static std::unique_ptr<ProducerQueue> Import(LocalChannelHandle handle) {
-    return BASE::Create(std::move(handle), sizeof(Meta));
+    return BASE::Create(std::move(handle));
   }
 
   // Get a buffer producer. Note that the method doesn't check whether the
@@ -286,7 +316,10 @@
   // use (i.e. in |Gain|'ed mode).
   // Returns Zero on success and negative error code when buffer allocation
   // fails.
-  int AllocateBuffer(int width, int height, int format, int usage,
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage, size_t slice_count, size_t* out_slot);
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage,
                      size_t slice_count, size_t* out_slot);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
@@ -311,18 +344,21 @@
   // static template methods inherited from ClientBase, which take the same
   // arguments as the constructors.
   explicit ProducerQueue(size_t meta_size);
-  ProducerQueue(LocalChannelHandle handle, size_t meta_size);
-  ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
-                int usage_deny_set_mask, int usage_deny_clear_mask);
+  ProducerQueue(LocalChannelHandle handle);
+  ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+                uint64_t producer_usage_clear_mask,
+                uint64_t producer_usage_deny_set_mask,
+                uint64_t producer_usage_deny_clear_mask,
+                uint64_t consumer_usage_set_mask,
+                uint64_t consumer_usage_clear_mask,
+                uint64_t consumer_usage_deny_set_mask,
+                uint64_t consumer_usage_deny_clear_mask);
 
   int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
                     LocalHandle* release_fence) override;
-
-  // Producer buffer is always allocated from the client (i.e. local) side.
-  int OnBufferAllocated() override { return 0; }
 };
 
-class ConsumerQueue : public pdx::ClientBase<ConsumerQueue, BufferHubQueue> {
+class ConsumerQueue : public BufferHubQueue {
  public:
   // Get a buffer consumer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been imported already. When no
@@ -333,10 +369,14 @@
         BufferHubQueue::GetBuffer(slot));
   }
 
+  // Import a |ConsumerQueue| from a channel handle.
+  static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle) {
+    return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(std::move(handle)));
+  }
+
   // Import newly created buffers from the service side.
-  // Returns number of buffers successfully imported; or negative error code
-  // when buffer import fails.
-  int ImportBuffers();
+  // Returns number of buffers successfully imported or an error.
+  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
@@ -353,10 +393,11 @@
   std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
                                           size_t meta_size,
                                           LocalHandle* acquire_fence);
- private:
-  friend BASE;
 
-  ConsumerQueue(LocalChannelHandle handle, size_t meta_size);
+ private:
+  friend BufferHubQueue;
+
+  ConsumerQueue(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|
@@ -367,7 +408,7 @@
   int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
                     LocalHandle* acquire_fence) override;
 
-  int OnBufferAllocated() override;
+  Status<void> OnBufferAllocated() override;
 };
 
 }  // namespace dvr
@@ -381,6 +422,7 @@
 
 struct DvrWriteBufferQueue {
   std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+  ANativeWindow* native_window_{nullptr};
 };
 
 struct DvrReadBufferQueue {
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 811543d..171577d 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -22,16 +22,20 @@
 class BufferHubQueueTest : public ::testing::Test {
  public:
   template <typename Meta>
-  void CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
+  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
                     int usage_deny_set_mask = 0,
                     int usage_deny_clear_mask = 0) {
     producer_queue_ =
         ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
                                     usage_deny_set_mask, usage_deny_clear_mask);
-    ASSERT_NE(nullptr, producer_queue_);
+    if (!producer_queue_)
+      return false;
 
     consumer_queue_ = producer_queue_->CreateConsumerQueue();
-    ASSERT_NE(nullptr, consumer_queue_);
+    if (!consumer_queue_)
+      return false;
+
+    return true;
   }
 
   void AllocateBuffer() {
@@ -51,7 +55,7 @@
 TEST_F(BufferHubQueueTest, TestDequeue) {
   const size_t nb_dequeue_times = 16;
 
-  CreateQueues<size_t>();
+  ASSERT_TRUE(CreateQueues<size_t>());
 
   // Allocate only one buffer.
   AllocateBuffer();
@@ -77,7 +81,7 @@
   size_t slot;
   uint64_t seq;
 
-  CreateQueues<uint64_t>();
+  ASSERT_TRUE(CreateQueues<uint64_t>());
 
   for (size_t i = 0; i < nb_buffer; i++) {
     AllocateBuffer();
@@ -127,7 +131,7 @@
 };
 
 TEST_F(BufferHubQueueTest, TestMetadata) {
-  CreateQueues<TestMetadata>();
+  ASSERT_TRUE(CreateQueues<TestMetadata>());
   AllocateBuffer();
 
   std::vector<TestMetadata> ms = {
@@ -149,7 +153,7 @@
 }
 
 TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
-  CreateQueues<int64_t>();
+  ASSERT_TRUE(CreateQueues<int64_t>());
   AllocateBuffer();
 
   int64_t mi = 3;
@@ -166,7 +170,7 @@
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
-  CreateQueues<int64_t>();
+  ASSERT_TRUE(CreateQueues<int64_t>());
   AllocateBuffer();
 
   size_t slot;
@@ -181,7 +185,7 @@
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
-  CreateQueues<int64_t>();
+  ASSERT_TRUE(CreateQueues<int64_t>());
 
   size_t s1;
   AllocateBuffer();
@@ -227,7 +231,7 @@
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const int set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  CreateQueues<int64_t>(set_mask, 0, 0, 0);
+  ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
@@ -243,7 +247,7 @@
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
   const int clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  CreateQueues<int64_t>(0, clear_mask, 0, 0);
+  ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
@@ -259,7 +263,7 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
   const int deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  CreateQueues<int64_t>(0, 0, deny_set_mask, 0);
+  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
 
   // Now that |deny_set_mask| is illegal, allocation without those bits should
   // be able to succeed.
@@ -278,7 +282,7 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
   const int deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  CreateQueues<int64_t>(0, 0, 0, deny_clear_mask);
+  ASSERT_TRUE(CreateQueues<int64_t>(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.
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 9952e59..ef50a0f 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -160,8 +160,7 @@
       return nullptr;
     }
 
-    producer_queue_ =
-        ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+    producer_queue_ = ProducerQueue::Import(status.take());
   }
   return producer_queue_;
 }
@@ -217,7 +216,8 @@
   return 0;
 }
 
-pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) {
+pdx::Status<void> DisplayClient::SetViewerParams(
+    const ViewerParams& viewer_params) {
   auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
   if (!status) {
     ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
@@ -253,16 +253,20 @@
   return DisplaySurfaceClient::Create(width, height, format, usage, flags);
 }
 
-std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+    const std::string& name) {
+  auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+        "error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return nullptr;
   }
 
-  return BufferConsumer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 bool DisplayClient::IsVrAppRunning() {
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 7993fce..44b3c4b 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,19 +31,22 @@
   return 0;
 }
 
-std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-      extended_region_size, usage);
+std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
+    const std::string& name, size_t size, uint64_t producer_usage,
+    uint64_t consumer_usage) {
+  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+      name, size, producer_usage, consumer_usage);
   if (!status) {
     ALOGE(
-        "DisplayManagerClient::SetupPoseBuffer: Failed to create the pose "
-        "buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
+        "buffer: name=%s, error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return {};
   }
 
-  return BufferProducer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 378f67c..fec2ea5 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -108,7 +108,7 @@
   std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
       int width, int height, int format, int usage, int flags);
 
-  std::unique_ptr<BufferConsumer> GetPoseBuffer();
+  std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   bool IsVrAppRunning();
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
index 144cd3b..b0a7d13 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
@@ -17,8 +17,10 @@
 
   int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
 
-  std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
-                                                  int usage);
+  std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
+                                              size_t size,
+                                              uint64_t producer_usage,
+                                              uint64_t consumer_usage);
 
   using Client::event_fd;
   using Client::GetChannel;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index ac08650..c12b090 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -9,6 +9,7 @@
 #include <pdx/rpc/remote_method.h>
 #include <pdx/rpc/serializable.h>
 #include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/display_types.h>
 
 namespace android {
@@ -218,7 +219,7 @@
     kOpCreateVideoMeshSurface,
     kOpVideoMeshSurfaceCreateProducerQueue,
     kOpSetViewerParams,
-    kOpGetPoseBuffer,
+    kOpGetNamedBuffer,
     kOpIsVrAppRunning,
   };
 
@@ -247,8 +248,8 @@
                     LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
                     void(const ViewerParams& viewer_params));
-  PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
-                    LocalChannelHandle(Void));
+  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name));
   PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
 };
 
@@ -260,7 +261,7 @@
   enum {
     kOpGetSurfaceList = 0,
     kOpUpdateSurfaces,
-    kOpSetupPoseBuffer,
+    kOpSetupNamedBuffer,
   };
 
   // Aliases.
@@ -273,8 +274,11 @@
   PDX_REMOTE_METHOD(
       UpdateSurfaces, kOpUpdateSurfaces,
       int(const std::map<int, DisplaySurfaceAttributes>& updates));
-  PDX_REMOTE_METHOD(SetupPoseBuffer, kOpSetupPoseBuffer,
-                    LocalChannelHandle(size_t extended_region_size, int usage));
+  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name,
+                                            size_t size,
+                                            uint64_t producer_usage,
+                                            uint64_t consumer_usage));
 };
 
 struct ScreenshotData {
diff --git a/libs/vr/libdisplay/video_mesh_surface_client.cpp b/libs/vr/libdisplay/video_mesh_surface_client.cpp
index 04cc194..a2307e5 100644
--- a/libs/vr/libdisplay/video_mesh_surface_client.cpp
+++ b/libs/vr/libdisplay/video_mesh_surface_client.cpp
@@ -30,8 +30,7 @@
       return nullptr;
     }
 
-    producer_queue_ =
-        ProducerQueue::Import<VideoMeshSurfaceBufferMetadata>(status.take());
+    producer_queue_ = ProducerQueue::Import(status.take());
   }
   return producer_queue_;
 }
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index 3c6934b..1050283 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -49,7 +49,6 @@
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.graphics.bufferqueue@1.0 \
     android.hidl.token@1.0-utils \
-    libandroid_runtime \
     libbase \
     libnativewindow \
 
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
index 7cbfc21..8d84f7b 100644
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -42,14 +42,16 @@
   delete client;
 }
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1) {
-  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
-  auto buffer_producer = client->client->SetupPoseBuffer(
-      extended_region_size, static_cast<int>(usage0));
-  if (buffer_producer) {
-    return CreateDvrWriteBufferFromBufferProducer(std::move(buffer_producer));
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+                                             const char* name, size_t size,
+                                             uint64_t producer_usage,
+                                             uint64_t consumer_usage) {
+  // TODO(hendrikw): When we move to gralloc1, pass both producer_usage and
+  // consumer_usage down.
+  auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
+                                                     consumer_usage);
+  if (ion_buffer) {
+    return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
   }
   return nullptr;
 }
@@ -109,8 +111,8 @@
 }
 
 int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers) {
+    DvrDisplayManagerClient* /* client */, int /* surface_id */,
+    DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
   // TODO(jwcai, hendrikw) Remove this after we replacing
   // dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
   return -1;
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index f786c29..b91de8f 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -31,8 +31,8 @@
         dvrDisplayManagerClientGetSurfaceList;
     dvr_api->display_manager_client_surface_list_destroy =
         dvrDisplayManagerClientSurfaceListDestroy;
-    dvr_api->display_manager_setup_pose_buffer =
-        dvrDisplayManagerSetupPoseBuffer;
+    dvr_api->display_manager_setup_named_buffer =
+        dvrDisplayManagerSetupNamedBuffer;
     dvr_api->display_manager_client_surface_list_get_size =
         dvrDisplayManagerClientSurfaceListGetSize;
     dvr_api->display_manager_client_surface_list_get_surface_id =
@@ -48,7 +48,6 @@
 
     // dvr_buffer.h
     dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
-    dvr_api->write_buffer_get_blob_fds = dvrWriteBufferGetBlobFds;
     dvr_api->write_buffer_get_ahardwarebuffer =
         dvrWriteBufferGetAHardwareBuffer;
     dvr_api->write_buffer_post = dvrWriteBufferPost;
@@ -56,11 +55,12 @@
     dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
 
     dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
-    dvr_api->read_buffer_get_blob_fds = dvrReadBufferGetBlobFds;
     dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
     dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
     dvr_api->read_buffer_release = dvrReadBufferRelease;
     dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
+    dvr_api->buffer_destroy = dvrBufferDestroy;
+    dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
 
     // dvr_buffer_queue.h
     dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
@@ -77,7 +77,7 @@
     dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
 
     // dvr_surface.h
-    dvr_api->get_pose_buffer = dvrGetPoseBuffer;
+    dvr_api->get_named_buffer = dvrGetNamedBuffer;
     dvr_api->surface_create = dvrSurfaceCreate;
     dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
 
@@ -108,6 +108,7 @@
     dvr_api->hwc_frame_get_display_id = dvrHwcFrameGetDisplayId;
     dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
     dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
+    dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
     dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
     dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
     dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 25128a6..0942b3d 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -6,13 +6,15 @@
 using namespace android;
 
 struct DvrWriteBuffer {
-  std::shared_ptr<dvr::BufferProducer> write_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferProducer> write_buffer;
 };
 
 struct DvrReadBuffer {
-  std::shared_ptr<dvr::BufferConsumer> read_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+  std::shared_ptr<dvr::IonBuffer> buffer;
 };
 
 namespace android {
@@ -20,16 +22,23 @@
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
-  DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
-  write_buffer->write_buffer_ = std::move(buffer_producer);
-  return write_buffer;
+  if (!buffer_producer)
+    return nullptr;
+  return new DvrWriteBuffer{std::move(buffer_producer)};
 }
 
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
     const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
-  DvrReadBuffer* read_buffer = new DvrReadBuffer;
-  read_buffer->read_buffer_ = std::move(buffer_consumer);
-  return read_buffer;
+  if (!buffer_consumer)
+    return nullptr;
+  return new DvrReadBuffer{std::move(buffer_consumer)};
+}
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer) {
+  if (!ion_buffer)
+    return nullptr;
+  return new DvrBuffer{std::move(ion_buffer)};
 }
 
 }  // namespace dvr
@@ -49,79 +58,82 @@
 
 extern "C" {
 
-void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
-
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count) {
-  client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
+  delete write_buffer;
 }
 
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->id();
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->write_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+      write_buffer->write_buffer->buffer()->buffer().get());
   return 0;
 }
 
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle fence(ready_fence_fd);
-  int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
-  fence.Release();
+  int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
   return result;
 }
 
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
   pdx::LocalHandle release_fence;
-  int result = client->write_buffer_->Gain(&release_fence);
+  int result = write_buffer->write_buffer->Gain(&release_fence);
   *release_fence_fd = release_fence.Release();
   return result;
 }
 
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
-  return client->write_buffer_->GainAsync();
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->GainAsync();
 }
 
-void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
 
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count) {
-  client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->id();
 }
 
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->read_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+      read_buffer->read_buffer->buffer()->buffer().get());
   return 0;
 }
 
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes) {
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle ready_fence;
   int result =
-      client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+      read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
   *ready_fence_fd = ready_fence.Release();
   return result;
 }
 
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
   pdx::LocalHandle fence(release_fence_fd);
-  int result = client->read_buffer_->Release(fence);
-  fence.Release();
+  int result = read_buffer->read_buffer->Release(fence);
   return result;
 }
 
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
-  return client->read_buffer_->ReleaseAsync();
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->ReleaseAsync();
+}
+
+void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
+
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer) {
+  if (!hardware_buffer) {
+    return -EINVAL;
+  }
+
+  *hardware_buffer =
+      reinterpret_cast<AHardwareBuffer*>(buffer->buffer->buffer().get());
+  return 0;
 }
 
 }  // extern "C"
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 4ce0b22..dfde21d 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -1,11 +1,10 @@
 #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 <android_runtime/android_view_Surface.h>
-
 #define CHECK_PARAM(param)                                               \
   LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
                       __FUNCTION__)
@@ -15,6 +14,9 @@
 extern "C" {
 
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
+  if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
+    ANativeWindow_release(write_queue->native_window_);
+  }
   delete write_queue;
 }
 
@@ -23,16 +25,30 @@
   return write_queue->producer_queue_->capacity();
 }
 
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                              JNIEnv* env) {
-  CHECK_PARAM(env);
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                          ANativeWindow** out_window) {
   CHECK_PARAM(write_queue);
+  CHECK_PARAM(out_window);
 
-  std::shared_ptr<dvr::BufferHubQueueCore> core =
-      dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+  // Lazy creation of |native_window_|.
+  if (write_queue->native_window_ == nullptr) {
+    std::shared_ptr<dvr::BufferHubQueueCore> core =
+        dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+    if (core == nullptr) {
+      ALOGE(
+          "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
+          "window.");
+      return -ENOMEM;
+    }
 
-  return android_view_Surface_createFromIGraphicBufferProducer(
-      env, new dvr::BufferHubQueueProducer(core));
+    sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
+    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;
 }
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
diff --git a/libs/vr/libdvr/dvr_hardware_composer_client.cpp b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
index e5665e1..39c2a90 100644
--- a/libs/vr/libdvr/dvr_hardware_composer_client.cpp
+++ b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
@@ -84,7 +84,7 @@
   delete frame;
 }
 
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
   return frame->frame.display_id;
 }
 
@@ -104,7 +104,7 @@
   return frame->frame.layers.size();
 }
 
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
   return frame->frame.layers[layer_index].id;
 }
 
@@ -120,8 +120,9 @@
   return frame->frame.layers[layer_index].fence->dup();
 }
 
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index) {
-  return Recti{
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+                                            size_t layer_index) {
+  return DvrHwcRecti{
     frame->frame.layers[layer_index].display_frame.left,
     frame->frame.layers[layer_index].display_frame.top,
     frame->frame.layers[layer_index].display_frame.right,
@@ -129,8 +130,8 @@
   };
 }
 
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
-  return Rectf{
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
+  return DvrHwcRectf{
     frame->frame.layers[layer_index].crop.left,
     frame->frame.layers[layer_index].crop.top,
     frame->frame.layers[layer_index].crop.right,
@@ -138,8 +139,10 @@
   };
 }
 
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index) {
-  return static_cast<BlendMode>(frame->frame.layers[layer_index].blend_mode);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+                                             size_t layer_index) {
+  return static_cast<DvrHwcBlendMode>(
+      frame->frame.layers[layer_index].blend_mode);
 }
 
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) {
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3cbba5..a04ed50 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -58,14 +58,25 @@
   return 0;
 }
 
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
   auto client = android::dvr::DisplayClient::Create();
   if (!client) {
-    ALOGE("Failed to create display client!");
+    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
     return -ECOMM;
   }
 
-  *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+  if (out_buffer == nullptr || name == nullptr) {
+    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+          out_buffer);
+    return -EINVAL;
+  }
+
+  auto named_buffer = client->GetNamedBuffer(name);
+  if (!named_buffer) {
+    ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
+    return -EINVAL;
+  }
+  *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
   return 0;
 }
 
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
index 0928d43..4e1f227 100644
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ b/libs/vr/libdvr/include/dvr/display_manager_client.h
@@ -14,15 +14,16 @@
     DvrDisplayManagerClientSurfaceList;
 typedef struct DvrDisplayManagerClientSurfaceBuffers
     DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrBuffer DvrBuffer;
 
 DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
 
 void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1);
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+                                             const char* name, size_t size,
+                                             uint64_t producer_usage,
+                                             uint64_t consumer_usage);
 
 // Return an event fd for checking if there was an event on the server
 // Note that the only event which will be flagged is POLLIN. You must use
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 053382f..7dc6a30 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -6,12 +6,13 @@
 #include <stdint.h>
 
 #include <dvr/dvr_hardware_composer_defs.h>
-#include <jni.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct ANativeWindow ANativeWindow;
+
 typedef struct DvrPoseAsync DvrPoseAsync;
 
 typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
@@ -29,6 +30,7 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
@@ -42,9 +44,9 @@
     DvrDisplayManagerClientSurfaceList** surface_list);
 typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1);
+typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
+    DvrDisplayManagerClient* client, const char* name, size_t size,
+    uint64_t producer_usage, uint64_t consumer_usage);
 typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
 typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
@@ -61,9 +63,6 @@
 
 // dvr_buffer.h
 typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
-typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
-                                            size_t* fds_count,
-                                            size_t max_fds_count);
 typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
     DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
@@ -73,9 +72,6 @@
 typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
 
 typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
-typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
-                                           size_t* fds_count,
-                                           size_t max_fds_count);
 typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
     DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
@@ -84,13 +80,16 @@
 typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
                                        int release_fence_fd);
 typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
+                                           AHardwareBuffer** hardware_buffer);
 
 // dvr_buffer_queue.h
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
 typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
-typedef jobject (*DvrWriteBufferQueueGetExternalSurfacePtr)(
-    DvrWriteBufferQueue* write_queue, JNIEnv* env);
+typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+    DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
@@ -109,7 +108,7 @@
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
-typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
 typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
                                    uint64_t usage0, uint64_t usage1, int flags,
                                    DvrSurface** out_surface);
@@ -148,27 +147,28 @@
 // dvr_hardware_composer_client.h
 typedef struct DvrHwcClient DvrHwcClient;
 typedef struct DvrHwcFrame DvrHwcFrame;
-typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
+typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
 typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback,
                                                void* client_state);
 typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client);
 typedef void (*DvrHwcFrameDestroyPtr)(DvrHwcFrame* frame);
-typedef Display (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
+typedef DvrHwcDisplay (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
 typedef int32_t (*DvrHwcFrameGetDisplayWidthPtr)(DvrHwcFrame* frame);
 typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame);
 typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame);
 typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame);
-typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, size_t layer_index);
+typedef DvrHwcLayer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame,
+                                                size_t layer_index);
 typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame,
                                                          size_t layer_index);
 typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame,
                                            size_t layer_index);
-typedef Recti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
-                                                    size_t layer_index);
-typedef Rectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
-                                            size_t layer_index);
-typedef BlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
-                                                     size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
+                                                          size_t layer_index);
+typedef DvrHwcRectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
+                                                  size_t layer_index);
+typedef DvrHwcBlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
+                                                           size_t layer_index);
 typedef float (*DvrHwcFrameGetLayerAlphaPtr)(DvrHwcFrame* frame,
                                              size_t layer_index);
 typedef uint32_t (*DvrHwcFrameGetLayerTypePtr)(DvrHwcFrame* frame,
@@ -184,7 +184,7 @@
       display_manager_client_get_surface_list;
   DvrDisplayManagerClientSurfaceListDestroyPtr
       display_manager_client_surface_list_destroy;
-  DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer;
+  DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
   DvrDisplayManagerClientSurfaceListGetSizePtr
       display_manager_client_surface_list_get_size;
   DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
@@ -200,7 +200,6 @@
 
   // Write buffer
   DvrWriteBufferDestroyPtr write_buffer_destroy;
-  DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds;
   DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
   DvrWriteBufferPostPtr write_buffer_post;
   DvrWriteBufferGainPtr write_buffer_gain;
@@ -208,11 +207,12 @@
 
   // Read buffer
   DvrReadBufferDestroyPtr read_buffer_destroy;
-  DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds;
   DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
   DvrReadBufferAcquirePtr read_buffer_acquire;
   DvrReadBufferReleasePtr read_buffer_release;
   DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
+  DvrBufferDestroy buffer_destroy;
+  DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
 
   // Write buffer queue
   DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
@@ -234,7 +234,7 @@
   DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
 
   // Display surface
-  DvrGetPoseBufferPtr get_pose_buffer;
+  DvrGetNamedBufferPtr get_named_buffer;
   DvrSurfaceCreatePtr surface_create;
   DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index bbfbb00..6c9c4d3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -1,9 +1,9 @@
 #ifndef ANDROID_DVR_BUFFER_H_
 #define ANDROID_DVR_BUFFER_H_
 
-#include <memory>
 #include <stdbool.h>
 #include <stdint.h>
+#include <memory>
 
 #ifdef __cplusplus
 extern "C" {
@@ -11,29 +11,33 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 // Write buffer
-void dvrWriteBufferDestroy(DvrWriteBuffer* client);
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count);
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes);
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
 
 // Read buffer
-void dvrReadBufferDestroy(DvrReadBuffer* client);
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count);
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes);
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// Buffer
+void dvrBufferDestroy(DvrBuffer* buffer);
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer);
 
 #ifdef __cplusplus
 }  // extern "C"
@@ -44,11 +48,14 @@
 
 class BufferProducer;
 class BufferConsumer;
+class IonBuffer;
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<BufferProducer>& buffer_producer);
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
     const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer);
 
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index 80c9779..ba39513 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -2,12 +2,13 @@
 #define ANDROID_DVR_BUFFER_QUEUE_H_
 
 #include <dvr/dvr_buffer.h>
-#include <jni.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct ANativeWindow ANativeWindow;
+
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
 
@@ -15,10 +16,12 @@
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
 size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
 
-// Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
-// using ANativeWindow_fromSurface NDK API.
-jobject dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
-                                              JNIEnv* env);
+// 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.
+int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+                                          ANativeWindow** out_window);
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
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 692864d..2d28aa3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -29,7 +29,7 @@
 // Called to free the frame information.
 void dvrHwcFrameDestroy(DvrHwcFrame* frame);
 
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
 
 int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
 
@@ -43,7 +43,7 @@
 // @return Number of layers in the frame.
 size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
 
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
 
 // Return the graphic buffer associated with the layer at |layer_index| in
 // |frame|.
@@ -58,11 +58,13 @@
 // @return Fence FD. Caller owns the FD and is responsible for closing it.
 int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
 
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+                                            size_t layer_index);
 
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
 
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+                                             size_t layer_index);
 
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
index 546ed7b..36c30f9 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
@@ -10,33 +10,33 @@
 // NOTE: These definitions must match the ones in
 // //hardware/libhardware/include/hardware/hwcomposer2.h. They are used by the
 // client side which does not have access to hwc2 headers.
-enum BlendMode {
-  BLEND_MODE_INVALID = 0,
-  BLEND_MODE_NONE = 1,
-  BLEND_MODE_PREMULTIPLIED = 2,
-  BLEND_MODE_COVERAGE = 3,
+enum DvrHwcBlendMode {
+  DVR_HWC_BLEND_MODE_INVALID = 0,
+  DVR_HWC_BLEND_MODE_NONE = 1,
+  DVR_HWC_BLEND_MODE_PREMULTIPLIED = 2,
+  DVR_HWC_BLEND_MODE_COVERAGE = 3,
 };
 
-enum Composition {
-  COMPOSITION_INVALID = 0,
-  COMPOSITION_CLIENT = 1,
-  COMPOSITION_DEVICE = 2,
-  COMPOSITION_SOLID_COLOR = 3,
-  COMPOSITION_CURSOR = 4,
-  COMPOSITION_SIDEBAND = 5,
+enum DvrHwcComposition {
+  DVR_HWC_COMPOSITION_INVALID = 0,
+  DVR_HWC_COMPOSITION_CLIENT = 1,
+  DVR_HWC_COMPOSITION_DEVICE = 2,
+  DVR_HWC_COMPOSITION_SOLID_COLOR = 3,
+  DVR_HWC_COMPOSITION_CURSOR = 4,
+  DVR_HWC_COMPOSITION_SIDEBAND = 5,
 };
 
-typedef uint64_t Display;
-typedef uint64_t Layer;
+typedef uint64_t DvrHwcDisplay;
+typedef uint64_t DvrHwcLayer;
 
-struct Recti {
+struct DvrHwcRecti {
   int32_t left;
   int32_t top;
   int32_t right;
   int32_t bottom;
 };
 
-struct Rectf {
+struct DvrHwcRectf {
   float left;
   float top;
   float right;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 2712f24..e5228d6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -12,7 +12,7 @@
 typedef struct DvrSurfaceParameter DvrSurfaceParameter;
 
 // Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
 
 int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
                      uint64_t usage1, int flags, DvrSurface** out_surface);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 158d58f..29cdc13 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -9,6 +9,7 @@
     libhardware \
     libui \
     libutils \
+    libnativewindow \
 
 static_libraries := \
     libdvr \
@@ -16,14 +17,18 @@
     libbufferhub \
     libchrome \
     libdvrcommon \
+    libdisplay \
     libpdx_default_transport \
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_SRC_FILES := \
+    dvr_buffer_queue-test.cpp \
+    dvr_named_buffer-test.cpp \
+
 LOCAL_STATIC_LIBRARIES := $(static_libraries)
 LOCAL_SHARED_LIBRARIES := $(shared_libraries)
 LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_api-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_api-test
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index f344a24..1c9eadd 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -1,4 +1,5 @@
 #include <dvr/dvr_buffer_queue.h>
+#include <gui/Surface.h>
 #include <private/dvr/buffer_hub_queue_client.h>
 
 #include <base/logging.h>
@@ -143,6 +144,17 @@
   dvrReadBufferQueueDestroy(read_queue);
 }
 
+TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
+  ANativeWindow* window = nullptr;
+  int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
+
+  ASSERT_EQ(0, ret);
+  ASSERT_NE(nullptr, window);
+
+  sp<Surface> surface = static_cast<Surface*>(window);
+  ASSERT_TRUE(Surface::isValid(surface));
+}
+
 }  // 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
new file mode 100644
index 0000000..cd3285f
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -0,0 +1,122 @@
+#include <android/hardware_buffer.h>
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_surface.h>
+#include <system/graphics.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class DvrNamedBufferTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    client_ = dvrDisplayManagerClientCreate();
+    ASSERT_NE(nullptr, client_);
+  }
+
+  void TearDown() override {
+    if (client_ != nullptr) {
+      dvrDisplayManagerClientDestroy(client_);
+      client_ = nullptr;
+    }
+  }
+
+  DvrDisplayManagerClient* client_ = nullptr;
+};
+
+TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
+  const char* buffer_name = "same_name";
+  DvrBuffer* buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer1);
+
+  DvrBuffer* buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer2);
+
+  AHardwareBuffer* hardware_buffer1 = nullptr;
+  int e1 = dvrBufferGetAHardwareBuffer(buffer1, &hardware_buffer1);
+  ASSERT_EQ(0, e1);
+
+  AHardwareBuffer* hardware_buffer2 = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer2);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer1);
+
+  AHardwareBuffer_Desc desc1 = {};
+  AHardwareBuffer_describe(hardware_buffer1, &desc1);
+  AHardwareBuffer_Desc desc2 = {};
+  AHardwareBuffer_describe(hardware_buffer2, &desc2);
+  ASSERT_EQ(desc1.width, 10u);
+  ASSERT_EQ(desc1.height, 1u);
+  ASSERT_EQ(desc1.layers, 1u);
+  ASSERT_EQ(desc1.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc1.usage0, 0u);
+  ASSERT_EQ(desc1.usage1, 0u);
+  ASSERT_EQ(desc2.width, 10u);
+  ASSERT_EQ(desc2.height, 1u);
+  ASSERT_EQ(desc2.layers, 1u);
+  ASSERT_EQ(desc2.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc2.usage0, 0u);
+  ASSERT_EQ(desc2.usage1, 0u);
+
+  dvrBufferDestroy(buffer1);
+  dvrBufferDestroy(buffer2);
+
+  DvrBuffer* buffer3 = nullptr;
+  int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+  ASSERT_NE(nullptr, buffer3);
+  ASSERT_EQ(0, e3);
+
+  AHardwareBuffer* hardware_buffer3 = nullptr;
+  int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+  ASSERT_EQ(0, e4);
+  ASSERT_NE(nullptr, hardware_buffer3);
+
+  AHardwareBuffer_Desc desc3 = {};
+  AHardwareBuffer_describe(hardware_buffer3, &desc3);
+  ASSERT_EQ(desc3.width, 10u);
+  ASSERT_EQ(desc3.height, 1u);
+  ASSERT_EQ(desc3.layers, 1u);
+  ASSERT_EQ(desc3.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc3.usage0, 0u);
+  ASSERT_EQ(desc3.usage1, 0u);
+
+  dvrBufferDestroy(buffer3);
+}
+
+TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
+  const char* buffer_name1 = "test1";
+  const char* buffer_name2 = "test2";
+  DvrBuffer* setup_buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer1);
+  dvrBufferDestroy(setup_buffer1);
+
+  DvrBuffer* setup_buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer2);
+  dvrBufferDestroy(setup_buffer2);
+
+  DvrBuffer* buffer1 = nullptr;
+  int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+  ASSERT_NE(nullptr, buffer1);
+  ASSERT_EQ(0, e1);
+  dvrBufferDestroy(buffer1);
+
+  DvrBuffer* buffer2 = nullptr;
+  int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+  ASSERT_NE(nullptr, buffer2);
+  ASSERT_EQ(0, e2);
+  dvrBufferDestroy(buffer2);
+}
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index 9a012ed..f12aef1 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -247,7 +247,7 @@
 inline std::size_t GetSerializedSize(const EmptyVariant&);
 template <typename... Types>
 inline std::size_t GetSerializedSize(const Variant<Types...>&);
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
 inline constexpr std::size_t GetSerializedSize(const T&);
 template <typename T>
 inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>&);
@@ -293,7 +293,7 @@
 }
 
 // Overload for structs/classes with SerializableMembers defined.
-template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enabled>
 inline constexpr std::size_t GetSerializedSize(const T& value) {
   return SerializableTraits<T>::GetSerializedSize(value);
 }
@@ -836,7 +836,7 @@
 inline void SerializeObject(const EmptyVariant&, MessageWriter*, void*&);
 template <typename... Types>
 inline void SerializeObject(const Variant<Types...>&, MessageWriter*, void*&);
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
 inline void SerializeObject(const T&, MessageWriter*, void*&);
 template <typename T>
 inline void SerializeObject(const PointerWrapper<T>&, MessageWriter*, void*&);
@@ -887,7 +887,7 @@
 }
 
 // Overload for serializable structure/class types.
-template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enabled>
 inline void SerializeObject(const T& value, MessageWriter* writer,
                             void*& buffer) {
   SerializableTraits<T>::SerializeObject(value, writer, buffer);
@@ -1379,7 +1379,7 @@
 }
 
 // Forward declarations for nested definitions.
-template <typename T, typename Enabled>
+template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
 inline ErrorType DeserializeObject(T*, MessageReader*, const void*&,
                                    const void*&);
 template <typename T>
@@ -1438,7 +1438,7 @@
                                    const void*&);
 
 // Deserializes a Serializable type.
-template <typename T, typename Enable = EnableIfHasSerializableMembers<T>>
+template <typename T, typename Enable>
 inline ErrorType DeserializeObject(T* value, MessageReader* reader,
                                    const void*& start, const void*& end) {
   return SerializableTraits<T>::DeserializeObject(value, reader, start, end);
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index 09789e5..cb44a51 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -39,15 +39,11 @@
 template <typename... Types>
 struct HasType : std::false_type {};
 template <typename T, typename U>
-struct HasType<T, U> : std::is_same<T, U> {};
+struct HasType<T, U> : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
 template <typename T, typename First, typename... Rest>
 struct HasType<T, First, Rest...>
-    : std::integral_constant<
-          bool, std::is_same<T, First>::value || HasType<T, Rest...>::value> {};
-
-template <typename T, typename... Types>
-using HasTypeIgnoreRef =
-    HasType<typename std::remove_reference<T>::type, Types...>;
+    : std::integral_constant<bool, HasType<T, First>::value ||
+                                       HasType<T, Rest...>::value> {};
 
 // Defines set operations on a set of Types...
 template <typename... Types>
@@ -59,8 +55,8 @@
   struct IsSubset<T> : HasType<T, Types...> {};
   template <typename First, typename... Rest>
   struct IsSubset<First, Rest...>
-      : std::integral_constant<
-            bool, IsSubset<First>::value && IsSubset<Rest...>::value> {};
+      : std::integral_constant<bool, IsSubset<First>::value &&
+                                         IsSubset<Rest...>::value> {};
 };
 
 // Determines the number of elements of Types... that are constructible from
@@ -80,18 +76,18 @@
 // Enable if T is an element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfElement =
-    typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value, R>::type;
+    typename std::enable_if<HasType<T, Types...>::value, R>::type;
 // Enable if T is not an element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfNotElement =
-    typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value, R>::type;
+    typename std::enable_if<!HasType<T, Types...>::value, R>::type;
 
 // Enable if T is convertible to an element of Types... T is considered
 // convertible IIF a single element of Types... is assignable from T and T is
 // not a direct element of Types...
 template <typename R, typename T, typename... Types>
 using EnableIfConvertible =
-    typename std::enable_if<!HasTypeIgnoreRef<T, Types...>::value &&
+    typename std::enable_if<!HasType<T, Types...>::value &&
                                 ConstructibleCount<T, Types...>::value == 1,
                             R>::type;
 
@@ -102,7 +98,7 @@
 // in conversion.
 template <typename R, typename T, typename... Types>
 using EnableIfAssignable =
-    typename std::enable_if<HasTypeIgnoreRef<T, Types...>::value ||
+    typename std::enable_if<HasType<T, Types...>::value ||
                                 ConstructibleCount<T, Types...>::value == 1,
                             R>::type;
 
@@ -362,15 +358,13 @@
   template <typename T>
   using TypeTag = detail::TypeTag<T>;
   template <typename T>
-  using TypeTagIgnoreRef = TypeTag<typename std::remove_reference<T>::type>;
+  using DecayedTypeTag = TypeTag<std::decay_t<T>>;
   template <std::size_t I>
   using TypeForIndex = detail::TypeForIndex<I, Types...>;
   template <std::size_t I>
   using TypeTagForIndex = detail::TypeTagForIndex<I, Types...>;
   template <typename T>
   using HasType = detail::HasType<T, Types...>;
-  template <typename T>
-  using HasTypeIgnoreRef = detail::HasTypeIgnoreRef<T, Types...>;
   template <typename R, typename T>
   using EnableIfElement = detail::EnableIfElement<R, T, Types...>;
   template <typename R, typename T>
@@ -381,13 +375,12 @@
   struct Direct {};
   struct Convert {};
   template <typename T>
-  using SelectConstructor =
-      detail::Select<HasTypeIgnoreRef<T>::value, Direct, Convert>;
+  using SelectConstructor = detail::Select<HasType<T>::value, Direct, Convert>;
 
   // Constructs by type tag when T is an direct element of Types...
   template <typename T>
   explicit Variant(T&& value, Direct)
-      : value_(0, &index_, TypeTagIgnoreRef<T>{}, std::forward<T>(value)) {}
+      : value_(0, &index_, DecayedTypeTag<T>{}, std::forward<T>(value)) {}
   // Conversion constructor when T is not a direct element of Types...
   template <typename T>
   explicit Variant(T&& value, Convert)
@@ -421,7 +414,7 @@
   // convertible to multiple elements of Types.
   template <typename T>
   EnableIfElement<Variant&, T> operator=(T&& value) {
-    Assign(TypeTagIgnoreRef<T>{}, std::forward<T>(value));
+    Assign(DecayedTypeTag<T>{}, std::forward<T>(value));
     return *this;
   }
 
@@ -487,7 +480,7 @@
   template <typename T>
   constexpr std::int32_t index_of() const {
     static_assert(HasType<T>::value, "T is not an element type of Variant.");
-    return value_.template index(TypeTag<T>{});
+    return value_.template index(DecayedTypeTag<T>{});
   }
 
   // Returns the index of the active type. If the Variant is empty -1 is
@@ -509,14 +502,14 @@
   template <typename T>
   T* get() {
     if (is<T>())
-      return &value_.template get(TypeTag<T>{});
+      return &value_.template get(DecayedTypeTag<T>{});
     else
       return nullptr;
   }
   template <typename T>
   const T* get() const {
     if (is<T>())
-      return &value_.template get(TypeTag<T>{});
+      return &value_.template get(DecayedTypeTag<T>{});
     else
       return nullptr;
   }
@@ -537,7 +530,7 @@
 
  private:
   std::int32_t index_ = kEmptyIndex;
-  detail::Union<Types...> value_;
+  detail::Union<std::decay_t<Types>...> value_;
 
   // Constructs an element from the given arguments and sets the Variant to the
   // resulting type.
diff --git a/libs/vr/libpdx/thread_local_buffer_tests.cpp b/libs/vr/libpdx/thread_local_buffer_tests.cpp
index 1747d79..6cdaf10 100644
--- a/libs/vr/libpdx/thread_local_buffer_tests.cpp
+++ b/libs/vr/libpdx/thread_local_buffer_tests.cpp
@@ -89,13 +89,13 @@
   EXPECT_NE(id1, id2);
 }
 
-// TODO(b/36456321): Fix this and enable it again.
 // Tests that thread-local buffers are allocated at the first buffer request.
-TEST(ThreadLocalBufferTest, DISABLED_InitialValue) {
+TEST(ThreadLocalBufferTest, InitialValue) {
   struct TypeTagX;
   using SendSlotX = ThreadLocalSlot<TypeTagX, kSendBufferIndex>;
 
   auto value1 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
+  MessageBuffer<SendSlotX>::GetBuffer();
   auto value2 = ThreadLocalBufferTest::GetSlotValue<SendSlotX>();
 
   EXPECT_EQ(0U, value1);
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index c30c055..325f33f 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -368,6 +368,13 @@
   }
 
   {
+    TestType<int> i(1);
+    Variant<int, bool, float> v(i.get());
+    ASSERT_TRUE(v.is<int>());
+    EXPECT_EQ(1, std::get<int>(v));
+  }
+
+  {
     TestType<bool> b(true);
     Variant<int, bool, float> v(b.take());
     ASSERT_TRUE(v.is<bool>());
@@ -375,6 +382,13 @@
   }
 
   {
+    TestType<bool> b(true);
+    Variant<int, bool, float> v(b.get());
+    ASSERT_TRUE(v.is<bool>());
+    EXPECT_EQ(true, std::get<bool>(v));
+  }
+
+  {
     Variant<const char*> c("test");
     Variant<std::string> s(c);
     ASSERT_TRUE(s.is<std::string>());
@@ -1060,8 +1074,8 @@
   EXPECT_FALSE((detail::HasType<char, int, float, bool>::value));
   EXPECT_FALSE(detail::HasType<>::value);
 
-  EXPECT_TRUE((detail::HasTypeIgnoreRef<int&, int, float, bool>::value));
-  EXPECT_FALSE((detail::HasTypeIgnoreRef<char&, int, float, bool>::value));
+  EXPECT_TRUE((detail::HasType<int&, int, float, bool>::value));
+  EXPECT_FALSE((detail::HasType<char&, int, float, bool>::value));
 }
 
 TEST(Variant, Set) {
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 4cbdb94..924335f 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -67,7 +67,7 @@
   ResponseHeader<LocalHandle> response;
 };
 
-Status<void> ReadAndDiscardData(int socket_fd, size_t size) {
+Status<void> ReadAndDiscardData(const BorrowedHandle& socket_fd, size_t size) {
   while (size > 0) {
     // If there is more data to read in the message than the buffers provided
     // by the caller, read and discard the extra data from the socket.
@@ -83,9 +83,10 @@
   return ErrorStatus(EIO);
 }
 
-Status<void> SendRequest(int socket_fd, TransactionState* transaction_state,
-                         int opcode, const iovec* send_vector,
-                         size_t send_count, size_t max_recv_len) {
+Status<void> SendRequest(const BorrowedHandle& socket_fd,
+                         TransactionState* transaction_state, int opcode,
+                         const iovec* send_vector, size_t send_count,
+                         size_t max_recv_len) {
   size_t send_len = CountVectorSize(send_vector, send_count);
   InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
               false);
@@ -95,7 +96,8 @@
   return status;
 }
 
-Status<void> ReceiveResponse(int socket_fd, TransactionState* transaction_state,
+Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
+                             TransactionState* transaction_state,
                              const iovec* receive_vector, size_t receive_count,
                              size_t max_recv_len) {
   auto status = ReceiveData(socket_fd, &transaction_state->response);
@@ -164,7 +166,7 @@
 
   InitRequest(&request, opcode, length, 0, true);
   memcpy(request.impulse_payload.data(), buffer, length);
-  return SendData(channel_handle_.value(), request);
+  return SendData(BorrowedHandle{channel_handle_.value()}, request);
 }
 
 Status<int> ClientChannel::SendAndReceive(void* transaction_state, int opcode,
@@ -182,11 +184,11 @@
   auto* state = static_cast<TransactionState*>(transaction_state);
   size_t max_recv_len = CountVectorSize(receive_vector, receive_count);
 
-  auto status = SendRequest(channel_handle_.value(), state, opcode, send_vector,
-                            send_count, max_recv_len);
+  auto status = SendRequest(BorrowedHandle{channel_handle_.value()}, state,
+                            opcode, send_vector, send_count, max_recv_len);
   if (status) {
-    status = ReceiveResponse(channel_handle_.value(), state, receive_vector,
-                             receive_count, max_recv_len);
+    status = ReceiveResponse(BorrowedHandle{channel_handle_.value()}, state,
+                             receive_vector, receive_count, max_recv_len);
   }
   if (!result.PropagateError(status)) {
     const int return_code = state->response.ret_code;
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index f059453..323236d 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -111,11 +111,11 @@
         remote.sun_path);
   RequestHeader<BorrowedHandle> request;
   InitRequest(&request, opcodes::CHANNEL_OPEN, 0, 0, false);
-  status = SendData(socket_fd.Get(), request);
+  status = SendData(socket_fd.Borrow(), request);
   if (!status)
     return ErrorStatus(status.error());
   ResponseHeader<LocalHandle> response;
-  status = ReceiveData(socket_fd.Get(), &response);
+  status = ReceiveData(socket_fd.Borrow(), &response);
   if (!status)
     return ErrorStatus(status.error());
   int ref = response.ret_code;
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index fe5c986..d604f62 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -26,18 +26,19 @@
   uint32_t fd_count{0};
 };
 
-Status<void> SendPayload::Send(int socket_fd) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd) {
   return Send(socket_fd, nullptr);
 }
 
-Status<void> SendPayload::Send(int socket_fd, const ucred* cred) {
+Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
+                               const ucred* cred) {
   MessagePreamble preamble;
   preamble.magic = kMagicPreamble;
   preamble.data_size = buffer_.size();
   preamble.fd_count = file_handles_.size();
 
-  ssize_t ret =
-      RETRY_EINTR(send(socket_fd, &preamble, sizeof(preamble), MSG_NOSIGNAL));
+  ssize_t ret = RETRY_EINTR(
+      send(socket_fd.Get(), &preamble, sizeof(preamble), MSG_NOSIGNAL));
   if (ret < 0)
     return ErrorStatus(errno);
   if (ret != sizeof(preamble))
@@ -71,7 +72,7 @@
     }
   }
 
-  ret = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+  ret = RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
   if (ret < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(ret) != buffer_.size())
@@ -125,14 +126,15 @@
   return ErrorStatus{EOPNOTSUPP};
 }
 
-Status<void> ReceivePayload::Receive(int socket_fd) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd) {
   return Receive(socket_fd, nullptr);
 }
 
-Status<void> ReceivePayload::Receive(int socket_fd, ucred* cred) {
+Status<void> ReceivePayload::Receive(const BorrowedHandle& socket_fd,
+                                     ucred* cred) {
   MessagePreamble preamble;
-  ssize_t ret =
-      RETRY_EINTR(recv(socket_fd, &preamble, sizeof(preamble), MSG_WAITALL));
+  ssize_t ret = RETRY_EINTR(
+      recv(socket_fd.Get(), &preamble, sizeof(preamble), MSG_WAITALL));
   if (ret < 0)
     return ErrorStatus(errno);
   else if (ret == 0)
@@ -157,7 +159,7 @@
     msg.msg_control = alloca(msg.msg_controllen);
   }
 
-  ret = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+  ret = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
   if (ret < 0)
     return ErrorStatus(errno);
   else if (ret == 0)
@@ -219,8 +221,10 @@
   return false;
 }
 
-Status<void> SendData(int socket_fd, const void* data, size_t size) {
-  ssize_t size_written = RETRY_EINTR(send(socket_fd, data, size, MSG_NOSIGNAL));
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+                      size_t size) {
+  ssize_t size_written =
+      RETRY_EINTR(send(socket_fd.Get(), data, size, MSG_NOSIGNAL));
   if (size_written < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(size_written) != size)
@@ -228,11 +232,13 @@
   return {};
 }
 
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+                            size_t count) {
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_written = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
+  ssize_t size_written =
+      RETRY_EINTR(sendmsg(socket_fd.Get(), &msg, MSG_NOSIGNAL));
   if (size_written < 0)
     return ErrorStatus(errno);
   if (static_cast<size_t>(size_written) != CountVectorSize(data, count))
@@ -240,8 +246,10 @@
   return {};
 }
 
-Status<void> ReceiveData(int socket_fd, void* data, size_t size) {
-  ssize_t size_read = RETRY_EINTR(recv(socket_fd, data, size, MSG_WAITALL));
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+                         size_t size) {
+  ssize_t size_read =
+      RETRY_EINTR(recv(socket_fd.Get(), data, size, MSG_WAITALL));
   if (size_read < 0)
     return ErrorStatus(errno);
   else if (size_read == 0)
@@ -251,11 +259,12 @@
   return {};
 }
 
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count) {
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+                               const iovec* data, size_t count) {
   msghdr msg = {};
   msg.msg_iov = const_cast<iovec*>(data);
   msg.msg_iovlen = count;
-  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
+  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd.Get(), &msg, MSG_WAITALL));
   if (size_read < 0)
     return ErrorStatus(errno);
   else if (size_read == 0)
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 80530bf..82950a2 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -25,8 +25,8 @@
 
 class SendPayload : public MessageWriter, public OutputResourceMapper {
  public:
-  Status<void> Send(int socket_fd);
-  Status<void> Send(int socket_fd, const ucred* cred);
+  Status<void> Send(const BorrowedHandle& socket_fd);
+  Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
 
   // MessageWriter
   void* GetNextWriteBufferSection(size_t size) override;
@@ -50,8 +50,8 @@
 
 class ReceivePayload : public MessageReader, public InputResourceMapper {
  public:
-  Status<void> Receive(int socket_fd);
-  Status<void> Receive(int socket_fd, ucred* cred);
+  Status<void> Receive(const BorrowedHandle& socket_fd);
+  Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
 
   // MessageReader
   BufferSection GetNextReadBufferSection() override;
@@ -111,25 +111,27 @@
 };
 
 template <typename T>
-inline Status<void> SendData(int socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
   SendPayload payload;
   rpc::Serialize(data, &payload);
   return payload.Send(socket_fd);
 }
 
 template <typename FileHandleType>
-inline Status<void> SendData(int socket_fd,
+inline Status<void> SendData(const BorrowedHandle& socket_fd,
                              const RequestHeader<FileHandleType>& request) {
   SendPayload payload;
   rpc::Serialize(request, &payload);
   return payload.Send(socket_fd, &request.cred);
 }
 
-Status<void> SendData(int socket_fd, const void* data, size_t size);
-Status<void> SendDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
+                      size_t size);
+Status<void> SendDataVector(const BorrowedHandle& socket_fd, const iovec* data,
+                            size_t count);
 
 template <typename T>
-inline Status<void> ReceiveData(int socket_fd, T* data) {
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd, T* data) {
   ReceivePayload payload;
   Status<void> status = payload.Receive(socket_fd);
   if (status && rpc::Deserialize(data, &payload) != rpc::ErrorCode::NO_ERROR)
@@ -138,7 +140,7 @@
 }
 
 template <typename FileHandleType>
-inline Status<void> ReceiveData(int socket_fd,
+inline Status<void> ReceiveData(const BorrowedHandle& socket_fd,
                                 RequestHeader<FileHandleType>* request) {
   ReceivePayload payload;
   Status<void> status = payload.Receive(socket_fd, &request->cred);
@@ -147,8 +149,10 @@
   return status;
 }
 
-Status<void> ReceiveData(int socket_fd, void* data, size_t size);
-Status<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count);
+Status<void> ReceiveData(const BorrowedHandle& socket_fd, void* data,
+                         size_t size);
+Status<void> ReceiveDataVector(const BorrowedHandle& socket_fd,
+                               const iovec* data, size_t count);
 
 size_t CountVectorSize(const iovec* data, size_t count);
 void InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 2b24f62..f747abc 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -117,18 +117,20 @@
     return next_message_id_.fetch_add(1, std::memory_order_relaxed);
   }
 
-  void BuildCloseMessage(int channel_id, Message* message);
+  void BuildCloseMessage(int32_t channel_id, Message* message);
 
   Status<void> AcceptConnection(Message* message);
-  Status<void> ReceiveMessageForChannel(int channel_id, Message* message);
+  Status<void> ReceiveMessageForChannel(const BorrowedHandle& channel_fd,
+                                        Message* message);
   Status<void> OnNewChannel(LocalHandle channel_fd);
-  Status<ChannelData*> OnNewChannelLocked(LocalHandle channel_fd,
-                                          Channel* channel_state);
-  Status<void> CloseChannelLocked(int channel_id);
-  Status<void> ReenableEpollEvent(int fd);
-  Channel* GetChannelState(int channel_id);
-  int GetChannelSocketFd(int channel_id);
-  int GetChannelEventFd(int channel_id);
+  Status<std::pair<int32_t, ChannelData*>> OnNewChannelLocked(
+      LocalHandle channel_fd, Channel* channel_state);
+  Status<void> CloseChannelLocked(int32_t channel_id);
+  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);
+  int32_t GetChannelId(const BorrowedHandle& channel_fd);
 
   std::string endpoint_path_;
   bool is_blocking_;
@@ -137,7 +139,9 @@
   LocalHandle epoll_fd_;
 
   mutable std::mutex channel_mutex_;
-  std::map<int, ChannelData> channels_;
+  std::map<int32_t, ChannelData> channels_;
+  std::map<int, int32_t> channel_fd_to_id_;
+  int32_t last_channel_id_{0};
 
   Service* service_{nullptr};
   std::atomic<uint32_t> next_message_id_;
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 6f32867..65fd59f 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -220,9 +220,11 @@
     return ErrorStatus(errno);
   }
 
-  auto status = ReceiveMessageForChannel(channel_fd.Get(), message);
+  // Borrow the channel handle before we pass (move) it into OnNewChannel().
+  BorrowedHandle borrowed_channel_handle = channel_fd.Borrow();
+  auto status = OnNewChannel(std::move(channel_fd));
   if (status)
-    status = OnNewChannel(std::move(channel_fd));
+    status = ReceiveMessageForChannel(borrowed_channel_handle, message);
   return status;
 }
 
@@ -247,7 +249,7 @@
   return status;
 }
 
-Status<Endpoint::ChannelData*> Endpoint::OnNewChannelLocked(
+Status<std::pair<int32_t, Endpoint::ChannelData*>> Endpoint::OnNewChannelLocked(
     LocalHandle channel_fd, Channel* channel_state) {
   epoll_event event;
   event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
@@ -259,19 +261,28 @@
     return ErrorStatus(errno);
   }
   ChannelData channel_data;
-  const int channel_id = channel_fd.Get();
   channel_data.event_set.AddDataFd(channel_fd);
   channel_data.data_fd = std::move(channel_fd);
   channel_data.channel_state = channel_state;
-  auto pair = channels_.emplace(channel_id, std::move(channel_data));
-  return &pair.first->second;
+  for (;;) {
+    // Try new channel IDs until we find one which is not already in the map.
+    if (last_channel_id_++ == std::numeric_limits<int32_t>::max())
+      last_channel_id_ = 1;
+    auto iter = channels_.lower_bound(last_channel_id_);
+    if (iter == channels_.end() || iter->first != last_channel_id_) {
+      channel_fd_to_id_.emplace(channel_data.data_fd.Get(), last_channel_id_);
+      iter = channels_.emplace_hint(iter, last_channel_id_,
+                                    std::move(channel_data));
+      return std::make_pair(last_channel_id_, &iter->second);
+    }
+  }
 }
 
-Status<void> Endpoint::ReenableEpollEvent(int fd) {
+Status<void> Endpoint::ReenableEpollEvent(const BorrowedHandle& fd) {
   epoll_event event;
   event.events = EPOLLIN | EPOLLRDHUP | EPOLLONESHOT;
-  event.data.fd = fd;
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd, &event) < 0) {
+  event.data.fd = fd.Get();
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_MOD, fd.Get(), &event) < 0) {
     ALOGE(
         "Endpoint::ReenableEpollEvent: Failed to re-enable channel to "
         "endpoint: %s\n",
@@ -286,16 +297,17 @@
   return CloseChannelLocked(channel_id);
 }
 
-Status<void> Endpoint::CloseChannelLocked(int channel_id) {
+Status<void> Endpoint::CloseChannelLocked(int32_t channel_id) {
   ALOGD_IF(TRACE, "Endpoint::CloseChannelLocked: channel_id=%d", channel_id);
 
-  auto channel_data = channels_.find(channel_id);
-  if (channel_data == channels_.end())
+  auto iter = channels_.find(channel_id);
+  if (iter == channels_.end())
     return ErrorStatus{EINVAL};
 
+  int channel_fd = iter->second.data_fd.Get();
   Status<void> status;
   epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
-  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_id, &dummy) < 0) {
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, channel_fd, &dummy) < 0) {
     status.SetError(errno);
     ALOGE(
         "Endpoint::CloseChannelLocked: Failed to remove channel from endpoint: "
@@ -305,7 +317,8 @@
     status.SetValue();
   }
 
-  channels_.erase(channel_data);
+  channel_fd_to_id_.erase(channel_fd);
+  channels_.erase(iter);
   return status;
 }
 
@@ -348,10 +361,10 @@
   }
 
   std::lock_guard<std::mutex> autolock(channel_mutex_);
-  *channel_id = local_socket.Get();
   auto channel_data = OnNewChannelLocked(std::move(local_socket), channel);
   if (!channel_data)
     return channel_data.error_status();
+  *channel_id = channel_data.get().first;
 
   // Flags are ignored for now.
   // TODO(xiaohuit): Implement those.
@@ -359,7 +372,7 @@
   auto* state = static_cast<MessageState*>(message->GetState());
   Status<ChannelReference> ref = state->PushChannelHandle(
       remote_socket.Borrow(),
-      channel_data.get()->event_set.event_fd().Borrow());
+      channel_data.get().second->event_set.event_fd().Borrow());
   if (!ref)
     return ref.error_status();
   state->sockets_to_close.push_back(std::move(remote_socket));
@@ -373,32 +386,42 @@
   return ErrorStatus(EFAULT);
 }
 
-Channel* Endpoint::GetChannelState(int channel_id) {
+Channel* Endpoint::GetChannelState(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
   auto channel_data = channels_.find(channel_id);
   return (channel_data != channels_.end()) ? channel_data->second.channel_state
                                            : nullptr;
 }
 
-int Endpoint::GetChannelSocketFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelSocketFd(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
+  BorrowedHandle handle;
   auto channel_data = channels_.find(channel_id);
-  return (channel_data != channels_.end()) ? channel_data->second.data_fd.Get()
-                                           : -1;
+  if (channel_data != channels_.end())
+    handle = channel_data->second.data_fd.Borrow();
+  return handle;
 }
 
-int Endpoint::GetChannelEventFd(int channel_id) {
+BorrowedHandle Endpoint::GetChannelEventFd(int32_t channel_id) {
   std::lock_guard<std::mutex> autolock(channel_mutex_);
+  BorrowedHandle handle;
   auto channel_data = channels_.find(channel_id);
-  return (channel_data != channels_.end())
-             ? channel_data->second.event_set.event_fd().Get()
-             : -1;
+  if (channel_data != channels_.end())
+    handle = channel_data->second.event_set.event_fd().Borrow();
+  return handle;
 }
 
-Status<void> Endpoint::ReceiveMessageForChannel(int channel_id,
-                                                Message* message) {
+int32_t Endpoint::GetChannelId(const BorrowedHandle& channel_fd) {
+  std::lock_guard<std::mutex> autolock(channel_mutex_);
+  auto iter = channel_fd_to_id_.find(channel_fd.Get());
+  return (iter != channel_fd_to_id_.end()) ? iter->second : -1;
+}
+
+Status<void> Endpoint::ReceiveMessageForChannel(
+    const BorrowedHandle& channel_fd, Message* message) {
   RequestHeader<LocalHandle> request;
-  auto status = ReceiveData(channel_id, &request);
+  int32_t channel_id = GetChannelId(channel_fd);
+  auto status = ReceiveData(channel_fd.Borrow(), &request);
   if (!status) {
     if (status.error() == ESHUTDOWN) {
       BuildCloseMessage(channel_id, message);
@@ -434,12 +457,12 @@
   state->request = std::move(request);
   if (request.send_len > 0 && !request.is_impulse) {
     state->request_data.resize(request.send_len);
-    status = ReceiveData(channel_id, state->request_data.data(),
+    status = ReceiveData(channel_fd, state->request_data.data(),
                          state->request_data.size());
   }
 
   if (status && request.is_impulse)
-    status = ReenableEpollEvent(channel_id);
+    status = ReenableEpollEvent(channel_fd);
 
   if (!status) {
     if (status.error() == ESHUTDOWN) {
@@ -454,7 +477,7 @@
   return status;
 }
 
-void Endpoint::BuildCloseMessage(int channel_id, Message* message) {
+void Endpoint::BuildCloseMessage(int32_t channel_id, Message* message) {
   ALOGD_IF(TRACE, "Endpoint::BuildCloseMessage: channel_id=%d", channel_id);
   MessageInfo info;
   info.pid = -1;
@@ -496,22 +519,22 @@
     auto status = AcceptConnection(message);
     if (!status)
       return status;
-    return ReenableEpollEvent(socket_fd_.Get());
+    return ReenableEpollEvent(socket_fd_.Borrow());
   }
 
-  int channel_id = event.data.fd;
+  BorrowedHandle channel_fd{event.data.fd};
   if (event.events & (EPOLLRDHUP | EPOLLHUP)) {
-    BuildCloseMessage(channel_id, message);
+    BuildCloseMessage(GetChannelId(channel_fd), message);
     return {};
   }
 
-  return ReceiveMessageForChannel(channel_id, message);
+  return ReceiveMessageForChannel(channel_fd, message);
 }
 
 Status<void> Endpoint::MessageReply(Message* message, int return_code) {
-  const int channel_id = message->GetChannelId();
-  const int channel_socket = GetChannelSocketFd(channel_id);
-  if (channel_socket < 0)
+  const int32_t channel_id = message->GetChannelId();
+  auto channel_socket = GetChannelSocketFd(channel_id);
+  if (!channel_socket)
     return ErrorStatus{EBADF};
 
   auto* state = static_cast<MessageState*>(message->GetState());
@@ -524,8 +547,7 @@
         return CloseChannel(channel_id);
       } else {
         // Reply with the event fd.
-        auto push_status = state->PushFileHandle(
-            BorrowedHandle{GetChannelEventFd(channel_socket)});
+        auto push_status = state->PushFileHandle(GetChannelEventFd(channel_id));
         state->response_data.clear();  // Just in case...
         if (!push_status)
           return push_status.error_status();
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 3f79a7b..632978b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,7 +47,7 @@
 ]
 
 sharedLibraries = [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.allocator@2.0",
     "android.hardware.graphics.composer@2.1",
     "libbinder",
@@ -76,7 +76,7 @@
     cflags: [
         "-DLOG_TAG=\"vr_flinger\"",
         "-DTRACE=0",
-	"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
         "-DGL_GLEXT_PROTOTYPES",
         "-DEGL_EGLEXT_PROTOTYPES",
     ],
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 49b6f09..99f93bf 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -2,7 +2,9 @@
 
 #include <pdx/channel_handle.h>
 #include <pdx/default_transport/service_endpoint.h>
+#include <private/android_filesystem_config.h>
 #include <private/dvr/display_rpc.h>
+#include <private/dvr/trusted_uids.h>
 #include <sys/poll.h>
 
 #include <array>
@@ -82,9 +84,9 @@
           *this, &DisplayManagerService::OnUpdateSurfaces, message);
       return {};
 
-  case DisplayManagerRPC::SetupPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-          *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+    case DisplayManagerRPC::SetupNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+          *this, &DisplayManagerService::OnSetupNamedBuffer, message);
       return {};
 
     default:
@@ -188,9 +190,20 @@
   return 0;
 }
 
-pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
-    pdx::Message& /*message*/, size_t extended_region_size, int usage) {
-  return display_service_->SetupPoseBuffer(extended_region_size, usage);
+pdx::Status<BorrowedNativeBufferHandle>
+DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
+                                          const std::string& name, size_t size,
+                                          uint64_t producer_usage,
+                                          uint64_t consumer_usage) {
+  if (message.GetEffectiveUserId() != AID_ROOT &&
+      !IsTrustedUid(message.GetEffectiveUserId())) {
+    // Only trusted users can setup named buffers.
+    ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
+          message.GetEffectiveUserId());
+    return {};
+  }
+  return display_service_->SetupNamedBuffer(name, size, producer_usage,
+                                            consumer_usage);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 80324fd..7b037de 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,9 +54,9 @@
   int OnUpdateSurfaces(pdx::Message& message,
                        const std::map<int, DisplaySurfaceAttributes>& updates);
 
-  pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
-                                               size_t extended_region_size,
-                                               int usage);
+  pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
+      pdx::Message& message, const std::string& name, size_t size,
+      uint64_t producer_usage, uint64_t consumer_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 3750ea3..8cf9d64 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,5 +1,6 @@
 #include "display_service.h"
 
+#include <unistd.h>
 #include <vector>
 
 #include <pdx/default_transport/service_endpoint.h>
@@ -18,20 +19,10 @@
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
 
-namespace {
-
-constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
-const int kPersistentPoseBufferUserId = 0;
-const int kPersistentPoseBufferGroupId = 0;
-const size_t kTimingDataSizeOffset = 128;
-
-}  // anonymous namespace
-
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService()
-    : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
 
 DisplayService::DisplayService(Hwc2::Composer* hidl)
     : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -89,9 +80,9 @@
           *this, &DisplayService::OnSetViewerParams, message);
       return {};
 
-    case DisplayRPC::GetPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
-          *this, &DisplayService::OnGetPoseBuffer, message);
+    case DisplayRPC::GetNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+          *this, &DisplayService::OnGetNamedBuffer, message);
       return {};
 
     case DisplayRPC::IsVrAppRunning::Opcode:
@@ -254,13 +245,14 @@
   compositor->UpdateHeadMountMetrics(head_mount_metrics);
 }
 
-pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
-  if (pose_buffer_) {
-    return pose_buffer_->CreateConsumer().take();
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
+    pdx::Message& /* message */, const std::string& name) {
+  auto named_buffer = named_buffers_.find(name);
+  if (named_buffer != named_buffers_.end()) {
+    return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
   }
 
-  pdx::rpc::RemoteMethodError(message, EAGAIN);
-  return {};
+  return pdx::ErrorStatus(EINVAL);
 }
 
 // Calls the message handler for the DisplaySurface associated with this
@@ -334,16 +326,22 @@
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
-pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  if (!pose_buffer_) {
-    pose_buffer_ = BufferProducer::Create(
-        kPersistentPoseBufferName, kPersistentPoseBufferUserId,
-        kPersistentPoseBufferGroupId, usage,
-        extended_region_size + kTimingDataSizeOffset);
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
+    const std::string& name, size_t size, int producer_usage,
+    int consumer_usage) {
+  auto named_buffer = named_buffers_.find(name);
+  if (named_buffer == named_buffers_.end()) {
+    // TODO(hendrikw): Update BufferProducer to take producer_usage and
+    // consumer_usage flags.
+    auto ion_buffer = std::make_unique<IonBuffer>(
+        static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB,
+        producer_usage | consumer_usage);
+    named_buffer =
+        named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+            .first;
   }
 
-  return pose_buffer_->GetChannelHandle().Borrow();
+  return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
 }
 
 void DisplayService::OnHardwareComposerRefresh() {
@@ -361,11 +359,12 @@
 }
 
 int DisplayService::IsVrAppRunning(pdx::Message& message) {
-  bool visible = true;
-  ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
-    if (surface->client_z_order() == 0 && !surface->IsVisible())
-      visible = false;
-  });
+  bool visible = false;
+  ForEachDisplaySurface(
+      [&visible](const std::shared_ptr<DisplaySurface>& surface) {
+        if (surface->client_z_order() == 0 && surface->IsVisible())
+          visible = true;
+      });
 
   REPLY_SUCCESS_RETURN(message, visible, 0);
 }
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index da80a84..db89064 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -3,6 +3,7 @@
 
 #include <pdx/service.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/display_rpc.h>
 #include <private/dvr/late_latch.h>
 
@@ -38,8 +39,9 @@
   // any change to client/manager attributes that affect visibility or z order.
   void UpdateActiveDisplaySurfaces();
 
-  pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
-                                             int usage);
+  pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
+      const std::string& name, size_t size, int producer_usage,
+      int consumer_usage);
 
   template <class A>
   void ForEachDisplaySurface(A action) const {
@@ -85,7 +87,8 @@
 
   void OnSetViewerParams(pdx::Message& message,
                          const ViewerParams& view_params);
-  pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
+  pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
+      pdx::Message& message, const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   int IsVrAppRunning(pdx::Message& message);
@@ -102,7 +105,7 @@
   HardwareComposer hardware_composer_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
-  std::unique_ptr<BufferProducer> pose_buffer_;
+  std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 542bbd9..6602d78 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1416,7 +1416,7 @@
 
 void Layer::Prepare() {
   int right, bottom;
-  buffer_handle_t handle;
+  sp<GraphicBuffer> handle;
 
   if (surface_) {
     // Only update the acquired buffer when one is either available or this is
@@ -1465,14 +1465,14 @@
     }
     right = acquired_buffer_.buffer()->width();
     bottom = acquired_buffer_.buffer()->height();
-    handle = acquired_buffer_.buffer()->native_handle();
+    handle = acquired_buffer_.buffer()->buffer()->buffer();
     acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
   } else {
     // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
     // mechanism to accept distorted layers from VrCore.
     right = direct_buffer_->width();
     bottom = direct_buffer_->height();
-    handle = direct_buffer_->handle();
+    handle = direct_buffer_->buffer();
     acquire_fence_fd_.Close();
   }
 
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
index 1bb3c4f..40b4638 100644
--- a/libs/vr/libvrsensor/include/private/dvr/latency_model.h
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -6,23 +6,21 @@
 namespace android {
 namespace dvr {
 
-// This class holds a rolling average of the sensor latency.
+// This class models the latency from sensors. It will look at the first
+// window_size measurements and return their average after that.
 class LatencyModel {
  public:
-  LatencyModel(size_t window_size, double weight_mass_in_window);
+  LatencyModel(size_t window_size);
   ~LatencyModel() = default;
 
   void AddLatency(int64_t latency_ns);
-  int64_t CurrentLatencyEstimate() const {
-    return static_cast<int64_t>(rolling_average_);
-  }
+  int64_t CurrentLatencyEstimate() const { return latency_; }
 
  private:
-  // The rolling average of the latencies.
-  double rolling_average_ = 0;
-
-  // The alpha parameter for an exponential moving average.
-  double alpha_;
+  size_t window_size_;
+  int64_t latency_sum_ = 0;
+  size_t num_summed_ = 0;
+  int64_t latency_ = 0;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrsensor/latency_model.cpp b/libs/vr/libvrsensor/latency_model.cpp
index 8233889..d3a4521 100644
--- a/libs/vr/libvrsensor/latency_model.cpp
+++ b/libs/vr/libvrsensor/latency_model.cpp
@@ -5,28 +5,19 @@
 namespace android {
 namespace dvr {
 
-LatencyModel::LatencyModel(size_t window_size, double weight_mass_in_window) {
-  // Compute an alpha so the weight of the last window_size measurements is
-  // weight_mass_in_window of the total weights.
-
-  // The weight in a series of k measurements:
-  // alpha + (1 + (1 - alpha) + (1 - alpha)^2 + ... (1 - alpha)^k-1)
-  // = alpha x (1 - (1 - alpha) ^ k) / alpha
-  // = 1 - (1 - alpha) ^ k
-  // weight_mass_in_window = 1 - (1 - alpha) ^ k / lim_k->inf (1 - alpha) ^ k
-  // weight_mass_in_window = 1 - (1 - alpha) ^ k / 1
-  // 1 - weight_mass_in_window = (1 - alpha) ^ k
-  // log(1 - weight_mass_in_window) = k * log(1 - alpha)
-  // 10 ^ (log(1 - weight_mass_in_window) / k) = 1 - alpha
-  // alpha = 1 - 10 ^ (log(1 - weight_mass_in_window) / k)
-  // alpha = 1 - 10 ^ (log(1 - weight_mass_in_window) / window_size)
-
-  alpha_ = 1 - std::pow(10.0, std::log10(1 - weight_mass_in_window) /
-                                  static_cast<double>(window_size));
-}
+LatencyModel::LatencyModel(size_t window_size) : window_size_(window_size) {}
 
 void LatencyModel::AddLatency(int64_t latency_ns) {
-  rolling_average_ = latency_ns * alpha_ + rolling_average_ * (1 - alpha_);
+  // Not enough samples yet?
+  if (num_summed_ < window_size_) {
+    // Accumulate.
+    latency_sum_ += latency_ns;
+
+    // Have enough samples for latency estimate?
+    if (++num_summed_ == window_size_) {
+      latency_ = latency_sum_ / window_size_;
+    }
+  }
 }
 
 }  // namespace dvr
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..d0996f0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -627,19 +627,21 @@
 
 #ifndef EGL_ANDROID_get_frame_timestamps
 #define EGL_ANDROID_get_frame_timestamps 1
-#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-#define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMPS_ANDROID 0x3430
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define EGL_READS_DONE_TIME_ANDROID 0x343C
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
 EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6a62e8d..a895e63 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
 
 // The headers modules are in frameworks/native/opengl/Android.bp.
 ndk_library {
-    name: "libEGL.ndk",
+    name: "libEGL",
     symbol_file: "libEGL.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv1_CM.ndk",
+    name: "libGLESv1_CM",
     symbol_file: "libGLESv1_CM.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv2.ndk",
+    name: "libGLESv2",
     symbol_file: "libGLESv2.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv3.ndk",
+    name: "libGLESv3",
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
     unversioned_until: "current",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 683e6ca..7d20ba1 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -33,6 +33,10 @@
 #include "egl_trace.h"
 #include "egldefs.h"
 
+extern "C" {
+  android_namespace_t* android_get_exported_namespace(const char*);
+}
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -106,6 +110,11 @@
     return dlopen(path, mode);
 }
 
+static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
+    ATRACE_CALL();
+    return android_dlopen_ext(path, mode, info);
+}
+
 // ----------------------------------------------------------------------------
 
 Loader::driver_t::driver_t(void* gles)
@@ -414,6 +423,27 @@
     }
     const char* const driver_absolute_path = absolutePath.c_str();
 
+    // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
+    // the original routine when the namespace does not exist or the load from
+    // the namespace fails.
+    // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
+    // sphal namespace.
+    android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+    if (sphal_namespace != NULL) {
+        const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = sphal_namespace,
+        };
+        void* dso = do_android_dlopen_ext(driver_absolute_path, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+        if (dso) {
+            ALOGD("loaded %s from sphal namespace", driver_absolute_path);
+            return dso;
+        }
+        else {
+            ALOGW("failed to load %s from sphal namespace: %s", driver_absolute_path, dlerror());
+        }
+    }
+
     void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
     if (dso == 0) {
         const char* err = dlerror();
@@ -426,11 +456,6 @@
     return dso;
 }
 
-static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
-    ATRACE_CALL();
-    return android_dlopen_ext(path, mode, info);
-}
-
 static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
     "ro.hardware.egl",
     "ro.board.platform",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b00d401..0807d1f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2166,10 +2166,15 @@
         case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
         case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
         case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
-        case EGL_DISPLAY_PRESENT_TIME_ANDROID:
         case EGL_DEQUEUE_READY_TIME_ANDROID:
         case EGL_READS_DONE_TIME_ANDROID:
             return EGL_TRUE;
+        case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
+            int value = 0;
+            window->query(window,
+                    NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
+            return value == 0 ? EGL_FALSE : EGL_TRUE;
+        }
         default:
             return EGL_FALSE;
     }
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..b8a9add 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -28,7 +28,7 @@
 
 Version
 
-    Version 1, January 13, 2017
+    Version 8, April 11, 2017
 
 Number
 
@@ -81,19 +81,21 @@
 
 New Tokens
 
-    EGL_TIMESTAMPS_ANDROID 0x314D
-    EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-    EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-    EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-    EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-    EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-    EGL_READS_DONE_TIME_ANDROID 0x3159
+    EGL_TIMESTAMPS_ANDROID 0x3430
+    EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+    EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+    EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+    EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+    EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+    EGL_READS_DONE_TIME_ANDROID 0x343C
+    EGL_TIMESTAMP_PENDING_ANDROID -2
+    EGL_TIMESTAMP_INVALID_ANDROID -1
 
 Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
 "Surface Attributes", page 43:
@@ -155,10 +157,12 @@
     limited history of timestamp data. If a query is made for a frame whose
     timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
     timestamp collection has not been enabled for the surface then
-    EGL_BAD_SURFACE is generated.  Timestamps for events that will not occur or
-    have not yet occurred will be zero. Timestamp queries that are not
-    supported will generate an EGL_BAD_PARAMETER error. If any error is
-    generated the function will return EGL_FALSE.
+    EGL_BAD_SURFACE is generated.  Timestamps for events that might still occur
+    will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+    that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+    Otherwise, the timestamp will be valid and indicate the event has occured.
+    Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+    error. If any error is generated the function will return EGL_FALSE.
 
     The application can poll for the timestamp of particular events by calling
     eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,12 @@
 
 Revision History
 
+#8 (Brian Anderson, April 11, 2017)
+    - Use reserved enumerant values.
+
+#7 (Brian Anderson, March 21, 2017)
+    - Differentiate between pending events and events that did not occur.
+
 #6 (Brian Anderson, March 16, 2017)
     - Remove DISPLAY_RETIRE_TIME_ANDROID.
 
diff --git a/opengl/specs/README b/opengl/specs/README
index e922740..cba4453 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -4,8 +4,14 @@
 The table below tracks usage of EGL enumerant values that have been reserved
 for use by Android extensions.
 
+See https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml
+for a list of all enumarant values currently reserved and registered with
+Khronos.
+
      Value                       Extension
-----------------     ----------------------------------
+================     ==================================
+0x3140 - 0x314F      Reserved block
+================     ==================================
 0x3140               EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
 0x3141               EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
 0x3142               EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
@@ -18,17 +24,23 @@
 0x314A               EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
 0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
 0x314C               EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
-0x314D               EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E               EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F               EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150               EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156               EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3159               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x315A - 0x315F      (unused)
+0x314D - 0x314F      (unused)
+
+     Value                       Extension
+================     ==================================
+0x3430 - 0x343F      Reserved block
+================     ==================================
+0x3430               EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3431               EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3432               EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3433               EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3434               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3435               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3436               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3437               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3438               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3439               EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343A               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343B               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343C               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343D - 0x343F      (unused)
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index b772450..5620496 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -12,12 +12,17 @@
     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 \
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 1b3086b..94de5af 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -16,6 +16,9 @@
 
 #include <gtest/gtest.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+
+#include <configstore/Utils.h>
 #include <utils/String8.h>
 
 #include <EGL/egl.h>
@@ -25,10 +28,31 @@
 #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);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
+    bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
+    bool atEnd = (cropExtLen + 1) < extsLen &&
+            !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
 namespace android {
 
 #define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
 
+// retrieve wide-color setting from configstore
+using namespace android::hardware::configstore;
+
+static bool hasWideColorDisplay =
+        getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
 class EGLTest : public ::testing::Test {
 protected:
     EGLDisplay mEglDisplay;
@@ -169,5 +193,75 @@
     EXPECT_GE(components[3], 8);
 }
 
+TEST_F(EGLTest, EGLConfigFP16) {
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
 
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        return;
+    }
+
+    ASSERT_TRUE(hasEglPixelFormatFloat());
+
+    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};
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(1, numConfigs);
+
+    EGLint components[4];
+
+    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_GE(components[0], 16);
+    EXPECT_GE(components[1], 16);
+    EXPECT_GE(components[2], 16);
+    EXPECT_GE(components[3], 16);
+
+    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;
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
 }
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
new file mode 100644
index 0000000..1f1340c
--- /dev/null
+++ b/services/schedulerservice/Android.bp
@@ -0,0 +1,25 @@
+cc_library_shared {
+    name: "libschedulerservicehidl",
+    srcs: [
+        "SchedulingPolicyService.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libmediautils",
+        "liblog",
+        "libutils",
+        "android.hidl.base@1.0",
+        "android.frameworks.schedulerservice@1.0",
+    ],
+    header_libs: [
+        "libcutils_headers",
+    ],
+    export_include_dirs: [
+        "include/"
+    ],
+    local_include_dirs: [
+        "include/schedulerservice/",
+    ],
+}
diff --git a/services/schedulerservice/SchedulingPolicyService.cpp b/services/schedulerservice/SchedulingPolicyService.cpp
new file mode 100644
index 0000000..1f6ed57
--- /dev/null
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 "schedulerservicehidl"
+
+#include "SchedulingPolicyService.h"
+
+#include <log/log.h>
+#include <hwbinder/IPCThreadState.h>
+#include <mediautils/SchedulingPolicyService.h>
+
+namespace android {
+namespace frameworks {
+namespace schedulerservice {
+namespace V1_0 {
+namespace implementation {
+
+bool SchedulingPolicyService::isAllowed() {
+    // TODO(b/37291237)
+    return true;
+}
+
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
+    if (priority < static_cast<int32_t>(Priority::MIN) ||
+            priority > static_cast<int32_t>(Priority::MAX)) {
+        return false;
+    }
+
+    if (!isAllowed()) {
+        return false;
+    }
+
+    // TODO(b/37226359): decouple from and remove AIDL service
+    // this should always be allowed since we are in system_server.
+    int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
+    return value == 0 /* success */;
+}
+
+Return<int32_t> SchedulingPolicyService::getMaxAllowedPriority() {
+    if (!isAllowed()) {
+        return 0;
+    }
+
+    // TODO(b/37226359): decouple from and remove AIDL service
+    return 3;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace schedulerservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
new file mode 100644
index 0000000..7d1c478
--- /dev/null
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -0,0 +1,50 @@
+/*
+ * 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 <android/frameworks/schedulerservice/1.0/ISchedulingPolicyService.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace frameworks {
+namespace schedulerservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct SchedulingPolicyService : public ISchedulingPolicyService {
+    Return<bool> requestPriority(int32_t pid, int32_t tid, int32_t priority) override;
+    Return<int32_t> getMaxAllowedPriority() override;
+private:
+    bool isAllowed();
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace schedulerservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8fc4921..4d76272 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,23 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include <cutils/properties.h>
-
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
-
 #include <cutils/ashmem.h>
-#include <sensor/SensorEventQueue.h>
-
+#include <cutils/properties.h>
 #include <hardware/sensors.h>
 #include <hardware_legacy/power.h>
-
 #include <openssl/digest.h>
 #include <openssl/hmac.h>
 #include <openssl/rand.h>
+#include <sensor/SensorEventQueue.h>
+#include <utils/SystemClock.h>
 
 #include "BatteryService.h"
 #include "CorrectedGyroSensor.h"
@@ -77,7 +73,8 @@
 #define SENSOR_SERVICE_SCHED_FIFO_PRIORITY 10
 
 // Permissions.
-static const String16 sDump("android.permission.DUMP");
+static const String16 sDumpPermission("android.permission.DUMP");
+static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
 
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -319,7 +316,7 @@
 
 status_t SensorService::dump(int fd, const Vector<String16>& args) {
     String8 result;
-    if (!PermissionCache::checkCallingPermission(sDump)) {
+    if (!PermissionCache::checkCallingPermission(sDumpPermission)) {
         result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
@@ -1032,6 +1029,84 @@
     return conn;
 }
 
+int SensorService::setOperationParameter(
+            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)) {
+        return PERMISSION_DENIED;
+    }
+
+    bool isFloat = true;
+    size_t expectSize = INT32_MAX;
+    switch (type) {
+        case AINFO_LOCAL_GEOMAGNETIC_FIELD:
+            isFloat = true;
+            expectSize = 3;
+            break;
+        case AINFO_LOCAL_GRAVITY:
+            isFloat = true;
+            expectSize = 1;
+            break;
+        case AINFO_DOCK_STATE:
+        case AINFO_HIGH_PERFORMANCE_MODE:
+        case AINFO_MAGNETIC_FIELD_CALIBRATION:
+            isFloat = false;
+            expectSize = 1;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    // three events: first one is begin tag, last one is end tag, the one in the middle
+    // is the payload.
+    sensors_event_t event[3];
+    int64_t timestamp = elapsedRealtimeNano();
+    for (sensors_event_t* i = event; i < event + 3; i++) {
+        *i = (sensors_event_t) {
+            .version = sizeof(sensors_event_t),
+            .sensor = 0,
+            .type = SENSOR_TYPE_ADDITIONAL_INFO,
+            .timestamp = timestamp++,
+            .additional_info = (additional_info_event_t) {
+                .serial = 0
+            }
+        };
+    }
+
+    event[0].additional_info.type = AINFO_BEGIN;
+    event[1].additional_info.type = type;
+    event[2].additional_info.type = AINFO_END;
+
+    if (isFloat) {
+        if (floats.size() != expectSize) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < expectSize; ++i) {
+            event[1].additional_info.data_float[i] = floats[i];
+        }
+    } else {
+        if (ints.size() != expectSize) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < expectSize; ++i) {
+            event[1].additional_info.data_int32[i] = ints[i];
+        }
+    }
+
+    SensorDevice& dev(SensorDevice::getInstance());
+    for (sensors_event_t* i = event; i < event + 3; i++) {
+        int ret = dev.injectSensorData(i);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+    }
+    return NO_ERROR;
+}
+
 status_t SensorService::resetToNormalMode() {
     Mutex::Autolock _l(mLock);
     return resetToNormalModeLocked();
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index d0be121..2a9d6e8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -158,6 +158,8 @@
     virtual int isDataInjectionEnabled();
     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);
     virtual status_t dump(int fd, const Vector<String16>& args);
 
     String8 getSensorName(int handle) const;
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
index 773ce8c..adc4675 100644
--- a/services/sensorservice/hidl/DirectReportChannel.cpp
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -31,10 +31,13 @@
 }
 
 // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+Return<void> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate,
+        configure_cb _hidl_cb) {
     int token = mManager.configureDirectChannel(mId,
             static_cast<int>(sensorHandle), static_cast<int>(rate));
-    return token <= 0 ? convertResult(token) : Result::OK;
+    _hidl_cb(token <= 0 ? 0 : token,
+             token <= 0 ? convertResult(token) : Result::OK);
+    return Void();
 }
 
 
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
index 9134944..dd67827 100644
--- a/services/sensorservice/hidl/DirectReportChannel.h
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -47,7 +47,8 @@
     ~DirectReportChannel();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-    Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+    Return<void> configure(int32_t sensorHandle, RateLevel rate,
+            configure_cb _hidl_cb) override;
 
 private:
     ::android::SensorManager& mManager;
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index 86d365c..c0365e5 100644
--- a/services/sensorservice/hidl/EventQueue.cpp
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -39,7 +39,8 @@
 
         while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
             internalQueue->sendAck(&event, actual);
-            mCallback->onEvent(convertEvent(event));
+            Return<void> ret = mCallback->onEvent(convertEvent(event));
+            (void)ret.isOk(); // ignored
         }
 
         return 1; // continue to receive callbacks
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 0743fc3..06ff95c 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -22,12 +22,14 @@
 
 #include "SensorManager.h"
 
+#include <sched.h>
+
+#include <thread>
+
 #include "EventQueue.h"
 #include "DirectReportChannel.h"
 #include "utils.h"
 
-#include <thread>
-
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -131,6 +133,14 @@
         std::condition_variable looperSet;
 
         std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+
+            struct sched_param p = {0};
+            p.sched_priority = 10;
+            if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
+                LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
+                        << strerror(errno);
+            }
+
             std::unique_lock<std::mutex> lock(mutex);
             looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
             lock.unlock();
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index b540525..2f9e922 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -63,6 +63,8 @@
             return Result::NO_MEMORY;
         case NO_INIT:
             return Result::NO_INIT;
+        case PERMISSION_DENIED:
+            return Result::PERMISSION_DENIED;
         case BAD_VALUE:
             return Result::BAD_VALUE;
         case INVALID_OPERATION:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index ebf72bc..7bb20ba 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -74,7 +74,7 @@
     libvrflinger
 
 LOCAL_SHARED_LIBRARIES := \
-    android.dvr.composer@1.0 \
+    android.frameworks.vr.composer@1.0 \
     android.hardware.graphics.allocator@2.0 \
     android.hardware.graphics.composer@2.1 \
     android.hardware.configstore@1.0 \
@@ -133,10 +133,15 @@
     main_surfaceflinger.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+    android.hardware.configstore@1.0 \
+    android.hardware.configstore-utils \
+    android.hardware.graphics.allocator@2.0 \
     libsurfaceflinger \
     libcutils \
     liblog \
     libbinder \
+    libhidlbase \
+    libhidltransport \
     libutils \
     libui \
     libgui \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c3b48ca..b5ffc60 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -80,6 +80,7 @@
 
 uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
 
+// clang-format off
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
@@ -91,7 +92,8 @@
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer,
-        EGLConfig config)
+        EGLConfig config,
+        bool supportWideColor)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
       mType(type),
@@ -113,12 +115,16 @@
       mPowerMode(HWC_POWER_MODE_OFF),
       mActiveConfig(0)
 {
+    // clang-format on
     Surface* surface;
     mNativeWindow = surface = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
 #ifdef USE_HWC2
     mActiveColorMode = static_cast<android_color_mode_t>(-1);
+    mDisplayHasWideColor = supportWideColor;
+#else
+    (void) supportWideColor;
 #endif
     /*
      * Create our display's surface
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index caa7adc..e2852a7 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -83,6 +83,7 @@
         NO_LAYER_STACK = 0xFFFFFFFF,
     };
 
+    // clang-format off
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
@@ -94,7 +95,9 @@
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
             const sp<IGraphicBufferProducer>& producer,
-            EGLConfig config);
+            EGLConfig config,
+            bool supportWideColor);
+    // clang-format on
 
     ~DisplayDevice();
 
@@ -146,6 +149,7 @@
     status_t beginFrame(bool mustRecompose) const;
 #ifdef USE_HWC2
     status_t prepareFrame(HWComposer& hwc);
+    bool getWideColorSupport() const { return mDisplayHasWideColor; }
 #else
     status_t prepareFrame(const HWComposer& hwc) const;
 #endif
@@ -264,6 +268,11 @@
 #ifdef USE_HWC2
     // current active color mode
     android_color_mode_t mActiveColorMode;
+
+    // Need to know if display is wide-color capable or not.
+    // Initialized by SurfaceFlinger when the DisplayDevice is created.
+    // Fed to RenderEngine during composition.
+    bool mDisplayHasWideColor;
 #endif
 };
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index d9bddb5..262ab62 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,6 @@
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
 
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
 #include <inttypes.h>
 #include <log/log.h>
 #include <gui/BufferQueue.h>
@@ -26,7 +25,6 @@
 
 namespace android {
 
-using dvr::composer::V1_0::IVrComposerClient;
 using hardware::Return;
 using hardware::hidl_vec;
 using hardware::hidl_handle;
@@ -124,6 +122,41 @@
     endCommand();
 }
 
+void Composer::CommandWriter::setClientTargetMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetClientTargetMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
+        kSetClientTargetMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::setLayerBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetLayerBufferMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
+        kSetLayerBufferMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::writeBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    write(metadata.width);
+    write(metadata.height);
+    write(metadata.stride);
+    write(metadata.layerCount);
+    writeSigned(static_cast<int32_t>(metadata.format));
+    write64(metadata.usage);
+}
+
 Composer::Composer(bool useVrComposer)
     : mWriter(kWriterInitialSize),
       mIsUsingVrComposer(useVrComposer)
@@ -426,12 +459,29 @@
 }
 
 Error Composer::setClientTarget(Display display, uint32_t slot,
-        const native_handle_t* target,
+        const sp<GraphicBuffer>& target,
         int acquireFence, Dataspace dataspace,
         const std::vector<IComposerClient::Rect>& damage)
 {
     mWriter.selectDisplay(display);
-    mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
+    if (mIsUsingVrComposer && target.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = target->getWidth(),
+            .height = target->getHeight(),
+            .stride = target->getStride(),
+            .layerCount = target->getLayerCount(),
+            .format = static_cast<PixelFormat>(target->getPixelFormat()),
+            .usage = target->getUsage(),
+        };
+        mWriter.setClientTargetMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (target.get()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
     return Error::NONE;
 }
 
@@ -502,11 +552,28 @@
 }
 
 Error Composer::setLayerBuffer(Display display, Layer layer,
-        uint32_t slot, const native_handle_t* buffer, int acquireFence)
+        uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
 {
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
-    mWriter.setLayerBuffer(slot, buffer, acquireFence);
+    if (mIsUsingVrComposer && buffer.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = buffer->getWidth(),
+            .height = buffer->getHeight(),
+            .stride = buffer->getStride(),
+            .layerCount = buffer->getLayerCount(),
+            .format = static_cast<PixelFormat>(buffer->getPixelFormat()),
+            .usage = buffer->getUsage(),
+        };
+        mWriter.setLayerBufferMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (buffer.get()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
+    mWriter.setLayerBuffer(slot, handle, acquireFence);
     return Error::NONE;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 18af9dd..37b7766 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,6 +23,7 @@
 #include <utility>
 #include <vector>
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <utils/StrongPointer.h>
 #include <IComposerCommandBuffer.h>
@@ -31,6 +32,8 @@
 
 namespace Hwc2 {
 
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Dataspace;
@@ -179,7 +182,7 @@
      * When target is not nullptr, the cache is updated with the new target.
      */
     Error setClientTarget(Display display, uint32_t slot,
-            const native_handle_t* target,
+            const sp<GraphicBuffer>& target,
             int acquireFence, Dataspace dataspace,
             const std::vector<IComposerClient::Rect>& damage);
     Error setColorMode(Display display, ColorMode mode);
@@ -199,7 +202,7 @@
             int32_t x, int32_t y);
     /* see setClientTarget for the purpose of slot */
     Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
-            const native_handle_t* buffer, int acquireFence);
+            const sp<GraphicBuffer>& buffer, int acquireFence);
     Error setLayerSurfaceDamage(Display display, Layer layer,
             const std::vector<IComposerClient::Rect>& damage);
     Error setLayerBlendMode(Display display, Layer layer,
@@ -232,6 +235,14 @@
         ~CommandWriter() override;
 
         void setLayerInfo(uint32_t type, uint32_t appId);
+        void setClientTargetMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+        void setLayerBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+
+    private:
+        void writeBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
     };
 
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e49e734..8270c39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -244,7 +244,7 @@
         ALOGE("Failed to get display by id");
         return Error::BadDisplay;
     }
-    (*outDisplay)->setVirtual();
+    (*outDisplay)->setConnected(true);
     return Error::None;
 }
 
@@ -531,15 +531,28 @@
   : mDevice(device),
     mId(id),
     mIsConnected(false),
-    mIsVirtual(false)
+    mType(DisplayType::Invalid)
 {
     ALOGV("Created display %" PRIu64, id);
+
+#ifdef BYPASS_IHWC
+    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+            reinterpret_cast<int32_t *>(&mType));
+#else
+    auto intError = mDevice.mComposer->getDisplayType(mId,
+            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
+#endif
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
+              id, to_string(error).c_str(), intError);
+    }
 }
 
 Display::~Display()
 {
     ALOGV("Destroyed display %" PRIu64, mId);
-    if (mIsVirtual) {
+    if (mType == DisplayType::Virtual) {
         mDevice.destroyVirtualDisplay(mId);
     }
 }
@@ -802,21 +815,7 @@
 
 Error Display::getType(DisplayType* outType) const
 {
-#ifdef BYPASS_IHWC
-    int32_t intType = 0;
-    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
-            &intType);
-#else
-    Hwc2::IComposerClient::DisplayType intType =
-        Hwc2::IComposerClient::DisplayType::INVALID;
-    auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
-#endif
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    *outType = static_cast<DisplayType>(intType);
+    *outType = mType;
     return Error::None;
 }
 
@@ -961,14 +960,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
         const sp<Fence>& acquireFence, android_dataspace_t dataspace)
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
-    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+    buffer_handle_t handle = nullptr;
+    if (target.get() && target->getNativeBuffer()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
             fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
 #else
     auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
@@ -1195,14 +1199,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
+    buffer_handle_t handle = nullptr;
+    if (buffer.get() && buffer->getNativeBuffer()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
     int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
-            mId, buffer, fenceFd);
+            mId, handle, fenceFd);
 #else
     auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
             mId, slot, buffer, fenceFd);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4419dc1..643b1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -329,7 +329,7 @@
     [[clang::warn_unused_result]] Error setActiveConfig(
             const std::shared_ptr<const Config>& config);
     [[clang::warn_unused_result]] Error setClientTarget(
-            uint32_t slot, buffer_handle_t target,
+            uint32_t slot, const android::sp<android::GraphicBuffer>& target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
     [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -352,12 +352,6 @@
 private:
     // For use by Device
 
-    // Virtual displays are always connected
-    void setVirtual() {
-        mIsVirtual = true;
-        mIsConnected = true;
-    }
-
     void setConnected(bool connected) { mIsConnected = connected; }
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
     void loadConfig(hwc2_config_t configId);
@@ -375,7 +369,7 @@
     Device& mDevice;
     hwc2_display_t mId;
     bool mIsConnected;
-    bool mIsVirtual;
+    DisplayType mType;
     std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
 };
@@ -392,7 +386,7 @@
 
     [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
     [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
-            buffer_handle_t buffer,
+            const android::sp<android::GraphicBuffer>& buffer,
             const android::sp<android::Fence>& acquireFence);
     [[clang::warn_unused_result]] Error setSurfaceDamage(
             const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 09434f6..40979c9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -206,7 +206,7 @@
         }
         disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-    mEventHandler->onHotplugReceived(disp,
+    mEventHandler->onHotplugReceived(this, disp,
             connected == HWC2::Connection::Connected);
 }
 
@@ -465,12 +465,7 @@
 
     ALOGV("setClientTarget for display %d", displayId);
     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    buffer_handle_t handle = nullptr;
-    if ((target != nullptr) && target->getNativeBuffer()) {
-        handle = target->getNativeBuffer()->handle;
-    }
-    auto error = hwcDisplay->setClientTarget(slot, handle,
-            acquireFence, dataspace);
+    auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
     if (error != HWC2::Error::None) {
         ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 81f1619..78d0307 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -70,7 +70,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 5b5f1cf..dcb2913 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -315,7 +315,7 @@
     queryDisplayProperties(disp);
     // Do not teardown or recreate the primary display
     if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(disp, bool(connected));
+        mEventHandler.onHotplugReceived(this, disp, bool(connected));
     }
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f64d69a..4bc63bb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -62,7 +62,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 486bce4..a9bb2ba 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -21,7 +21,6 @@
 
 #include <cutils/compiler.h>
 
-#include <private/gui/BitTube.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/DisplayEventReceiver.h>
 
@@ -389,7 +388,7 @@
 
 EventThread::Connection::Connection(
         const sp<EventThread>& eventThread)
-    : count(-1), mEventThread(eventThread), mChannel(new BitTube())
+    : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
 {
 }
 
@@ -403,12 +402,14 @@
     mEventThread->registerDisplayEventConnection(this);
 }
 
-sp<BitTube> EventThread::Connection::getDataChannel() const {
-    return mChannel;
+status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
+    outChannel->setReceiveFd(mChannel.moveReceiveFd());
+    return NO_ERROR;
 }
 
-void EventThread::Connection::setVsyncRate(uint32_t count) {
+status_t EventThread::Connection::setVsyncRate(uint32_t count) {
     mEventThread->setVsyncRate(count, this);
+    return NO_ERROR;
 }
 
 void EventThread::Connection::requestNextVsync() {
@@ -417,7 +418,7 @@
 
 status_t EventThread::Connection::postEvent(
         const DisplayEventReceiver::Event& event) {
-    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
+    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 3f1d0bb..6a59fbb 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <private/gui/BitTube.h>
 #include <gui/DisplayEventReceiver.h>
 #include <gui/IDisplayEventConnection.h>
 
@@ -68,11 +69,11 @@
     private:
         virtual ~Connection();
         virtual void onFirstRef();
-        virtual sp<BitTube> getDataChannel() const;
-        virtual void setVsyncRate(uint32_t count);
-        virtual void requestNextVsync();    // asynchronous
+        status_t stealReceiveChannel(gui::BitTube* outChannel) override;
+        status_t setVsyncRate(uint32_t count) override;
+        void requestNextVsync() override;    // asynchronous
         sp<EventThread> const mEventThread;
-        sp<BitTube> const mChannel;
+        gui::BitTube mChannel;
     };
 
 public:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 16d8160..027fae6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -852,18 +852,12 @@
     }
 
     uint32_t hwcSlot = 0;
-    buffer_handle_t hwcHandle = nullptr;
-    {
-        sp<GraphicBuffer> hwcBuffer;
-        hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
-                &hwcSlot, &hwcBuffer);
-        if (hwcBuffer != nullptr) {
-            hwcHandle = hwcBuffer->handle;
-        }
-    }
+    sp<GraphicBuffer> hwcBuffer;
+    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+            &hwcSlot, &hwcBuffer);
 
     auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-    error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
+    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
                 mActiveBuffer->handle, to_string(error).c_str(),
@@ -1011,6 +1005,9 @@
     return inverse(tr);
 }
 
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
         bool useIdentityTransform) const
 {
@@ -1172,6 +1169,9 @@
 
     RenderEngine& engine(mFlinger->getRenderEngine());
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
+#ifdef USE_HWC2
+    engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
     engine.drawMesh(mMesh);
     engine.disableBlending();
 }
@@ -1713,10 +1713,55 @@
     mCurrentState.sequence++;
     mCurrentState.z = z;
     mCurrentState.modified = true;
+
+    // Discard all relative layering.
+    if (mCurrentState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+        if (strongRelative != nullptr) {
+            strongRelative->removeZOrderRelative(this);
+        }
+        mCurrentState.zOrderRelativeOf = nullptr;
+    }
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
+void Layer::removeZOrderRelative(const wp<Layer>& relative) {
+    mCurrentState.zOrderRelatives.remove(relative);
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+}
+
+void Layer::addZOrderRelative(const wp<Layer>& relative) {
+    mCurrentState.zOrderRelatives.add(relative);
+    mCurrentState.modified = true;
+    mCurrentState.sequence++;
+    setTransactionFlags(eTransactionNeeded);
+}
+
+bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) {
+    sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
+    if (handle == nullptr) {
+        return false;
+    }
+    sp<Layer> relative = handle->owner.promote();
+    if (relative == nullptr) {
+        return false;
+    }
+
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    mCurrentState.z = z;
+
+    mCurrentState.zOrderRelativeOf = relative;
+    relative->addZOrderRelative(this);
+
+    setTransactionFlags(eTransactionNeeded);
+
+    return true;
+}
+
 bool Layer::setSize(uint32_t w, uint32_t h) {
     if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
         return false;
@@ -2500,40 +2545,70 @@
     return mDrawingState.z;
 }
 
+LayerVector Layer::makeTraversalList() {
+    if (mDrawingState.zOrderRelatives.size() == 0) {
+        return mDrawingChildren;
+    }
+    LayerVector traverse;
+
+    for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+        sp<Layer> strongRelative = weakRelative.promote();
+        if (strongRelative != nullptr) {
+            traverse.add(strongRelative);
+        } else {
+            // We need to erase from current state instead of drawing
+            // state so we don't overwrite when copying
+            // the current state to the drawing state.
+            mCurrentState.zOrderRelatives.remove(weakRelative);
+        }
+    }
+
+    for (const sp<Layer>& child : mDrawingChildren) {
+        traverse.add(child);
+    }
+
+    return traverse;
+}
+
 /**
- * Negatively signed children are before 'this' in Z-order.
+ * Negatively signed relatives are before 'this' in Z-order.
  */
 void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
+    LayerVector list = makeTraversalList();
+
     size_t i = 0;
-    for (; i < mDrawingChildren.size(); i++) {
-        const auto& child = mDrawingChildren[i];
-        if (child->getZ() >= 0)
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
+        if (relative->getZ() >= 0) {
             break;
-        child->traverseInZOrder(exec);
+        }
+        relative->traverseInZOrder(exec);
     }
     exec(this);
-    for (; i < mDrawingChildren.size(); i++) {
-        const auto& child = mDrawingChildren[i];
-        child->traverseInZOrder(exec);
+    for (; i < list.size(); i++) {
+        const auto& relative = list[i];
+        relative->traverseInZOrder(exec);
     }
 }
 
 /**
- * Positively signed children are before 'this' in reverse Z-order.
+ * Positively signed relatives are before 'this' in reverse Z-order.
  */
 void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
+    LayerVector list = makeTraversalList();
+
     int32_t i = 0;
-    for (i = mDrawingChildren.size()-1; i>=0; i--) {
-        const auto& child = mDrawingChildren[i];
-        if (child->getZ() < 0) {
+    for (i = list.size()-1; i>=0; i--) {
+        const auto& relative = list[i];
+        if (relative->getZ() < 0) {
             break;
         }
-        child->traverseInReverseZOrder(exec);
+        relative->traverseInReverseZOrder(exec);
     }
     exec(this);
     for (; i>=0; i--) {
-        const auto& child = mDrawingChildren[i];
-        child->traverseInReverseZOrder(exec);
+        const auto& relative = list[i];
+        relative->traverseInReverseZOrder(exec);
     }
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e21be8b..a5224ec 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@
 
         uint32_t appId;
         uint32_t type;
+
+        // If non-null, a Surface this Surface's Z-order is interpreted relative to.
+        wp<Layer> zOrderRelativeOf;
+
+        // A list of surfaces whose Z-order is interpreted relative to ours.
+        SortedVector<wp<Layer>> zOrderRelatives;
     };
 
     // -----------------------------------------------------------------------
@@ -173,6 +179,8 @@
     bool setFinalCrop(const Rect& crop, bool immediate);
 
     bool setLayer(int32_t z);
+    bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+
     bool setSize(uint32_t w, uint32_t h);
 #ifdef USE_HWC2
     bool setAlpha(float alpha);
@@ -549,6 +557,10 @@
 
     void setParent(const sp<Layer>& layer);
 
+    LayerVector makeTraversalList();
+    void addZOrderRelative(const wp<Layer>& relative);
+    void removeZOrderRelative(const wp<Layer>& relative);
+
     // -----------------------------------------------------------------------
 
     class SyncPoint
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 7ba6ad3..90e6395 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@
 
 void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
     for (size_t i = 0; i < size(); i++) {
-        (*this)[i]->traverseInZOrder(consume);
+        const auto& layer = (*this)[i];
+        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        layer->traverseInZOrder(consume);
     }
 }
 
 void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
     for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
-        (*this)[i]->traverseInReverseZOrder(consume);
+        const auto& layer = (*this)[i];
+        if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        layer->traverseInReverseZOrder(consume);
      }
 }
 } // namespace android
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index debea58..bca3430 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -25,7 +25,6 @@
 #include <utils/Log.h>
 
 #include <gui/IDisplayEventConnection.h>
-#include <private/gui/BitTube.h>
 
 #include "MessageQueue.h"
 #include "EventThread.h"
@@ -94,8 +93,8 @@
 {
     mEventThread = eventThread;
     mEvents = eventThread->createEventConnection();
-    mEventTube = mEvents->getDataChannel();
-    mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
+    mEvents->stealReceiveChannel(&mEventTube);
+    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
             MessageQueue::cb_eventReceiver, this);
 }
 
@@ -150,7 +149,7 @@
 int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
     ssize_t n;
     DisplayEventReceiver::Event buffer[8];
-    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
+    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
         for (int i=0 ; i<n ; i++) {
             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                 mHandler->dispatchInvalidate();
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index aed0aa9..85a33c8 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -25,6 +25,7 @@
 #include <utils/Timers.h>
 #include <utils/Looper.h>
 
+#include <private/gui/BitTube.h>
 #include <gui/DisplayEventReceiver.h>
 
 #include "Barrier.h"
@@ -81,7 +82,7 @@
     sp<Looper> mLooper;
     sp<EventThread> mEventThread;
     sp<IDisplayEventConnection> mEvents;
-    sp<BitTube> mEventTube;
+    gui::BitTube mEventTube;
     sp<Handler> mHandler;
 
 
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 406e611..04fe182 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -14,11 +14,16 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
 #include <ui/Rect.h>
 
 #include <utils/String8.h>
@@ -35,6 +40,73 @@
 #include "Mesh.h"
 #include "Texture.h"
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+#include <fstream>
+
+// ---------------------------------------------------------------------------
+#ifdef USE_HWC2
+bool checkGlError(const char* op, int lineNumber) {
+    bool errorFound = false;
+    GLint error = glGetError();
+    while (error != GL_NO_ERROR) {
+        errorFound = true;
+        error = glGetError();
+        ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
+    }
+    return errorFound;
+}
+
+static constexpr bool outputDebugPPMs = false;
+
+void writePPM(const char* basename, GLuint width, GLuint height) {
+    ALOGV("writePPM #%s: %d x %d", basename, width, height);
+
+    std::vector<GLubyte> pixels(width * height * 4);
+    std::vector<GLubyte> outBuffer(width * height * 3);
+
+    // TODO(courtneygo): We can now have float formats, need
+    // to remove this code or update to support.
+    // Make returned pixels fit in uint32_t, one byte per component
+    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+    if (checkGlError(__FUNCTION__, __LINE__)) {
+        return;
+    }
+
+    std::string filename(basename);
+    filename.append(".ppm");
+    std::ofstream file(filename.c_str(), std::ios::binary);
+    if (!file.is_open()) {
+        ALOGE("Unable to open file: %s", filename.c_str());
+        ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
+              "surfaceflinger to write debug images");
+        return;
+    }
+
+    file << "P6\n";
+    file << width << "\n";
+    file << height << "\n";
+    file << 255 << "\n";
+
+    auto ptr = reinterpret_cast<char*>(pixels.data());
+    auto outPtr = reinterpret_cast<char*>(outBuffer.data());
+    for (int y = height - 1; y >= 0; y--) {
+        char* data = ptr + y * width * sizeof(uint32_t);
+
+        for (GLuint x = 0; x < width; x++) {
+            // Only copy R, G and B components
+            outPtr[0] = data[0];
+            outPtr[1] = data[1];
+            outPtr[2] = data[2];
+            data += sizeof(uint32_t);
+            outPtr += 3;
+        }
+    }
+    file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
+}
+#endif
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -59,6 +131,28 @@
             GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
 
     //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();
+
+        // color transform needs to be transposed and 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));
+        mSrgbToDisplayP3 = gamutTransform;
+    }
+#endif
 }
 
 GLES20RenderEngine::~GLES20RenderEngine() {
@@ -170,6 +264,42 @@
     }
 }
 
+#ifdef USE_HWC2
+void GLES20RenderEngine::setColorMode(android_color_mode mode) {
+    ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
+
+    if (mColorMode == mode) return;
+
+    if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB ||
+        mode == HAL_COLOR_MODE_NATIVE) {
+        // We are returning back to our default color_mode
+        mUseWideColor = false;
+        mWideColorFrameCount = 0;
+    } else {
+        mUseWideColor = true;
+    }
+
+    mColorMode = mode;
+}
+
+void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
+    if (source == HAL_DATASPACE_UNKNOWN) {
+        // Treat UNKNOWN as SRGB
+        source = HAL_DATASPACE_V0_SRGB;
+    }
+    mDataSpace = source;
+}
+
+void GLES20RenderEngine::setWideColor(bool hasWideColor) {
+    ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
+    mDisplayHasWideColor = hasWideColor;
+}
+
+bool GLES20RenderEngine::usesWideColor() {
+    return mUseWideColor;
+}
+#endif
+
 void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
     GLuint target = texture.getTextureTarget();
     glBindTexture(target, texture.getTextureName());
@@ -242,8 +372,6 @@
 
 void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
 
-    ProgramCache::getInstance().useProgram(mState);
-
     if (mesh.getTexCoordsSize()) {
         glEnableVertexAttribArray(Program::texCoords);
         glVertexAttribPointer(Program::texCoords,
@@ -259,7 +387,32 @@
             mesh.getByteStride(),
             mesh.getPositions());
 
+#ifdef USE_HWC2
+    if (usesWideColor()) {
+        Description wideColorState = mState;
+        if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
+            wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+            ALOGV("drawMesh: gamut transform applied");
+        }
+        ProgramCache::getInstance().useProgram(wideColorState);
+
+        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+        if (outputDebugPPMs) {
+            std::ostringstream out;
+            out << "/data/texture_out" << mWideColorFrameCount++;
+            writePPM(out.str().c_str(), mVpWidth, mVpHeight);
+        }
+    } else {
+        ProgramCache::getInstance().useProgram(mState);
+
+        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+    }
+#else
+    ProgramCache::getInstance().useProgram(mState);
+
     glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+#endif
 
     if (mesh.getTexCoordsSize()) {
         glDisableVertexAttribArray(Program::texCoords);
@@ -268,6 +421,13 @@
 
 void GLES20RenderEngine::dump(String8& result) {
     RenderEngine::dump(result);
+#ifdef USE_HWC2
+    if (usesWideColor()) {
+        result.append("Wide-color: On\n");
+    } else {
+        result.append("Wide-color: Off\n");
+    }
+#endif
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 7c3f9b5..19cbb60 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,6 +72,27 @@
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
             float alpha) override;
     virtual void setupDimLayerBlending(float alpha) override;
+
+    // Color management related functions and state
+    void setColorMode(android_color_mode mode);
+    void setSourceDataSpace(android_dataspace source);
+    void setWideColor(bool hasWideColor);
+    bool usesWideColor();
+
+    // Current color mode of display using the render engine
+    android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE;
+
+    // Current dataspace of layer being rendered
+    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;
+
+    // Currently only supporting sRGB and DisplayP3 color spaces
+    mat4 mSrgbToDisplayP3;
 #else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
             int alpha);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index d19137b..8b031bc 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -98,6 +98,10 @@
 #ifdef USE_HWC2
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
     virtual void setupDimLayerBlending(float alpha) = 0;
+    virtual void setColorMode(android_color_mode mode) = 0;
+    virtual void setSourceDataSpace(android_dataspace source) = 0;
+    virtual void setWideColor(bool hasWideColor) = 0;
+    virtual bool usesWideColor() = 0;
 #else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 834c1c4..18a7818 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
 
 #include <dvr/vr_flinger.h>
 
+#include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 
@@ -119,6 +120,7 @@
 bool SurfaceFlinger::hasSyncFramework;
 bool SurfaceFlinger::useVrFlinger;
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+bool SurfaceFlinger::hasWideColorDisplay;
 
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(),
@@ -189,6 +191,9 @@
     maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
             &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
 
+    hasWideColorDisplay =
+            getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
 
@@ -573,6 +578,14 @@
 
     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");
+    }
+
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
             mVrFlingerRequestsDisplay = requestDisplay;
@@ -593,7 +606,7 @@
 
     // make the GLContext current so that we can create textures when creating
     // Layers (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -646,6 +659,25 @@
     return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+        std::vector<FrameEvent>* outSupported) const {
+    *outSupported = {
+        FrameEvent::REQUESTED_PRESENT,
+        FrameEvent::ACQUIRE,
+        FrameEvent::LATCH,
+        FrameEvent::FIRST_REFRESH_START,
+        FrameEvent::LAST_REFRESH_START,
+        FrameEvent::GPU_COMPOSITION_DONE,
+        FrameEvent::DEQUEUE_READY,
+        FrameEvent::RELEASE,
+    };
+    if (!getHwComposer().hasCapability(
+            HWC2::Capability::PresentFenceIsNotReliable)) {
+        outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+    }
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
     if ((configs == NULL) || (display.get() == NULL)) {
@@ -709,8 +741,11 @@
             info.density = density;
 
             // TODO: this needs to go away (currently needed only by webkit)
-            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-            info.orientation = hw->getOrientation();
+            {
+                Mutex::Autolock _l(mStateLock);
+                sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
+                info.orientation = hw->getOrientation();
+            }
         } else {
             // TODO: where should this value come from?
             static const int TV_DENSITY = 213;
@@ -767,10 +802,13 @@
         ALOGE("%s : display is NULL", __func__);
         return BAD_VALUE;
     }
+
+    Mutex::Autolock _l(mStateLock);
     sp<DisplayDevice> device(getDisplayDevice(display));
     if (device != NULL) {
         return device->getActiveConfig();
     }
+
     return BAD_VALUE;
 }
 
@@ -858,6 +896,7 @@
 }
 
 android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    Mutex::Autolock _l(mStateLock);
     sp<DisplayDevice> device(getDisplayDevice(display));
     if (device != nullptr) {
         return device->getActiveColorMode();
@@ -867,13 +906,10 @@
 
 void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
         android_color_mode_t mode) {
-    ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
-          this);
     int32_t type = hw->getDisplayType();
     android_color_mode_t currentMode = hw->getActiveColorMode();
 
     if (mode == currentMode) {
-        ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
         return;
     }
 
@@ -882,6 +918,9 @@
         return;
     }
 
+    ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
+          hw->getDisplayType());
+
     hw->setActiveColorMode(mode);
     getHwComposer().setActiveColorMode(type, mode);
 }
@@ -902,17 +941,17 @@
             mFlinger.getDisplayColorModes(mDisplay, &modes);
             bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
             if (mMode < 0 || !exists) {
-                ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
-                        mDisplay.get());
+                ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
+                      decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
                 return true;
             }
             sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
             if (hw == nullptr) {
-                ALOGE("Attempt to set active color mode = %d for null display %p",
-                        mMode, mDisplay.get());
+                ALOGE("Attempt to set active color mode %s (%d) for null display %p",
+                      decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
             } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
-                ALOGW("Attempt to set active color mode= %d for virtual display",
-                        mMode);
+                ALOGW("Attempt to set active color mode %s %d for virtual display",
+                      decodeColorMode(mMode).c_str(), mMode);
             } else {
                 mFlinger.setActiveColorModeInternal(hw, mMode);
             }
@@ -1119,35 +1158,60 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
+void SurfaceFlinger::createDefaultDisplayDevice() {
+    const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+    wp<IBinder> token = mBuiltinDisplays[type];
+
+    // All non-virtual displays are currently considered secure.
+    const bool isSecure = true;
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc());
+
+    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, type, consumer);
+
+    bool hasWideColorModes = false;
+    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(
+        type);
+    for (android_color_mode_t colorMode : modes) {
+        switch (colorMode) {
+            case HAL_COLOR_MODE_DISPLAY_P3:
+            case HAL_COLOR_MODE_ADOBE_RGB:
+            case HAL_COLOR_MODE_DCI_P3:
+                hasWideColorModes = true;
+                break;
+            default:
+                break;
+        }
+    }
+    sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
+                                             token, fbs, producer, mRenderEngine->getEGLConfig(),
+                                             hasWideColorModes && hasWideColorDisplay);
+    mDisplays.add(token, hw);
+    android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+    if (hasWideColorModes && hasWideColorDisplay) {
+        defaultColorMode = HAL_COLOR_MODE_SRGB;
+    }
+    setActiveColorModeInternal(hw, defaultColorMode);
+}
+
+void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
     ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+
+    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.");
+        }
+        return;
+    }
+
     if (disp == DisplayDevice::DISPLAY_PRIMARY) {
         Mutex::Autolock lock(mStateLock);
-
-        // All non-virtual displays are currently considered secure.
-        bool isSecure = true;
-
-        int32_t type = DisplayDevice::DISPLAY_PRIMARY;
-
-        // When we're using the vr composer, the assumption is that we've
-        // already created the IBinder object for the primary display.
-        if (!mHwc->isUsingVrComposer()) {
-            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
-        }
-
-        wp<IBinder> token = mBuiltinDisplays[type];
-
-        sp<IGraphicBufferProducer> producer;
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&producer, &consumer,
-                new GraphicBufferAlloc());
-
-        sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
-                DisplayDevice::DISPLAY_PRIMARY, consumer);
-        sp<DisplayDevice> hw = new DisplayDevice(this,
-                DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
-                producer, mRenderEngine->getEGLConfig());
-        mDisplays.add(token, hw);
+        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+        createDefaultDisplayDevice();
     } else {
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
         Mutex::Autolock _l(mStateLock);
@@ -1189,6 +1253,7 @@
     }
 }
 
+// Note: it is assumed the caller holds |mStateLock| when this is called
 void SurfaceFlinger::resetHwc() {
     disableHardwareVsync(true);
     clearHwcLayers(mDrawingState.layersSortedByZ);
@@ -1209,36 +1274,46 @@
     if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) {
         return;
     }
+
+    bool vrHwcNewlyInitialized = false;
+
     if (vrFlingerRequestsDisplay && !mVrHwc) {
         // Construct new HWComposer without holding any locks.
         mVrHwc = new HWComposer(true);
+        vrHwcNewlyInitialized = true;
         ALOGV("Vr HWC created");
     }
-    {
-        Mutex::Autolock _l(mStateLock);
 
-        if (vrFlingerRequestsDisplay) {
-            resetHwc();
+    Mutex::Autolock _l(mStateLock);
 
-            mHwc = mVrHwc;
-            mVrFlinger->GrantDisplayOwnership();
-        } else {
-            mVrFlinger->SeizeDisplayOwnership();
+    if (vrFlingerRequestsDisplay) {
+        resetHwc();
 
-            resetHwc();
+        mHwc = mVrHwc;
+        mVrFlinger->GrantDisplayOwnership();
 
-            mHwc = mRealHwc;
-            enableHardwareVsync();
+        if (vrHwcNewlyInitialized) {
+            mVrHwc->setEventHandler(
+                static_cast<HWComposer::EventHandler*>(this));
         }
+    } else {
+        mVrFlinger->SeizeDisplayOwnership();
 
-        mVisibleRegionsDirty = true;
-        invalidateHwcGeometry();
-        android_atomic_or(1, &mRepaintEverything);
-        setTransactionFlags(eDisplayTransactionNeeded);
+        resetHwc();
+
+        mHwc = mRealHwc;
+        enableHardwareVsync();
     }
-    if (mVrHwc) {
-        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-    }
+
+    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();
+
+    android_atomic_or(1, &mRepaintEverything);
+    setTransactionFlags(eDisplayTransactionNeeded);
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -1448,7 +1523,8 @@
         layer->releasePendingBuffer(dequeueReadyTime);
     }
 
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    // |mStateLock| not needed as we are on the main thread
+    const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
     if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
@@ -1591,6 +1667,39 @@
     }
 }
 
+// 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) {
+    switch (dataSpace) {
+        // treat Unknown as regular SRGB buffer, since that's what the rest of the
+        // system expects.
+        case HAL_DATASPACE_UNKNOWN:
+        case HAL_DATASPACE_SRGB:
+        case HAL_DATASPACE_V0_SRGB:
+            return HAL_COLOR_MODE_SRGB;
+            break;
+
+        case HAL_DATASPACE_DISPLAY_P3:
+            return HAL_COLOR_MODE_DISPLAY_P3;
+            break;
+
+        default:
+            // TODO (courtneygo): Do we want to assert an error here?
+            ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(),
+                  dataSpace);
+            return HAL_COLOR_MODE_SRGB;
+            break;
+    }
+}
+
+android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+    // Only support sRGB and Display-P3 right now.
+    if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+    return HAL_DATASPACE_V0_SRGB;
+}
+
 void SurfaceFlinger::setUpHWComposer() {
     ATRACE_CALL();
     ALOGV("setUpHWComposer");
@@ -1661,6 +1770,7 @@
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
         auto& displayDevice = mDisplays[displayId];
         const auto hwcId = displayDevice->getHwcDisplayId();
+
         if (hwcId < 0) {
             continue;
         }
@@ -1672,6 +1782,21 @@
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             layer->setPerFrameData(displayDevice);
         }
+
+        if (hasWideColorDisplay) {
+            android_color_mode newColorMode;
+            android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
+                      layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
+                      layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
+            }
+            newColorMode = pickColorMode(newDataSpace);
+
+            setActiveColorModeInternal(displayDevice, newColorMode);
+        }
     }
 
     mPreviousColorMatrix = colorMatrix;
@@ -1747,7 +1872,8 @@
     mLastSwapBufferTime = systemTime() - now;
     mDebugInSwapBuffers = 0;
 
-    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
+    // |mStateLock| not needed as we are on the main thread
+    uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
     if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
         logFrameStats();
     }
@@ -1832,7 +1958,7 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                         defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                         sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                         if (hw != NULL)
@@ -1950,10 +2076,11 @@
 
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (dispSurface != NULL) {
-                        sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, hwcId, state.isSecure, display,
-                                dispSurface, producer,
-                                mRenderEngine->getEGLConfig());
+                        sp<DisplayDevice> hw =
+                                new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
+                                                  dispSurface, producer,
+                                                  mRenderEngine->getEGLConfig(),
+                                                  hasWideColorDisplay);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -2021,7 +2148,7 @@
                 // could be null when this layer is using a layerStack
                 // that is not visible on any display. Also can occur at
                 // screen off/on times.
-                disp = getDefaultDisplayDevice();
+                disp = getDefaultDisplayDeviceLocked();
             }
             layer->updateTransformHint(disp);
 
@@ -2369,11 +2496,17 @@
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
 
+#ifdef USE_HWC2
+        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
+        mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+#endif
         if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   displayDevice->getDisplayName().string());
             eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
+
+            // |mStateLock| not needed as we are on the main thread
+            if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
             }
             return false;
@@ -2741,6 +2874,11 @@
                 }
             }
         }
+        if (what & layer_state_t::eRelativeLayerChanged) {
+            if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
         if (what & layer_state_t::eSizeChanged) {
             if (layer->setSize(s.w, s.h)) {
                 flags |= eTraversalNeeded;
@@ -3014,7 +3152,6 @@
     int currentMode = hw->getPowerMode();
 
     if (mode == currentMode) {
-        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
         return;
     }
 
@@ -3171,6 +3308,12 @@
                 dumpFrameEventsLocked(result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) && (args[index] == String16("--wide-color"))) {
+                index++;
+                dumpWideColorInfo(result);
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
@@ -3341,6 +3484,30 @@
     result.append("\n");
 }
 
+void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
+    result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+
+    // TODO: print out if wide-color mode is active or not
+
+    for (size_t d = 0; d < mDisplays.size(); d++) {
+        const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+        int32_t hwcId = displayDevice->getHwcDisplayId();
+        if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+            continue;
+        }
+
+        result.appendFormat("Display %d color modes:\n", hwcId);
+        std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(hwcId);
+        for (auto&& mode : modes) {
+            result.appendFormat("    %s (%d)\n", decodeColorMode(mode).c_str(), mode);
+        }
+
+        android_color_mode_t currentMode = displayDevice->getActiveColorMode();
+        result.appendFormat("    Current color mode: %s (%d)\n",
+                            decodeColorMode(currentMode).c_str(), currentMode);
+    }
+    result.append("\n");
+}
 
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
@@ -3373,6 +3540,9 @@
     appendGuiConfigString(result);
     result.append("\n");
 
+    result.append("\nWide-Color information:\n");
+    dumpWideColorInfo(result);
+
     colorizer.bold(result);
     result.append("Sync configuration: ");
     colorizer.reset(result);
@@ -3428,7 +3598,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
@@ -3658,7 +3828,7 @@
                 return NO_ERROR;
             case 1013: {
                 Mutex::Autolock _l(mStateLock);
-                sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+                sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
                 reply->writeInt32(hw->getPageFlipCount());
                 return NO_ERROR;
             }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ecbddd..e9c0acf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -151,6 +151,13 @@
     // FramebufferSurface
     static int64_t maxFrameBufferAcquiredBuffers;
 
+    // Indicate if platform supports color management on its
+    // wide-color display. This is typically found on devices
+    // with wide gamut (e.g. Display-P3) display.
+    // This also allows devices with wide-color displays that don't
+    // want to support color management to disable color management.
+    static bool hasWideColorDisplay;
+
     static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
@@ -177,8 +184,9 @@
     void repaintEverything();
 
     // returns the default Display
-    sp<const DisplayDevice> getDefaultDisplayDevice() const {
-        return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+    sp<const DisplayDevice> getDefaultDisplayDevice() {
+        Mutex::Autolock _l(mStateLock);
+        return getDefaultDisplayDeviceLocked();
     }
 
     // utility function to delete a texture on the main thread
@@ -220,6 +228,7 @@
     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();
@@ -258,6 +267,8 @@
     virtual void bootFinished();
     virtual bool authenticateSurfaceTexture(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
+    virtual status_t getSupportedFrameTimestamps(
+            std::vector<FrameEvent>* outSupported) const;
     virtual sp<IDisplayEventConnection> createDisplayEventConnection();
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
@@ -297,7 +308,7 @@
      * HWComposer::EventHandler interface
      */
     virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
-    virtual void onHotplugReceived(int disp, bool connected);
+    virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
     virtual void onInvalidateReceived(HWComposer* composer);
 
     /* ------------------------------------------------------------------------
@@ -432,6 +443,12 @@
         return mDisplays.valueFor(dpy);
     }
 
+    sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+        return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+    }
+
+    void createDefaultDisplayDevice();
+
     int32_t getDisplayType(const sp<IBinder>& display) {
         if (!display.get()) return NAME_NOT_FOUND;
         for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
@@ -472,6 +489,12 @@
             nsecs_t vsyncPhase, nsecs_t vsyncInterval,
             nsecs_t compositeToPresentLatency);
     void rebuildLayerStacks();
+
+    // 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);
+
     void setUpHWComposer();
     void doComposition();
     void doDebugFlashRegions();
@@ -522,6 +545,7 @@
     void recordBufferingStats(const char* layerName,
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
+    void dumpWideColorInfo(String8& result) const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index a6c0b9c..bdaf85d 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -549,6 +549,9 @@
     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);
@@ -570,7 +573,7 @@
             sp<DisplayDevice> hw = new DisplayDevice(this,
                     type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                     fbs, producer,
-                    mRenderEngine->getEGLConfig());
+                    mRenderEngine->getEGLConfig(), false);
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -584,7 +587,7 @@
 
     // make the GLContext current so that we can create textures when creating Layers
     // (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -647,6 +650,21 @@
     return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
 }
 
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+        std::vector<FrameEvent>* outSupported) const {
+    *outSupported = {
+        FrameEvent::REQUESTED_PRESENT,
+        FrameEvent::ACQUIRE,
+        FrameEvent::LATCH,
+        FrameEvent::FIRST_REFRESH_START,
+        FrameEvent::LAST_REFRESH_START,
+        FrameEvent::GPU_COMPOSITION_DONE,
+        FrameEvent::DEQUEUE_READY,
+        FrameEvent::RELEASE,
+    };
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
         Vector<DisplayInfo>* configs) {
     if ((configs == NULL) || (display.get() == NULL)) {
@@ -1040,7 +1058,7 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
+void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
     if (mEventThread == NULL) {
         // This is a temporary workaround for b/7145521.  A non-null pointer
         // does not mean EventThread has finished initializing, so this
@@ -1740,7 +1758,7 @@
                                 state.type, hwcDisplayId,
                                 mHwc->getFormat(hwcDisplayId), state.isSecure,
                                 display, dispSurface, producer,
-                                mRenderEngine->getEGLConfig());
+                                mRenderEngine->getEGLConfig(), false);
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -3222,7 +3240,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index f151087..d15376e 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,17 +18,44 @@
 
 #include <sched.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <cutils/sched_policy.h>
 #include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <hidl/LegacySupport.h>
+#include <configstore/Utils.h>
 #include "GpuService.h"
 #include "SurfaceFlinger.h"
 
 using namespace android;
 
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using android::hardware::configstore::getBool;
+using android::hardware::configstore::getBool;
+
+static status_t startGraphicsAllocatorService() {
+    hardware::configureRpcThreadpool( 1 /* maxThreads */,
+            false /* callerWillJoin */);
+    status_t result =
+        hardware::registerPassthroughServiceImplementation<IAllocator>();
+    if (result != OK) {
+        ALOGE("could not start graphics allocator service");
+        return result;
+    }
+
+    return OK;
+}
+
 int main(int, char**) {
+    if (getBool<ISurfaceFlingerConfigs,
+            &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
+        startGraphicsAllocatorService();
+    }
+
     signal(SIGPIPE, SIG_IGN);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a46ba48..441fc7e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@
     }
 }
 
+TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before adding relative surface");
+        ScreenCapture::captureScreen(&sc);
+        sc->expectBGColor(24, 24);
+        sc->expectFGColor(75, 75);
+        sc->expectBGColor(145, 145);
+    }
+
+    auto relativeSurfaceControl = mComposerClient->createSurface(
+            String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+    fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
+    waitForPostedBuffers();
+
+    // Now we stack the surface above the foreground surface and make sure it is visible.
+    SurfaceComposerClient::openGlobalTransaction();
+    relativeSurfaceControl->setPosition(64, 64);
+    relativeSurfaceControl->show();
+    relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+
+    {
+        SCOPED_TRACE("after adding relative surface");
+        ScreenCapture::captureScreen(&sc);
+        // our relative surface should be visible now.
+        sc->checkPixel(75, 75, 255, 177, 177);
+    }
+
+    // A call to setLayer will override a call to setRelativeLayer
+    SurfaceComposerClient::openGlobalTransaction();
+    relativeSurfaceControl->setLayer(0);
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    {
+        SCOPED_TRACE("after set layer");
+        ScreenCapture::captureScreen(&sc);
+        // now the FG surface should be visible again.
+        sc->expectFGColor(75, 75);
+    }
+}
+
 class ChildLayerTest : public LayerUpdateTest {
 protected:
     void SetUp() override {
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index b3d777e..97f0332 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -37,8 +37,6 @@
         libui
 
 include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
 LOCAL_SRC_FILES := $(sourceFiles)
 LOCAL_CFLAGS := -DLOG_TAG=\"bufferhubd\"
 LOCAL_CFLAGS += -DTRACE=0
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index de4950e..4b1a522 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -1,5 +1,6 @@
 #include "buffer_hub.h"
 
+#include <inttypes.h>
 #include <log/log.h>
 #include <poll.h>
 #include <utils/Trace.h>
@@ -16,7 +17,9 @@
 #include "producer_queue_channel.h"
 
 using android::pdx::Channel;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::default_transport::Endpoint;
 
@@ -28,9 +31,7 @@
 
 BufferHubService::~BufferHubService() {}
 
-bool BufferHubService::IsInitialized() const {
-  return BASE::IsInitialized();
-}
+bool BufferHubService::IsInitialized() const { return BASE::IsInitialized(); }
 
 std::string BufferHubService::DumpState(size_t /*max_length*/) {
   std::ostringstream stream;
@@ -52,7 +53,7 @@
   stream << " ";
   stream << std::setw(6) << "Format";
   stream << " ";
-  stream << std::setw(10) << "Usage";
+  stream << std::setw(21) << "Usage";
   stream << " ";
   stream << "Name";
   stream << std::endl;
@@ -79,7 +80,9 @@
       stream << std::setw(6) << info.format;
       stream << " ";
       stream << "0x" << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage;
+      stream << std::setw(8) << info.producer_usage;
+      stream << "0x";
+      stream << std::setw(8) << info.consumer_usage;
       stream << std::dec << std::setfill(' ');
       stream << " ";
       stream << info.name;
@@ -137,6 +140,10 @@
   stream << " UsageClearMask";
   stream << " UsageDenySetMask";
   stream << " UsageDenyClearMask";
+  stream << " UsageSetMask";
+  stream << " UsageClearMask";
+  stream << " UsageDenySetMask";
+  stream << " UsageDenyClearMask";
   stream << " ";
   stream << std::endl;
 
@@ -150,16 +157,30 @@
       stream << std::right << std::setw(12) << info.consumer_count;
       stream << std::setw(5) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_set_mask;
       stream << std::setw(7) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_clear_mask;
+      stream << std::setw(8) << info.usage_policy.producer_clear_mask;
       stream << std::setw(9) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
       stream << std::setw(11) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_clear_mask;
+      stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
+      stream << std::setw(5) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_set_mask;
+      stream << std::setw(7) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
+      stream << std::setw(9) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
+      stream << std::setw(11) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+      stream << std::hex << std::setfill('0');
+      stream << std::endl;
     }
   }
 
@@ -177,6 +198,7 @@
 
       stream << std::right << std::setw(6) << info.id;
       stream << std::right << std::setw(12) << info.capacity;
+      stream << std::endl;
     }
   }
 
@@ -235,48 +257,53 @@
     buffer->Detach();
 }
 
-int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
-                                     int format, int usage,
-                                     size_t meta_size_bytes,
-                                     size_t slice_count) {
+Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
+                                              uint32_t height, uint32_t format,
+                                              uint64_t producer_usage,
+                                              uint64_t consumer_usage,
+                                              size_t meta_size_bytes,
+                                              size_t slice_count) {
   // Use the producer channel id as the global buffer id.
   const int buffer_id = message.GetChannelId();
   ALOGD_IF(TRACE,
-           "BufferHubService::OnCreateBuffer: buffer_id=%d width=%d height=%d "
-           "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
-           buffer_id, width, height, format, usage, meta_size_bytes,
-           slice_count);
+           "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
+           "format=%u producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " meta_size_bytes=%zu slice_count=%zu",
+           buffer_id, width, height, format, producer_usage, consumer_usage,
+           meta_size_bytes, slice_count);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
     ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
           buffer_id);
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel =
-          ProducerChannel::Create(this, buffer_id, width, height, format, usage,
-                                  meta_size_bytes, slice_count, &error)) {
-    message.SetChannel(producer_channel);
-    return 0;
+  auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
+                                        producer_usage, consumer_usage,
+                                        meta_size_bytes, slice_count);
+  if (status) {
+    message.SetChannel(status.take());
+    return {};
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
   }
 }
 
-int BufferHubService::OnCreatePersistentBuffer(
+Status<void> BufferHubService::OnCreatePersistentBuffer(
     Message& message, const std::string& name, int user_id, int group_id,
-    int width, int height, int format, int usage, size_t meta_size_bytes,
-    size_t slice_count) {
+    uint32_t width, uint32_t height, uint32_t format, uint64_t producer_usage,
+    uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
-           "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
-           "meta_size_bytes=%zu slice_count=%zu",
+           "user_id=%d group_id=%d width=%u height=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " meta_size_bytes=%zu slice_count=%zu",
            channel_id, name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -284,12 +311,11 @@
         "BufferHubService::OnCreatePersistentBuffer: Channel already attached "
         "to buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
   const int egid = message.GetEffectiveGroupId();
-  int error;
 
   if (auto buffer = GetNamedBuffer(name)) {
     if (!buffer->CheckAccess(euid, egid)) {
@@ -297,41 +323,45 @@
           "BufferHubService::OnCreatePersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, euid);
-      return -EPERM;
-    } else if (!buffer->CheckParameters(width, height, format, usage,
-                                        meta_size_bytes, slice_count)) {
+      return ErrorStatus(EPERM);
+    } else if (!buffer->CheckParameters(width, height, format, producer_usage,
+                                        consumer_usage, meta_size_bytes,
+                                        slice_count)) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
           "buffer with different parameters: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
-  } else if (auto buffer = ProducerChannel::Create(
-                 this, channel_id, width, height, format, usage,
-                 meta_size_bytes, slice_count, &error)) {
-    const int ret =
-        buffer->OnProducerMakePersistent(message, name, user_id, group_id);
-    if (!ret)
-      message.SetChannel(buffer);
-    return ret;
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    auto status = ProducerChannel::Create(
+        this, channel_id, width, height, format, producer_usage, consumer_usage,
+        meta_size_bytes, slice_count);
+    if (!status) {
+      ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
+      return status.error_status();
+    }
+    auto persistent_buffer = status.take();
+    auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
+        message, name, user_id, group_id);
+    if (make_persistent_status)
+      message.SetChannel(persistent_buffer);
+    return make_persistent_status;
   }
 }
 
-int BufferHubService::OnGetPersistentBuffer(Message& message,
-                                            const std::string& name) {
+Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
+                                                     const std::string& name) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
@@ -343,7 +373,7 @@
         "BufferHubService::OnGetPersistentBuffer: Channel already attached to "
         "buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
@@ -355,28 +385,28 @@
           "BufferHubService::OnGetPersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, egid);
-      return -EPERM;
+      return ErrorStatus(EPERM);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
   } else {
     ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
           name.c_str());
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
   }
 }
 
-int BufferHubService::OnCreateProducerQueue(
-    pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
-    int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask) {
+Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
+    pdx::Message& message, size_t meta_size_bytes,
+    const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
   ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
@@ -386,18 +416,17 @@
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
     ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
           queue_id);
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel = ProducerQueueChannel::Create(
-          this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-          usage_deny_set_mask, usage_deny_clear_mask, &error)) {
-    message.SetChannel(producer_channel);
-    return 0;
+  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+                                             usage_policy);
+  if (status) {
+    message.SetChannel(status.take());
+    return {{meta_size_bytes, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    return status.error_status();
   }
 }
 
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 8a7dca8..4cb1eb9 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -7,6 +7,7 @@
 
 #include <hardware/gralloc.h>
 #include <pdx/service.h>
+#include <private/dvr/bufferhub_rpc.h>
 
 namespace android {
 namespace dvr {
@@ -47,43 +48,40 @@
     size_t consumer_count = 0;
 
     // Data field for buffer producer.
-    int width = 0;
-    int height = 0;
-    int format = 0;
-    int usage = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint64_t producer_usage = 0;
+    uint64_t consumer_usage = 0;
     size_t slice_count = 0;
     std::string name;
 
     // Data filed for producer queue.
     size_t capacity = 0;
-    int usage_set_mask = 0;
-    int usage_clear_mask = 0;
-    int usage_deny_set_mask = 0;
-    int usage_deny_clear_mask = 0;
+    UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
 
-    BufferInfo(int id, size_t consumer_count, int width, int height, int format,
-               int usage, size_t slice_count, const std::string& name)
+    BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
+               uint32_t format, uint64_t producer_usage,
+               uint64_t consumer_usage, size_t slice_count,
+               const std::string& name)
         : id(id),
           type(kProducerType),
           consumer_count(consumer_count),
           width(width),
           height(height),
           format(format),
-          usage(usage),
+          producer_usage(producer_usage),
+          consumer_usage(consumer_usage),
           slice_count(slice_count),
           name(name) {}
 
-    BufferInfo(int id, size_t consumer_count, size_t capacity, int usage_set_mask,
-               int usage_clear_mask, int usage_deny_set_mask,
-               int usage_deny_clear_mask)
+    BufferInfo(int id, size_t consumer_count, size_t capacity,
+               const UsagePolicy& usage_policy)
         : id(id),
           type(kProducerQueueType),
           consumer_count(consumer_count),
           capacity(capacity),
-          usage_set_mask(usage_set_mask),
-          usage_clear_mask(usage_clear_mask),
-          usage_deny_set_mask(usage_deny_set_mask),
-          usage_deny_clear_mask(usage_deny_clear_mask) {}
+          usage_policy(usage_policy) {}
 
     BufferInfo() {}
   };
@@ -161,16 +159,19 @@
   std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
       named_buffers_;
 
-  int OnCreateBuffer(pdx::Message& message, int width, int height, int format,
-                     int usage, size_t meta_size_bytes, size_t slice_count);
-  int OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
-                               int user_id, int group_id, int width, int height,
-                               int format, int usage, size_t meta_size_bytes,
-                               size_t slice_count);
-  int OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
-  int OnCreateProducerQueue(pdx::Message& message, size_t meta_size_bytes,
-                            int usage_set_mask, int usage_clear_mask,
-                            int usage_deny_set_mask, int usage_deny_clear_mask);
+  pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, uint32_t height,
+                     uint32_t format, uint64_t producer_usage,
+                     uint64_t consumer_usage, size_t meta_size_bytes,
+                     size_t slice_count);
+  pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message, 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 slice_count);
+  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);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 2264cef..311f5c6 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,11 @@
 #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::Message;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -103,53 +105,53 @@
   }
 }
 
-std::pair<BorrowedFence, ConsumerChannel::MetaData>
+Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
 ConsumerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
   auto producer = GetProducer();
   if (!producer)
-    REPLY_ERROR_RETURN(message, EPIPE, {});
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
     return producer->OnConsumerAcquire(message, metadata_size);
   }
 }
 
-int ConsumerChannel::OnConsumerRelease(Message& message,
-                                       LocalFence release_fence) {
+Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
-    const int ret =
+    auto status =
         producer->OnConsumerRelease(message, std::move(release_fence));
-    handled_ = ret == 0;
-    return ret;
+    handled_ = !!status;
+    return status;
   }
 }
 
-int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
+Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
   ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   ignored_ = ignored;
   if (ignored_ && !handled_) {
@@ -160,7 +162,7 @@
     handled_ = false;
   }
 
-  return 0;
+  return {};
 }
 
 bool ConsumerChannel::OnProducerPosted() {
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d2a078f..d84055c 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -32,10 +32,11 @@
 
   std::shared_ptr<ProducerChannel> GetProducer() const;
 
-  std::pair<BorrowedFence, MetaData> OnConsumerAcquire(
+  pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
       Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
-  int OnConsumerSetIgnore(Message& message, bool ignore);
+  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.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index ae87acd..7422751 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -4,7 +4,9 @@
 
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -40,6 +42,11 @@
           *producer, &ProducerQueueChannel::OnCreateConsumerQueue, message);
       return true;
 
+    case BufferHubRPC::GetQueueInfo::Opcode:
+      DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>(
+          *producer, &ProducerQueueChannel::OnGetQueueInfo, message);
+      return true;
+
     case BufferHubRPC::ConsumerQueueImportBuffers::Opcode:
       DispatchRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>(
           *this, &ConsumerQueueChannel::OnConsumerQueueImportBuffers, message);
@@ -78,7 +85,7 @@
   SignalAvailable();
 }
 
-std::vector<std::pair<RemoteChannelHandle, size_t>>
+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");
@@ -101,31 +108,30 @@
       continue;
     }
 
-    RemoteChannelHandle consumer_handle(
-        producer_channel->CreateConsumer(message));
+    auto status = producer_channel->CreateConsumer(message);
 
     // If no buffers are imported successfully, clear available and return an
     // error. Otherwise, return all consumer handles already imported
     // successfully, but keep available bits on, so that the client can retry
     // importing remaining consumer buffers.
-    if (!consumer_handle.valid()) {
+    if (!status) {
       ALOGE(
-          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: imported "
-          "consumer handle is invalid.");
+          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: Failed create "
+          "consumer: %s",
+          status.GetErrorMessage().c_str());
       if (buffer_handles.empty()) {
         ClearAvailable();
-        REPLY_ERROR_RETURN(message, EIO, {});
+        return status.error_status();
       } else {
-        return buffer_handles;
+        return {std::move(buffer_handles)};
       }
     }
 
-    // Move consumer_handle into buffer_handles.
-    buffer_handles.emplace_back(std::move(consumer_handle), producer_slot);
+    buffer_handles.emplace_back(status.take(), producer_slot);
   }
 
   ClearAvailable();
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index b345595..e1005e4 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -36,7 +36,7 @@
   // allocated. Clients uses kOpConsumerQueueImportBuffers to import new
   // consumer buffers and this handler returns a vector of fd representing
   // BufferConsumers that clients can import.
-  std::vector<std::pair<RemoteChannelHandle, size_t>>
+  pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
   OnConsumerQueueImportBuffers(Message& message);
 
  private:
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 903d174..c946a8d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -13,8 +13,10 @@
 #include "consumer_channel.h"
 
 using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::BufferWrapper;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
@@ -23,7 +25,9 @@
 namespace dvr {
 
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
-                                 int width, int height, int format, int usage,
+                                 uint32_t width, uint32_t height,
+                                 uint32_t format, uint64_t producer_usage,
+                                 uint64_t consumer_usage,
                                  size_t meta_size_bytes, size_t slice_count,
                                  int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -33,7 +37,8 @@
       meta_size_bytes_(meta_size_bytes),
       meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
   for (auto& ion_buffer : slices_) {
-    const int ret = ion_buffer.Alloc(width, height, format, usage);
+    const int ret =
+        ion_buffer.Alloc(width, height, format, producer_usage, consumer_usage);
     if (ret < 0) {
       ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
             strerror(-ret));
@@ -46,17 +51,18 @@
   *error = 0;
 }
 
-std::shared_ptr<ProducerChannel> ProducerChannel::Create(
-    BufferHubService* service, int channel_id, int width, int height,
-    int format, int usage, size_t meta_size_bytes, size_t slice_count,
-    int* error) {
-  std::shared_ptr<ProducerChannel> producer(
-      new ProducerChannel(service, channel_id, width, height, format, usage,
-                          meta_size_bytes, slice_count, error));
-  if (*error < 0)
-    return nullptr;
+Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
+    BufferHubService* service, int channel_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 slice_count) {
+  int error;
+  std::shared_ptr<ProducerChannel> producer(new ProducerChannel(
+      service, channel_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count, &error));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 ProducerChannel::~ProducerChannel() {
@@ -70,7 +76,8 @@
 BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
   return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
                     slices_[0].height(), slices_[0].format(),
-                    slices_[0].usage(), slices_.size(), name_);
+                    slices_[0].producer_usage(), slices_[0].consumer_usage(),
+                    slices_.size(), name_);
 }
 
 void ProducerChannel::HandleImpulse(Message& message) {
@@ -125,28 +132,28 @@
   }
 }
 
-NativeBufferHandle<BorrowedHandle> ProducerChannel::OnGetBuffer(
+Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
     Message& message, unsigned index) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
   if (index < slices_.size()) {
-    return NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id());
+    return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
   } else {
-    REPLY_ERROR_RETURN(message, EINVAL, NativeBufferHandle<BorrowedHandle>());
+    return ErrorStatus(EINVAL);
   }
 }
 
-std::vector<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffers(
-    Message&) {
+Status<std::vector<NativeBufferHandle<BorrowedHandle>>>
+ProducerChannel::OnGetBuffers(Message&) {
   ATRACE_NAME("ProducerChannel::OnGetBuffers");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffers: buffer_id=%d", buffer_id());
   std::vector<NativeBufferHandle<BorrowedHandle>> buffer_handles;
   for (const auto& buffer : slices_)
     buffer_handles.emplace_back(buffer, buffer_id());
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
-RemoteChannelHandle ProducerChannel::CreateConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::CreateConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
 
@@ -154,9 +161,9 @@
   auto status = message.PushChannel(0, nullptr, &channel_id);
   if (!status) {
     ALOGE(
-        "ProducerChannel::CreateConsumer: failed to push consumer channel: %s",
+        "ProducerChannel::CreateConsumer: Failed to push consumer channel: %s",
         status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   auto consumer = std::make_shared<ConsumerChannel>(
@@ -167,7 +174,7 @@
         "ProducerChannel::CreateConsumer: failed to set new consumer channel: "
         "%s",
         channel_status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   if (!producer_owns_) {
@@ -176,33 +183,27 @@
       pending_consumers_++;
   }
 
-  return status.take();
+  return {status.take()};
 }
 
-RemoteChannelHandle ProducerChannel::OnNewConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::OnNewConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
-
-  RemoteChannelHandle consumer_handle(CreateConsumer(message));
-
-  if (consumer_handle.valid())
-    return consumer_handle;
-  else
-    REPLY_ERROR_RETURN(message, ENOMEM, RemoteChannelHandle());
+  return CreateConsumer(message);
 }
 
-int ProducerChannel::OnProducerPost(
+Status<void> ProducerChannel::OnProducerPost(
     Message&, LocalFence acquire_fence,
     BufferWrapper<std::vector<std::uint8_t>> metadata) {
   ATRACE_NAME("ProducerChannel::OnProducerPost");
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
   if (!producer_owns_) {
     ALOGE("ProducerChannel::OnProducerPost: Not in gained state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   if (meta_size_bytes_ != metadata.size())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   std::copy(metadata.begin(), metadata.end(), meta_.get());
 
   post_fence_ = std::move(acquire_fence);
@@ -220,29 +221,29 @@
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
            pending_consumers_);
 
-  return 0;
+  return {};
 }
 
-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_) {
     ALOGE("ProducerChanneL::OnGain: Already in gained state: channel=%d",
           channel_id());
-    REPLY_ERROR_RETURN(message, EALREADY, {});
+    return ErrorStatus(EALREADY);
   }
 
   // There are still pending consumers, return busy.
   if (pending_consumers_ > 0)
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
 
   ClearAvailable();
   producer_owns_ = true;
   post_fence_.close();
-  return std::move(returned_fence_);
+  return {std::move(returned_fence_)};
 }
 
-std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>
+Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
 ProducerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
@@ -250,26 +251,27 @@
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerAcquire: Not in posted state!");
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   }
 
   // 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));
+    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::make_pair(post_fence_.borrow(),
+                           WrapBuffer(meta_.get(), meta_size_bytes_))};
 }
 
-int ProducerChannel::OnConsumerRelease(Message&, LocalFence release_fence) {
+Status<void> ProducerChannel::OnConsumerRelease(Message&,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ProducerChannel::OnConsumerRelease");
   ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerRelease: Not in acquired state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   // Attempt to merge the fences if necessary.
@@ -282,7 +284,7 @@
       if (!merged_fence) {
         ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
               strerror(error));
-        return -error;
+        return ErrorStatus(error);
       }
       returned_fence_ = std::move(merged_fence);
     } else {
@@ -291,7 +293,7 @@
   }
 
   OnConsumerIgnored();
-  return 0;
+  return {};
 }
 
 void ProducerChannel::OnConsumerIgnored() {
@@ -302,9 +304,10 @@
            buffer_id(), pending_consumers_);
 }
 
-int ProducerChannel::OnProducerMakePersistent(Message& message,
-                                              const std::string& name,
-                                              int user_id, int group_id) {
+Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
+                                                       const std::string& name,
+                                                       int user_id,
+                                                       int group_id) {
   ATRACE_NAME("ProducerChannel::OnProducerMakePersistent");
   ALOGD_IF(TRACE,
            "ProducerChannel::OnProducerMakePersistent: buffer_id=%d name=%s "
@@ -313,7 +316,7 @@
 
   if (name.empty() || (user_id < 0 && user_id != kNoCheckId) ||
       (group_id < 0 && group_id != kNoCheckId)) {
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   // Try to add this buffer with the requested name.
@@ -331,18 +334,18 @@
     owner_user_id_ = user_id;
     owner_group_id_ = group_id;
     name_ = name;
-    return 0;
+    return {};
   } else {
     // Otherwise a buffer with that name already exists.
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 }
 
-int ProducerChannel::OnRemovePersistence(Message&) {
+Status<void> ProducerChannel::OnRemovePersistence(Message&) {
   if (service()->RemoveNamedBuffer(*this))
-    return 0;
+    return {};
   else
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
 }
 
 void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -365,12 +368,16 @@
 }
 
 // Returns true if the given parameters match the underlying buffer parameters.
-bool ProducerChannel::CheckParameters(int width, int height, int format,
-                                      int usage, size_t meta_size_bytes,
+bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
+                                      uint32_t format, uint64_t producer_usage,
+                                      uint64_t consumer_usage,
+                                      size_t meta_size_bytes,
                                       size_t slice_count) {
   return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
          slices_[0].width() == width && slices_[0].height() == height &&
-         slices_[0].format() == format && slices_[0].usage() == usage;
+         slices_[0].format() == format &&
+         slices_[0].producer_usage() == producer_usage &&
+         slices_[0].consumer_usage() == consumer_usage;
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index e7ca459..f04c8a5 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,10 +30,10 @@
   template <typename T>
   using BufferWrapper = pdx::rpc::BufferWrapper<T>;
 
-  static std::shared_ptr<ProducerChannel> Create(
-      BufferHubService* service, int channel_id, int width, int height,
-      int format, int usage, size_t meta_size_bytes, size_t slice_count,
-      int* error);
+  static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
+      BufferHubService* service, int channel_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 slice_count);
 
   ~ProducerChannel() override;
 
@@ -42,17 +42,18 @@
 
   BufferInfo GetBufferInfo() const override;
 
-  NativeBufferHandle<BorrowedHandle> OnGetBuffer(Message& message,
-                                                 unsigned index);
-  std::vector<NativeBufferHandle<BorrowedHandle>> OnGetBuffers(
+  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
+                                                              unsigned index);
+  pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
       Message& message);
 
-  RemoteChannelHandle CreateConsumer(Message& message);
-  RemoteChannelHandle OnNewConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
 
-  std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>> OnConsumerAcquire(
-      Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
+  pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
+  OnConsumerAcquire(Message& message, std::size_t metadata_size);
+  pdx::Status<void> OnConsumerRelease(Message& message,
+                                      LocalFence release_fence);
 
   void OnConsumerIgnored();
 
@@ -60,12 +61,14 @@
   void RemoveConsumer(ConsumerChannel* channel);
 
   bool CheckAccess(int euid, int egid);
-  bool CheckParameters(int width, int height, int format, int usage,
+  bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
+                       uint64_t producer_usage, uint64_t consumer_usage,
                        size_t meta_size_bytes, size_t slice_count);
 
-  int OnProducerMakePersistent(Message& message, const std::string& name,
-                               int user_id, int group_id);
-  int OnRemovePersistence(Message& message);
+  pdx::Status<void> OnProducerMakePersistent(Message& message,
+                                             const std::string& name,
+                                             int user_id, int group_id);
+  pdx::Status<void> OnRemovePersistence(Message& message);
 
  private:
   std::vector<ConsumerChannel*> consumer_channels_;
@@ -91,13 +94,15 @@
 
   std::string name_;
 
-  ProducerChannel(BufferHubService* service, int channel, int width, int height,
-                  int format, int usage, size_t meta_size_bytes,
+  ProducerChannel(BufferHubService* service, int channel, uint32_t width,
+                  uint32_t height, uint32_t format, uint64_t producer_usage,
+                  uint64_t consumer_usage, size_t meta_size_bytes,
                   size_t slice_count, int* error);
 
-  int OnProducerPost(Message& message, LocalFence acquire_fence,
-                     BufferWrapper<std::vector<std::uint8_t>> metadata);
-  LocalFence OnProducerGain(Message& message);
+  pdx::Status<void> OnProducerPost(
+      Message& message, LocalFence acquire_fence,
+      BufferWrapper<std::vector<std::uint8_t>> metadata);
+  pdx::Status<LocalFence> OnProducerGain(Message& message);
 
   ProducerChannel(const ProducerChannel&) = delete;
   void operator=(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7952642..dc2a47e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -1,24 +1,27 @@
 #include "producer_queue_channel.h"
 
+#include <inttypes.h>
+
 #include "consumer_queue_channel.h"
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
+using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::RemoteChannelHandle;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
 namespace dvr {
 
-ProducerQueueChannel::ProducerQueueChannel(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error)
+ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
+                                           int channel_id,
+                                           size_t meta_size_bytes,
+                                           const UsagePolicy& usage_policy,
+                                           int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
       meta_size_bytes_(meta_size_bytes),
-      usage_set_mask_(usage_set_mask),
-      usage_clear_mask_(usage_clear_mask),
-      usage_deny_set_mask_(usage_deny_set_mask),
-      usage_deny_clear_mask_(usage_deny_clear_mask),
+      usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
 }
@@ -26,28 +29,34 @@
 ProducerQueueChannel::~ProducerQueueChannel() {}
 
 /* static */
-std::shared_ptr<ProducerQueueChannel> ProducerQueueChannel::Create(
+Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
     BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error) {
+    const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
-  if (usage_deny_set_mask & usage_deny_clear_mask) {
+  if ((usage_policy.producer_deny_set_mask &
+       usage_policy.producer_deny_clear_mask) ||
+      (usage_policy.consumer_deny_set_mask &
+       usage_policy.consumer_deny_clear_mask)) {
     ALOGE(
         "BufferHubService::OnCreateProducerQueue: illegal usage mask "
-        "configuration: usage_deny_set_mask=%d, usage_deny_clear_mask=%d",
-        usage_deny_set_mask, usage_deny_clear_mask);
-    *error = -EINVAL;
-    return nullptr;
+        "configuration: producer_deny_set_mask=%" PRIx64
+        " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
+        " consumer_deny_clear_mask=%" PRIx64,
+        usage_policy.producer_deny_set_mask,
+        usage_policy.producer_deny_clear_mask,
+        usage_policy.consumer_deny_set_mask,
+        usage_policy.consumer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
   }
 
+  int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-      usage_deny_set_mask, usage_deny_clear_mask, error));
-  if (*error < 0)
-    return nullptr;
+      service, channel_id, meta_size_bytes, usage_policy, &error));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 bool ProducerQueueChannel::HandleMessage(Message& message) {
@@ -58,6 +67,11 @@
           *this, &ProducerQueueChannel::OnCreateConsumerQueue, message);
       return true;
 
+    case BufferHubRPC::GetQueueInfo::Opcode:
+      DispatchRemoteMethod<BufferHubRPC::GetQueueInfo>(
+          *this, &ProducerQueueChannel::OnGetQueueInfo, message);
+      return true;
+
     case BufferHubRPC::ProducerQueueAllocateBuffers::Opcode:
       DispatchRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
           *this, &ProducerQueueChannel::OnProducerQueueAllocateBuffers,
@@ -80,12 +94,11 @@
 
 BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
   return BufferInfo(channel_id(), consumer_channels_.size(), capacity_,
-                    usage_set_mask_, usage_clear_mask_, usage_deny_set_mask_,
-                    usage_deny_clear_mask_);
+                    usage_policy_);
 }
 
-std::pair<RemoteChannelHandle, size_t>
-ProducerQueueChannel::OnCreateConsumerQueue(Message& message) {
+Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
+    Message& message) {
   ATRACE_NAME("ProducerQueueChannel::OnCreateConsumerQueue");
   ALOGD_IF(TRACE, "ProducerQueueChannel::OnCreateConsumerQueue: channel_id=%d",
            channel_id());
@@ -97,7 +110,7 @@
         "ProducerQueueChannel::OnCreateConsumerQueue: failed to push consumer "
         "channel: %s",
         status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, status.error(), {});
+    return ErrorStatus(ENOMEM);
   }
 
   const auto channel_status = service()->SetChannel(
@@ -108,18 +121,21 @@
         "ProducerQueueChannel::OnCreateConsumerQueue: failed to set new "
         "consumer channel: %s",
         channel_status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, channel_status.error(), {});
+    return ErrorStatus(ENOMEM);
   }
 
-  return std::make_pair(status.take(), meta_size_bytes_);
+  return {status.take()};
 }
 
-std::vector<std::pair<RemoteChannelHandle, size_t>>
-ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
-                                                     int width, int height,
-                                                     int format, int usage,
-                                                     size_t slice_count,
-                                                     size_t buffer_count) {
+Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
+  return {{meta_size_bytes_, buffer_id()}};
+}
+
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
+ProducerQueueChannel::OnProducerQueueAllocateBuffers(
+    Message& message, uint32_t width, uint32_t height, uint32_t format,
+    uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count,
+    size_t buffer_count) {
   ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -129,47 +145,76 @@
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
 
   // Deny buffer allocation violating preset rules.
-  if (usage & usage_deny_set_mask_) {
+  if (producer_usage & usage_policy_.producer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_set_mask, the following bits "
-        "shall not be set: %d.",
-        usage, usage_deny_set_mask_);
-    REPLY_ERROR_RETURN(message, EINVAL, buffer_handles);
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating producer_deny_set_mask, the following "
+        "bits shall not be set: %" PRIx64 ".",
+        producer_usage, usage_policy_.producer_deny_set_mask);
+    return ErrorStatus(EINVAL);
   }
 
-  if (~usage & usage_deny_clear_mask_) {
+  if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_clear_mask, the following bits "
-        "must be set: %d.",
-        usage, usage_deny_clear_mask_);
-    REPLY_ERROR_RETURN(message, EINVAL, buffer_handles);
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating consumer_deny_set_mask, the following "
+        "bits shall not be set: %" PRIx64 ".",
+        consumer_usage, usage_policy_.consumer_deny_set_mask);
+    return ErrorStatus(EINVAL);
   }
 
-  // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
-  // and will overwrite |usage_clear_mask_|.
-  int effective_usage = (usage & ~usage_clear_mask_) | usage_set_mask_;
+  if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
+    ALOGE(
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating producer_deny_clear_mask, the following "
+        "bits must be set: %" PRIx64 ".",
+        producer_usage, usage_policy_.producer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
+  }
+
+  if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
+    ALOGE(
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating consumer_deny_clear_mask, the following "
+        "bits must be set: %" PRIx64 ".",
+        consumer_usage, usage_policy_.consumer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
+  }
+  // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
+  // precedence and will overwrite |usage_policy_.X_clear_mask|.
+  uint64_t effective_producer_usage =
+      (producer_usage & ~usage_policy_.producer_clear_mask) |
+      usage_policy_.producer_set_mask;
+  uint64_t effective_consumer_usage =
+      (consumer_usage & ~usage_policy_.consumer_clear_mask) |
+      usage_policy_.consumer_set_mask;
 
   for (size_t i = 0; i < buffer_count; i++) {
-    auto buffer_handle_slot = AllocateBuffer(message, width, height, format,
-                                             effective_usage, slice_count);
-    if (!buffer_handle_slot.first) {
+    auto status =
+        AllocateBuffer(message, width, height, format, effective_producer_usage,
+                       effective_consumer_usage, slice_count);
+    if (!status) {
       ALOGE(
-          "ProducerQueueChannel::OnProducerQueueAllocateBuffers: failed to "
+          "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
           "allocate new buffer.");
-      REPLY_ERROR_RETURN(message, ENOMEM, buffer_handles);
+      return ErrorStatus(status.error());
     }
-    buffer_handles.emplace_back(std::move(buffer_handle_slot.first),
-                                buffer_handle_slot.second);
+    buffer_handles.push_back(status.take());
   }
 
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
-std::pair<RemoteChannelHandle, size_t> ProducerQueueChannel::AllocateBuffer(
-    Message& message, int width, int height, int format, int usage,
-    size_t slice_count) {
+Status<std::pair<RemoteChannelHandle, size_t>>
+ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint64_t producer_usage,
+                                     uint64_t consumer_usage,
+                                     size_t slice_count) {
   ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d",
@@ -177,7 +222,7 @@
 
   if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) {
     ALOGE("ProducerQueueChannel::AllocateBuffer: reaches kMaxQueueCapacity.");
-    return {};
+    return ErrorStatus(E2BIG);
   }
 
   // Here we are creating a new BufferHubBuffer, initialize the producer
@@ -189,25 +234,28 @@
   if (!status) {
     ALOGE("ProducerQueueChannel::AllocateBuffer: failed to push channel: %s",
           status.GetErrorMessage().c_str());
-    return {};
+    return ErrorStatus(status.error());
   }
 
   ALOGD_IF(TRACE,
-           "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%d "
-           "height=%d format=%d usage=%d slice_count=%zu",
-           buffer_id, width, height, format, usage, slice_count);
+           "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
+           "height=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " slice_count=%zu",
+           buffer_id, width, height, format, producer_usage, consumer_usage,
+           slice_count);
   auto buffer_handle = status.take();
 
-  int error;
-  const auto producer_channel = ProducerChannel::Create(
-      service(), buffer_id, width, height, format, usage,
-      meta_size_bytes_, slice_count, &error);
-  if (!producer_channel) {
+  auto producer_channel_status = ProducerChannel::Create(
+      service(), buffer_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes_, slice_count);
+  if (!producer_channel_status) {
     ALOGE(
-        "ProducerQueueChannel::AllocateBuffer: Failed to create "
-        "BufferHubBuffer producer!!");
-    return {};
+        "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
+        "buffer: %s",
+        producer_channel_status.GetErrorMessage().c_str());
+    return ErrorStatus(ENOMEM);
   }
+  auto producer_channel = producer_channel_status.take();
 
   ALOGD_IF(
       TRACE,
@@ -221,7 +269,7 @@
         "ProducerQueueChannel::AllocateBuffer: failed to set producer channel "
         "for new BufferHubBuffer: %s",
         channel_status.GetErrorMessage().c_str());
-    return {};
+    return ErrorStatus(ENOMEM);
   }
 
   // Register the newly allocated buffer's channel_id into the first empty
@@ -235,7 +283,7 @@
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new "
         "buffer allocation.");
-    return {};
+    return ErrorStatus(E2BIG);
   }
 
   buffers_[slot] = producer_channel;
@@ -250,29 +298,29 @@
     consumer_channel->RegisterNewBuffer(producer_channel, slot);
   }
 
-  return {std::move(buffer_handle), slot};
+  return {{std::move(buffer_handle), slot}};
 }
 
-int ProducerQueueChannel::OnProducerQueueDetachBuffer(Message& /*message*/,
-                                                      size_t slot) {
+Status<void> ProducerQueueChannel::OnProducerQueueDetachBuffer(
+    Message& /*message*/, size_t slot) {
   if (buffers_[slot].expired()) {
     ALOGE(
         "ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach "
         "an invalid buffer producer at slot %zu",
         slot);
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   if (capacity_ == 0) {
     ALOGE(
         "ProducerQueueChannel::OnProducerQueueDetachBuffer: trying to detach a "
         "buffer producer while the queue's capacity is already zero.");
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   buffers_[slot].reset();
   capacity_--;
-  return 0;
+  return {};
 }
 
 void ProducerQueueChannel::AddConsumer(ConsumerQueueChannel* channel) {
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 49611d4..09b0243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -3,6 +3,7 @@
 
 #include "buffer_hub.h"
 
+#include <pdx/status.h>
 #include <private/dvr/bufferhub_rpc.h>
 
 namespace android {
@@ -10,17 +11,13 @@
 
 class ProducerQueueChannel : public BufferHubChannel {
  public:
-  using Message = pdx::Message;
-  using RemoteChannelHandle = pdx::RemoteChannelHandle;
-
-  static std::shared_ptr<ProducerQueueChannel> Create(
+  static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
       BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-      int usage_deny_clear_mask, int* error);
+      const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
-  bool HandleMessage(Message& message) override;
-  void HandleImpulse(Message& message) override;
+  bool HandleMessage(pdx::Message& message) override;
+  void HandleImpulse(pdx::Message& message) override;
 
   BufferInfo GetBufferInfo() const override;
 
@@ -28,38 +25,41 @@
   // producer queue.
   // Returns a handle for the service channel, as well as the size of the
   // metadata associated with the queue.
-  std::pair<RemoteChannelHandle, size_t> OnCreateConsumerQueue(
-      Message& message);
+  pdx::Status<pdx::RemoteChannelHandle> OnCreateConsumerQueue(
+      pdx::Message& message);
+
+  pdx::Status<QueueInfo> OnGetQueueInfo(pdx::Message& message);
 
   // Allocate a new BufferHubProducer according to the input spec. Client may
   // handle this as if a new producer is created through kOpCreateBuffer.
-  std::vector<std::pair<RemoteChannelHandle, size_t>>
-  OnProducerQueueAllocateBuffers(Message& message, int width, int height,
-                                 int format, int usage, size_t slice_count,
+  pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
+  OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
+                                 uint32_t height, uint32_t format,
+                                 uint64_t producer_usage,
+                                 uint64_t consumer_usage, size_t slice_count,
                                  size_t buffer_count);
 
   // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
   // be in Gain'ed state for the producer queue to detach.
-  int OnProducerQueueDetachBuffer(Message& message, size_t slot);
+  pdx::Status<void> OnProducerQueueDetachBuffer(pdx::Message& message,
+                                                size_t slot);
 
   void AddConsumer(ConsumerQueueChannel* channel);
   void RemoveConsumer(ConsumerQueueChannel* channel);
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, int usage_set_mask,
-                       int usage_clear_mask, int usage_deny_set_mask,
-                       int usage_deny_clear_mask, int* error);
+                       size_t meta_size_bytes, 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
   // and our return type is a RemoteChannelHandle.
-  // Returns the remote channdel handle and the slot number for the newly
+  // Returns the remote channel handle and the slot number for the newly
   // allocated buffer.
-  std::pair<RemoteChannelHandle, size_t> AllocateBuffer(Message& message,
-                                                        int width, int height,
-                                                        int format, int usage,
-                                                        size_t slice_count);
+  pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
+      pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
+      uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
 
   // 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
@@ -68,10 +68,7 @@
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
-  int usage_set_mask_;
-  int usage_clear_mask_;
-  int usage_deny_set_mask_;
-  int usage_deny_clear_mask_;
+  UsagePolicy usage_policy_;
 
   // Provides access to the |channel_id| of all consumer channels associated
   // with this producer.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 629d65b..b94d333 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -56,7 +56,7 @@
     "libvr_hwc-binder",
   ],
   shared_libs: [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libbase",
     "libbinder",
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
index 999d71e..15f63fa 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -7,41 +7,6 @@
 
 namespace android {
 namespace dvr {
-namespace {
-
-sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
-
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  // Need to register |handle| otherwise we can't read its properties.
-  if (mapper.registerBuffer(handle) != OK) {
-    ALOGE("Failed to register buffer");
-    return nullptr;
-  }
-
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-
-  return buffer;
-}
-
-}  // namespace
 
 ParcelableComposerLayer::ParcelableComposerLayer() {}
 
@@ -54,7 +19,7 @@
   status_t ret = parcel->writeUint64(layer_.id);
   if (ret != OK) return ret;
 
-  ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+  ret = parcel->write(*layer_.buffer);
   if (ret != OK) return ret;
 
   ret = parcel->writeBool(layer_.fence->isValid());
@@ -108,11 +73,12 @@
   status_t ret = parcel->readUint64(&layer_.id);
   if (ret != OK) return ret;
 
-  native_handle* handle = parcel->readNativeHandle();
-  if (!handle) return BAD_VALUE;
-
-  layer_.buffer = GetBufferFromHandle(handle);
-  if (!layer_.buffer.get()) return BAD_VALUE;
+  layer_.buffer = new GraphicBuffer();
+  ret = parcel->read(*layer_.buffer);
+  if (ret != OK) {
+    layer_.buffer.clear();
+    return ret;
+  }
 
   bool has_fence = 0;
   ret = parcel->readBool(&has_fence);
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index ba0821b..638c9a8 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -51,8 +51,6 @@
           -DTRACE=0
 
 include $(CLEAR_VARS)
-# Don't strip symbols so we see stack traces in logcat.
-LOCAL_STRIP_MODULE := false
 LOCAL_SRC_FILES := $(sourceFiles)
 LOCAL_CFLAGS := $(cFlags)
 LOCAL_STATIC_LIBRARIES := $(staticLibraries)
diff --git a/services/vr/sensord/pose_service.cpp b/services/vr/sensord/pose_service.cpp
index 7534732..e3f8171 100644
--- a/services/vr/sensord/pose_service.cpp
+++ b/services/vr/sensord/pose_service.cpp
@@ -65,8 +65,7 @@
 static constexpr int kDatasetIdLength = 36;
 static constexpr char kDatasetIdChars[] = "0123456789abcdef-";
 
-static constexpr int kLatencyWindowSize = 100;
-static constexpr double kLatencyWindowMass = 0.5;
+static constexpr int kLatencyWindowSize = 200;
 
 // These are the flags used by BufferProducer::CreatePersistentUncachedBlob,
 // plus PRIVATE_ADSP_HEAP to allow access from the DSP.
@@ -115,7 +114,7 @@
       photon_timestamp_(0),
       // Will be updated by external service, but start with a non-zero value:
       display_period_ns_(16000000),
-      sensor_latency_(kLatencyWindowSize, kLatencyWindowMass) {
+      sensor_latency_(kLatencyWindowSize) {
   last_known_pose_ = {
       .orientation = {1.0f, 0.0f, 0.0f, 0.0f},
       .translation = {0.0f, 0.0f, 0.0f, 0.0f},
diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp
index 68f1d70..55ac9bf 100644
--- a/services/vr/virtual_touchpad/main.cpp
+++ b/services/vr/virtual_touchpad/main.cpp
@@ -8,8 +8,9 @@
 
 int main() {
   ALOGI("Starting");
-  android::dvr::VirtualTouchpadService touchpad_service(
-      std::move(android::dvr::VirtualTouchpadEvdev::Create()));
+  android::sp<android::dvr::VirtualTouchpadService> touchpad_service =
+      new android::dvr::VirtualTouchpadService(
+          android::dvr::VirtualTouchpadEvdev::Create());
 
   signal(SIGPIPE, SIG_IGN);
   android::sp<android::ProcessState> ps(android::ProcessState::self());
@@ -19,8 +20,8 @@
 
   android::sp<android::IServiceManager> sm(android::defaultServiceManager());
   const android::status_t service_status =
-      sm->addService(android::String16(touchpad_service.SERVICE_NAME()),
-                     &touchpad_service, false /*allowIsolated*/);
+      sm->addService(android::String16(touchpad_service->SERVICE_NAME()),
+                     touchpad_service, false /*allowIsolated*/);
   if (service_status != android::OK) {
     ALOGE("virtual touchpad service not added: %d",
           static_cast<int>(service_status));
diff --git a/services/vr/vr_window_manager/Android.bp b/services/vr/vr_window_manager/Android.bp
index 0406331..669426b 100644
--- a/services/vr/vr_window_manager/Android.bp
+++ b/services/vr/vr_window_manager/Android.bp
@@ -47,7 +47,7 @@
 ]
 
 shared_libs = [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libvrhwc",
     "libbase",
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index b2f02e5..8b4460a 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -206,8 +206,9 @@
     if (fade_value_ > 1.0f)
       fade_value_ = 1.0f;
 
-    controller_position_ = elbow_model_.Update(delta, last_pose_.GetRotation(),
-                                               controller_orientation_, false);
+    controller_position_ =
+        elbow_model_.Update(delta, last_pose_.GetRotation(),
+                            controller_orientation_, should_recenter_);
 
     dvrBeginRenderFrameEds(graphics_context_, pose.orientation,
                            pose.translation);
@@ -233,6 +234,7 @@
     OnEndFrame();
 
     dvrPresent(graphics_context_);
+    should_recenter_ = false;
   }
 }
 
diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h
index 4b36ecc..ed99157 100644
--- a/services/vr/vr_window_manager/application.h
+++ b/services/vr/vr_window_manager/application.h
@@ -80,6 +80,9 @@
   bool shmem_controller_active_ = false;
   uint64_t shmem_controller_buttons_;
 
+  // Used to center the scene when the shell becomes visible.
+  bool should_recenter_ = true;
+
   bool is_visible_ = false;
   std::chrono::time_point<std::chrono::system_clock> visibility_button_press_;
   bool debug_mode_ = false;
diff --git a/services/vr/vr_window_manager/composer/1.0/Android.bp b/services/vr/vr_window_manager/composer/1.0/Android.bp
deleted file mode 100644
index 58f83f8..0000000
--- a/services/vr/vr_window_manager/composer/1.0/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-genrule {
-    name: "android.dvr.composer@1.0_genc++",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
-    srcs: [
-        "IVrComposerClient.hal",
-    ],
-    out: [
-        "android/dvr/composer/1.0/VrComposerClientAll.cpp",
-    ],
-}
-
-genrule {
-    name: "android.dvr.composer@1.0_genc++_headers",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hidl:system/libhidl/transport -randroid.hardware:hardware/interfaces/ -randroid.dvr:frameworks/native/services/vr/vr_window_manager android.dvr.composer@1.0",
-    srcs: [
-        "IVrComposerClient.hal",
-    ],
-    out: [
-        "android/dvr/composer/1.0/IVrComposerClient.h",
-        "android/dvr/composer/1.0/IHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BnHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BpHwVrComposerClient.h",
-        "android/dvr/composer/1.0/BsVrComposerClient.h",
-    ],
-}
-
-cc_library_shared {
-    name: "android.dvr.composer@1.0",
-    generated_sources: ["android.dvr.composer@1.0_genc++"],
-    generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
-    export_generated_headers: ["android.dvr.composer@1.0_genc++_headers"],
-    shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libutils",
-        "libcutils",
-        "android.hardware.graphics.composer@2.1",
-        "android.hidl.base@1.0",
-    ],
-    export_shared_lib_headers: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "android.hardware.graphics.composer@2.1",
-        "android.hidl.base@1.0",
-    ],
-}
diff --git a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal b/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
deleted file mode 100644
index 230a68a..0000000
--- a/services/vr/vr_window_manager/composer/1.0/IVrComposerClient.hal
+++ /dev/null
@@ -1,49 +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.
- */
-package android.dvr.composer@1.0;
-
-import android.hardware.graphics.composer@2.1::IComposerClient;
-
-interface IVrComposerClient
-    extends android.hardware.graphics.composer@2.1::IComposerClient {
-    /*
-     * Used to annotate the layer with additional information, which will be
-     * used to describe the content of the layer (ie: notification, permission,
-     * etc) which allows VR window manager to treat certain layer types
-     * specially.
-     *
-     * @param display is the display on which the layer was created.
-     * @param layer is the layer affected by the change.
-     * @param layer_type the type of the layer as described by the window
-     * manager.
-     * @param application_id the application id the layer belongs to.
-     * @return error is NONE upon success. Otherwise,
-     *         BAD_DISPLAY when an invalid display handle was passed in.
-     *         BAD_LAYER when an invalid layer handle was passed in.
-     *
-     * setLayerInfo(Display display,
-     *              Layer layer,
-     *              uint32_t layer_type,
-     *              uint32_t application_id)
-     *     generates(Error error);
-     */
-
-    enum VrCommand : int32_t {
-        OPCODE_SHIFT         = android.hardware.graphics.composer@2.1::IComposerClient.Command:OPCODE_SHIFT,
-
-        SET_LAYER_INFO = 0x800 << OPCODE_SHIFT,
-    };
-};
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index f28818a..1998749 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -1,7 +1,3 @@
-subdirs = [
-  "1.0",
-]
-
 cc_library_shared {
   name: "libvrhwc",
 
@@ -14,13 +10,13 @@
   static_libs: [
     "libhwcomposer-client",
     "libdisplay",
-    "libpdx_default_transport",
-    "libbufferhub",
     "libbufferhubqueue",
+    "libbufferhub",
+    "libpdx_default_transport",
   ],
 
   shared_libs: [
-    "android.dvr.composer@1.0",
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "libbase",
     "libcutils",
@@ -39,6 +35,7 @@
   ],
 
   export_shared_lib_headers: [
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
   ],
 
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
index 367acb7..e0bdf1c 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <android/dvr/composer/1.0/IVrComposerClient.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
 #include <log/log.h>
@@ -26,7 +26,7 @@
 namespace dvr {
 
 using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::dvr::composer::V1_0::IVrComposerClient;
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
 
 VrComposerClient::VrComposerClient(dvr::VrHwc& hal)
     : ComposerClient(hal), mVrHal(hal) {}
@@ -50,6 +50,10 @@
   switch (vrCommand) {
     case IVrComposerClient::VrCommand::SET_LAYER_INFO:
       return parseSetLayerInfo(length);
+    case IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA:
+      return parseSetClientTargetMetadata(length);
+    case IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA:
+      return parseSetLayerBufferMetadata(length);
     default:
       return CommandReader::parseCommand(command, length);
   }
@@ -68,5 +72,43 @@
   return true;
 }
 
+bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setClientTargetMetadata(mDisplay, readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setLayerBufferMetadata(mDisplay, mLayer,
+                                           readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+IVrComposerClient::BufferMetadata
+VrComposerClient::VrCommandReader::readBufferMetadata() {
+  IVrComposerClient::BufferMetadata metadata = {
+    .width = read(),
+    .height = read(),
+    .stride = read(),
+    .layerCount = read(),
+    .format = static_cast<PixelFormat>(readSigned()),
+    .usage = read64(),
+  };
+  return metadata;
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
index 8f0c562..8d601ab 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
@@ -17,6 +17,7 @@
 #ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
 #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <ComposerClient.h>
 #include <IComposerCommandBuffer.h>
 
@@ -44,6 +45,10 @@
 
    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;
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index d142729..5efc482 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -16,8 +16,6 @@
 #include "vr_hwc.h"
 
 #include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
 
 #include <mutex>
 
@@ -43,41 +41,19 @@
 const Display kDefaultDisplayId = 1;
 const Config kDefaultConfigId = 1;
 
-sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
+sp<GraphicBuffer> CreateGraphicBuffer(
+    const native_handle_t* handle,
+    const IVrComposerClient::BufferMetadata& metadata) {
+   sp<GraphicBuffer> buffer = new GraphicBuffer(
+      handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
+      static_cast<int32_t>(metadata.format), metadata.layerCount,
+      metadata.usage, metadata.usage, metadata.stride);
+   if (buffer->initCheck() != OK) {
+     ALOGE("Failed to create graphic buffer");
+     return nullptr;
+   }
 
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  // Need to register |handle| otherwise we can't read its properties.
-  if (mapper.registerBuffer(handle) != OK) {
-    ALOGE("Failed to register buffer");
-    return nullptr;
-  }
-
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  // NOTE: Can't re-use |handle| since we don't own it.
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::CLONE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-  if (buffer->initCheck() != OK) {
-    ALOGE("Failed to register cloned buffer");
-    return nullptr;
-  }
-
-  return buffer;
+   return buffer;
 }
 
 void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -115,12 +91,17 @@
 bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
                                  base::unique_fd fence) {
   if (handle)
-    buffer_ = GetBufferFromHandle(handle);
+    buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);
 
   fence_ = new Fence(fence.release());
   return true;
 }
 
+void HwcDisplay::SetClientTargetMetadata(
+    const IVrComposerClient::BufferMetadata& metadata) {
+  buffer_metadata_ = metadata;
+}
+
 HwcLayer* HwcDisplay::CreateLayer() {
   uint64_t layer_id = layer_ids_++;
   layers_.push_back(HwcLayer(layer_id));
@@ -217,19 +198,14 @@
       queued_client_target = true;
     } else {
       if (!layer.info.buffer.get() || !layer.info.fence.get()) {
-        ALOGE("Layer requested without valid buffer");
-        return Error::BAD_LAYER;
+        ALOGV("Layer requested without valid buffer");
+        continue;
       }
 
       frame.push_back(layer.info);
     }
   }
 
-  if (frame.empty()) {
-    ALOGE("Requested frame with no layers");
-    return Error::BAD_LAYER;
-  }
-
   out_frames->swap(frame);
   return Error::NONE;
 }
@@ -564,7 +540,8 @@
   if (!hwc_layer)
     return Error::BAD_LAYER;
 
-  hwc_layer->info.buffer = GetBufferFromHandle(buffer);
+  hwc_layer->info.buffer = CreateGraphicBuffer(
+      buffer, hwc_layer->buffer_metadata);
   hwc_layer->info.fence = new Fence(fence.release());
 
   return Error::NONE;
@@ -730,6 +707,35 @@
   return Error::NONE;
 }
 
+Error VrHwc::setClientTargetMetadata(
+    Display display, const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  display_ptr->SetClientTargetMetadata(metadata);
+
+  return Error::NONE;
+}
+
+Error VrHwc::setLayerBufferMetadata(
+    Display display, Layer layer,
+    const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->buffer_metadata = metadata;
+
+  return Error::NONE;
+}
+
 Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
   hidl_cb(hidl_vec<Capability>());
   return Void();
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.h b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
index bfca9a6..3da2fb8 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
@@ -17,6 +17,7 @@
 #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
 
 #include <android-base/unique_fd.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <ComposerBase.h>
 #include <ui/Fence.h>
@@ -26,6 +27,7 @@
 #include <mutex>
 #include <unordered_map>
 
+using namespace android::frameworks::vr::composer::V1_0;
 using namespace android::hardware::graphics::common::V1_0;
 using namespace android::hardware::graphics::composer::V2_1;
 
@@ -38,7 +40,6 @@
 namespace android {
 
 class Fence;
-class GraphicBuffer;
 
 namespace dvr {
 
@@ -105,6 +106,7 @@
   Composition composition_type;
   uint32_t z_order;
   ComposerView::ComposerLayer info;
+  IVrComposerClient::BufferMetadata buffer_metadata;
 };
 
 class HwcDisplay {
@@ -120,6 +122,8 @@
   HwcLayer* GetLayer(Layer id);
 
   bool SetClientTarget(const native_handle_t* handle, base::unique_fd fence);
+  void SetClientTargetMetadata(
+      const IVrComposerClient::BufferMetadata& metadata);
 
   void GetChangedCompositionTypes(
       std::vector<Layer>* layer_ids,
@@ -131,8 +135,8 @@
 
  private:
   // The client target buffer and the associated fence.
-  // TODO(dnicoara): Replace this with a list of ComposerView::ComposerLayer.
   sp<GraphicBuffer> buffer_;
+  IVrComposerClient::BufferMetadata buffer_metadata_;
   sp<Fence> fence_;
 
   // List of currently active layers.
@@ -159,6 +163,11 @@
 
   Error setLayerInfo(Display display, Layer layer, uint32_t type,
                      uint32_t appId);
+  Error setClientTargetMetadata(
+      Display display, const IVrComposerClient::BufferMetadata& metadata);
+  Error setLayerBufferMetadata(
+      Display display, Layer layer,
+      const IVrComposerClient::BufferMetadata& metadata);
 
   // ComposerBase
   void removeClient() override;
diff --git a/services/vr/vr_window_manager/display_view.cpp b/services/vr/vr_window_manager/display_view.cpp
index 52984b7..88768a0 100644
--- a/services/vr/vr_window_manager/display_view.cpp
+++ b/services/vr/vr_window_manager/display_view.cpp
@@ -219,6 +219,11 @@
       visibility = ViewMode::Hidden;
       current_vr_app_ = app;
     }
+  } else if ((use_2dmode_ || !is_vr_active) && app != 0 &&
+             visibility == ViewMode::Hidden) {
+    // This is the case for the VR app launching a 2D intent of itself on some
+    // display.
+    visibility = ViewMode::App;
   } else if (!current_vr_app_) {
     // The VR app is running.
     current_vr_app_ = app;
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 850f604..2b53cd6 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -327,7 +327,6 @@
     // Position the quad horizontally aligned in the direction the user
     // is facing, effectively taking out head roll.
     displays_[0]->Recenter(GetHorizontallyAlignedMatrixFromPose(last_pose_));
-    should_recenter_ = false;
   }
 
   for (auto& display : displays_) {
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index be2ae58..d90e833 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -84,9 +84,6 @@
   bool is_touching_ = false;
   int touchpad_buttons_ = 0;
 
-  // Used to center the scene when the shell becomes visible.
-  bool should_recenter_ = true;
-
   std::mutex display_frame_mutex_;
 
   std::vector<std::unique_ptr<DisplayView>> displays_;
diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp
index 6636dc5..9d7afe3 100644
--- a/services/vr/vr_window_manager/vr_window_manager.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager.cpp
@@ -20,20 +20,20 @@
   LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status);
 
   // Create vr_wm_binder.
-  android::service::vr::VrWindowManagerBinder vr_wm_binder(app);
-  const int status = vr_wm_binder.Initialize();
+  android::sp<android::service::vr::VrWindowManagerBinder> vr_wm_binder =
+      new android::service::vr::VrWindowManagerBinder(app);
+  const int status = vr_wm_binder->Initialize();
   LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
 
   android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-  const android::status_t vr_wm_binder_status =
-      sm->addService(
-          android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
-          &vr_wm_binder, false /*allowIsolated*/);
+  const android::status_t vr_wm_binder_status = sm->addService(
+      android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
+      vr_wm_binder, false /*allowIsolated*/);
   LOG_ALWAYS_FATAL_IF(vr_wm_binder_status != android::OK,
                       "vr_wm_binder service not added: %d",
                       static_cast<int>(vr_wm_binder_status));
 
-  app.SetControllerDataProvider(&vr_wm_binder);
+  app.SetControllerDataProvider(vr_wm_binder.get());
 
   android::hardware::ProcessState::self()->startThreadPool();
 
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3fd8c51..91c270e 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
 cc_library_headers {
     name: "vulkan_headers",
     export_include_dirs: ["include"],
+    vendor_available: true,
 }
 
 subdirs = [
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..6149894 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
 
 // Headers module is in frameworks/native/vulkan/Android.bp.
 ndk_library {
-    name: "libvulkan.ndk",
+    name: "libvulkan",
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
     unversioned_until: "current",
@@ -78,6 +78,7 @@
         "libutils",
         "libcutils",
         "libz",
+        "libnativewindow",
     ],
     static_libs: ["libgrallocusage"],
 }
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 5fbf5f5..f2cd8e6 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -34,6 +34,11 @@
 #include "driver.h"
 #include "stubhal.h"
 
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+android_namespace_t* android_get_exported_namespace(const char*);
+}
+
 // Set to true to enable exposing unratified extensions for development
 static const bool kEnableUnratifiedExtensions = false;
 
@@ -150,14 +155,12 @@
     "ro.board.platform",
 }};
 
-int LoadUpdatedDriver(const hw_module_t** module) {
+int LoadDriver(android_namespace_t* library_namespace,
+               const hwvulkan_module_t** module) {
     const android_dlextinfo dlextinfo = {
         .flags = ANDROID_DLEXT_USE_NAMESPACE,
-        .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+        .library_namespace = library_namespace,
     };
-    if (!dlextinfo.library_namespace)
-        return -ENOENT;
-
     void* so = nullptr;
     char prop[PROPERTY_VALUE_MAX];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
@@ -171,7 +174,7 @@
     if (!so)
         return -ENOENT;
 
-    hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+    auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
     if (!hmi) {
         ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
         dlclose(so);
@@ -183,11 +186,24 @@
         return -EINVAL;
     }
     hmi->dso = so;
-    *module = hmi;
-    ALOGD("loaded updated driver");
+    *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
     return 0;
 }
 
+int LoadBuiltinDriver(const hwvulkan_module_t** module) {
+    auto ns = android_get_exported_namespace("sphal");
+    if (!ns)
+        return -ENOENT;
+    return LoadDriver(ns, module);
+}
+
+int LoadUpdatedDriver(const hwvulkan_module_t** module) {
+    auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+    if (!ns)
+        return -ENOENT;
+    return LoadDriver(ns, module);
+}
+
 bool Hal::Open() {
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
 
@@ -197,9 +213,21 @@
     int result;
     const hwvulkan_module_t* module = nullptr;
 
-    result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+    result = LoadUpdatedDriver(&module);
     if (result == -ENOENT) {
-        result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+        result = LoadBuiltinDriver(&module);
+        if (result != 0) {
+            // -ENOENT means the sphal namespace doesn't exist, not that there
+            // is a problem with the driver.
+            ALOGW_IF(
+                result != -ENOENT,
+                "Failed to load Vulkan driver into sphal namespace. This "
+                "usually means the driver has forbidden library dependencies."
+                "Please fix, this will soon stop working.");
+            result =
+                hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
+                              reinterpret_cast<const hw_module_t**>(&module));
+        }
     }
     if (result != 0) {
         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
@@ -789,9 +817,6 @@
     loader_extensions.push_back({
         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
-    loader_extensions.push_back({
-        VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
-        VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
 
     if (kEnableUnratifiedExtensions) {
         // conditionally add shared_presentable_image if supportable
@@ -804,6 +829,16 @@
         }
     }
 
+    // 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) {
+        loader_extensions.push_back({
+                VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
+                VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
+    }
+
     // enumerate our extensions first
     if (!pLayerName && pProperties) {
         uint32_t count = std::min(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
           native_frame_id_(nativeFrameId) {}
     bool ready() const {
-        return (timestamp_desired_present_time_ &&
-                timestamp_actual_present_time_ &&
-                timestamp_render_complete_time_ &&
-                timestamp_composition_latch_time_);
+        return (timestamp_desired_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_actual_present_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_render_complete_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING &&
+                timestamp_composition_latch_time_ !=
+                        NATIVE_WINDOW_TIMESTAMP_PENDING);
     }
-    void calculate(uint64_t rdur) {
-        vals_.actualPresentTime = timestamp_actual_present_time_;
-        uint64_t margin = (timestamp_composition_latch_time_ -
+    void calculate(int64_t rdur) {
+        bool anyTimestampInvalid =
+                (timestamp_actual_present_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_render_complete_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+                (timestamp_composition_latch_time_ ==
+                        NATIVE_WINDOW_TIMESTAMP_INVALID);
+        if (anyTimestampInvalid) {
+            ALOGE("Unexpectedly received invalid timestamp.");
+            vals_.actualPresentTime = 0;
+            vals_.earliestPresentTime = 0;
+            vals_.presentMargin = 0;
+            return;
+        }
+
+        vals_.actualPresentTime =
+                static_cast<uint64_t>(timestamp_actual_present_time_);
+        int64_t margin = (timestamp_composition_latch_time_ -
                            timestamp_render_complete_time_);
         // Calculate vals_.earliestPresentTime, and potentially adjust
         // vals_.presentMargin.  The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
         // it did (per the extension specification).  If for some reason, we
         // can do this subtraction repeatedly, we do, since
         // vals_.earliestPresentTime really is supposed to be the "earliest".
-        uint64_t early_time = vals_.actualPresentTime;
+        int64_t early_time = timestamp_actual_present_time_;
         while ((margin > rdur) &&
                ((early_time - rdur) > timestamp_composition_latch_time_)) {
             early_time -= rdur;
             margin -= rdur;
         }
-        vals_.earliestPresentTime = early_time;
-        vals_.presentMargin = margin;
+        vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+        vals_.presentMargin = static_cast<uint64_t>(margin);
     }
     void get_values(VkPastPresentationTimingGOOGLE* values) const {
         *values = vals_;
@@ -149,10 +169,11 @@
     VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
 
     uint64_t native_frame_id_ { 0 };
-    uint64_t timestamp_desired_present_time_ { 0 };
-    uint64_t timestamp_actual_present_time_ { 0 };
-    uint64_t timestamp_render_complete_time_ { 0 };
-    uint64_t timestamp_composition_latch_time_ { 0 };
+    int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+    int64_t timestamp_composition_latch_time_
+            { NATIVE_WINDOW_TIMESTAMP_PENDING };
 };
 
 // ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
           shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
                  present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
         ANativeWindow* window = surface.window.get();
-        int64_t rdur;
         native_window_get_refresh_cycle_duration(
             window,
-            &rdur);
-        refresh_duration = static_cast<uint64_t>(rdur);
+            &refresh_duration);
     }
 
     Surface& surface;
     uint32_t num_images;
     bool mailbox_mode;
     bool frame_timestamps_enabled;
-    uint64_t refresh_duration;
+    int64_t refresh_duration;
     bool shared;
 
     struct Image {
@@ -327,14 +346,10 @@
 
         // Record the timestamp(s) we received, and then see if this TimingInfo
         // is ready to be reported to the user:
-        ti.timestamp_desired_present_time_ =
-            static_cast<uint64_t>(desired_present_time);
-        ti.timestamp_actual_present_time_ =
-            static_cast<uint64_t>(actual_present_time);
-        ti.timestamp_render_complete_time_ =
-            static_cast<uint64_t>(render_complete_time);
-        ti.timestamp_composition_latch_time_ =
-               static_cast<uint64_t>(composition_latch_time);
+        ti.timestamp_desired_present_time_ = desired_present_time;
+        ti.timestamp_actual_present_time_ = actual_present_time;
+        ti.timestamp_render_complete_time_ = render_complete_time;
+        ti.timestamp_composition_latch_time_ = composition_latch_time;
 
         if (ti.ready()) {
             // The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
     Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
     VkResult result = VK_SUCCESS;
 
-    pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+    pDisplayTimingProperties->refreshDuration =
+            static_cast<uint64_t>(swapchain.refresh_duration);
 
     return result;
 }