Merge "Prevent runtime restart for crashed clients to framework sensorservice." into oc-dev
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/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/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/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.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..9229f82 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -46,6 +46,7 @@
     <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" />
 
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 51ea1ca..64e32ff 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -46,6 +46,7 @@
     <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" />
 
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/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/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/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/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/ui/Android.bp b/libs/ui/Android.bp
index 310d25e..ba37391 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -51,8 +51,7 @@
         "FrameStats.cpp",
         "Gralloc1.cpp",
         "Gralloc1On0Adapter.cpp",
-        "GrallocAllocator.cpp",
-        "GrallocMapper.cpp",
+        "Gralloc2.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
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..2f4d5fb 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,82 @@
     }
 }
 
-
-
-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);
+        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 +141,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 +185,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 +242,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/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index aacc385..dfeed50 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_; }
@@ -171,9 +174,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));
   }
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ed11551..7ed024f 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -119,6 +119,14 @@
 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);
+};
+
 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
 // type signatures supported by bufferhubd.
 struct BufferHubRPC {
@@ -151,6 +159,7 @@
     kOpConsumerSetIgnore,
     kOpCreateProducerQueue,
     kOpCreateConsumerQueue,
+    kOpGetQueueInfo,
     kOpProducerQueueAllocateBuffers,
     kOpProducerQueueDetachBuffer,
     kOpConsumerQueueImportBuffers,
@@ -192,18 +201,19 @@
 
   // 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, int usage_set_mask,
+                              int usage_clear_mask, int usage_deny_set_mask,
+                              int usage_deny_clear_mask));
   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,
                         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..ffc42d6 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -60,21 +60,20 @@
   int LockYUV(int 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; }
+
+  const sp<GraphicBuffer>& buffer() const { return buffer_; }
+  buffer_handle_t handle() const {
+    return buffer_.get() ? buffer_->handle : nullptr;
+  }
+  int width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+  int height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+  int layer_count() const {
+    return buffer_.get() ? buffer_->getLayerCount() : 0;
+  }
+  int stride() const { return buffer_.get() ? buffer_->getStride() : 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; }
+  int format() const { return buffer_.get() ? buffer_->getPixelFormat() : 0; }
+  int usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
 
  private:
   sp<GraphicBuffer> buffer_;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 031401a..e491abc 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;
   }
 
@@ -289,15 +319,22 @@
 ProducerQueue::ProducerQueue(size_t meta_size)
     : ProducerQueue(meta_size, 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) {
+    : BASE(BufferHubRPC::kClientPath) {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size_, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
+      meta_size, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
       usage_deny_clear_mask);
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
@@ -305,12 +342,14 @@
     Close(-status.error());
     return;
   }
+
+  SetupQueue(status.get().meta_size_bytes, status.get().id);
 }
 
 int ProducerQueue::AllocateBuffer(int width, int height, int format, int 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;
   }
 
@@ -362,7 +401,7 @@
 }
 
 int ProducerQueue::DetachBuffer(size_t slot) {
-  Status<int> status =
+  auto status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
   if (!status) {
     ALOGE(
@@ -378,7 +417,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 +433,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 +478,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 +495,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 +519,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/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 37cd8c7..2b70c5b 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;
 };
@@ -267,9 +283,8 @@
   }
 
   // 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
@@ -311,18 +326,15 @@
   // 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(LocalChannelHandle handle);
   ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
                 int usage_deny_set_mask, int 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 +345,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 +369,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 +384,7 @@
   int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
                     LocalHandle* acquire_fence) override;
 
-  int OnBufferAllocated() override;
+  Status<void> OnBufferAllocated() override;
 };
 
 }  // namespace dvr
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..6d39cdb 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_;
 }
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/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index f786c29..49702fd 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -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/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/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/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/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..522a8c0
--- /dev/null
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 <private/android_filesystem_config.h> // for AID_CAMERASERVER
+
+#include <log/log.h>
+#include <hwbinder/IPCThreadState.h>
+#include <mediautils/SchedulingPolicyService.h>
+
+namespace android {
+namespace frameworks {
+namespace schedulerservice {
+namespace V1_0 {
+namespace implementation {
+
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
+    using ::android::hardware::IPCThreadState;
+
+    if (priority < static_cast<int32_t>(Priority::MIN) ||
+            priority > static_cast<int32_t>(Priority::MAX)) {
+        return false;
+    }
+
+    if (IPCThreadState::self()->getCallingUid() != AID_CAMERASERVER) {
+        return false;
+    }
+
+    // this should always be allowed since we are in system_server.
+    int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
+    return value == 0 /* success */;
+}
+
+}  // 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..eb5a4ae
--- /dev/null
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -0,0 +1,47 @@
+/*
+ * 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;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace schedulerservice
+}  // namespace frameworks
+}  // namespace android
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index de4950e..2ce60e5 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -16,7 +16,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 +30,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;
@@ -374,7 +374,7 @@
   }
 }
 
-int BufferHubService::OnCreateProducerQueue(
+Status<QueueInfo> 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) {
   // Use the producer channel id as the global queue id.
@@ -386,7 +386,7 @@
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
     ALOGE("BufferHubService::OnCreateProducerQueue: already created: queue=%d",
           queue_id);
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   int error;
@@ -394,10 +394,10 @@
           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;
+    return {{meta_size_bytes, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    return ErrorStatus(-error);
   }
 }
 
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 8a7dca8..150e399 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 {
@@ -73,9 +74,9 @@
           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,
+               int usage_set_mask, int usage_clear_mask,
+               int usage_deny_set_mask, int usage_deny_clear_mask)
         : id(id),
           type(kProducerQueueType),
           consumer_count(consumer_count),
@@ -168,9 +169,9 @@
                                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<QueueInfo> 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);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index ae87acd..cc16f1f 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -40,6 +40,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);
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7952642..7741058 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -3,6 +3,9 @@
 #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;
 
@@ -58,6 +61,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,
@@ -84,8 +92,8 @@
                     usage_deny_clear_mask_);
 }
 
-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 +105,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,13 +116,17 @@
         "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>>
+Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
+  return {{meta_size_bytes_, buffer_id()}};
+}
+
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
 ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
                                                      int width, int height,
                                                      int format, int usage,
@@ -135,7 +147,7 @@
         "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);
+    return ErrorStatus(EINVAL);
   }
 
   if (~usage & usage_deny_clear_mask_) {
@@ -144,7 +156,7 @@
         "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);
+    return ErrorStatus(EINVAL);
   }
 
   // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
@@ -152,24 +164,24 @@
   int effective_usage = (usage & ~usage_clear_mask_) | usage_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_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, int width, int height,
+                                     int format, int usage,
+                                     size_t slice_count) {
   ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d",
@@ -177,7 +189,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,7 +201,7 @@
   if (!status) {
     ALOGE("ProducerQueueChannel::AllocateBuffer: failed to push channel: %s",
           status.GetErrorMessage().c_str());
-    return {};
+    return ErrorStatus(status.error());
   }
 
   ALOGD_IF(TRACE,
@@ -199,14 +211,14 @@
   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);
+  const auto producer_channel =
+      ProducerChannel::Create(service(), buffer_id, width, height, format,
+                              usage, meta_size_bytes_, slice_count, &error);
   if (!producer_channel) {
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Failed to create "
         "BufferHubBuffer producer!!");
-    return {};
+    return ErrorStatus(ENOMEM);
   }
 
   ALOGD_IF(
@@ -221,7 +233,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 +247,7 @@
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new "
         "buffer allocation.");
-    return {};
+    return ErrorStatus(E2BIG);
   }
 
   buffers_[slot] = producer_channel;
@@ -250,29 +262,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..a12a37d 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,14 @@
 
 class ProducerQueueChannel : public BufferHubChannel {
  public:
-  using Message = pdx::Message;
-  using RemoteChannelHandle = pdx::RemoteChannelHandle;
-
   static 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);
   ~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,19 +26,22 @@
   // 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,
+  pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
+  OnProducerQueueAllocateBuffers(pdx::Message& message, int width, int height,
                                  int format, int 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);
@@ -56,10 +57,9 @@
   // and our return type is a RemoteChannelHandle.
   // Returns the remote channdel 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, int width, int height, int format, int 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
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..6e4daa0 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
@@ -10,35 +10,9 @@
 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;
+  // Querying properties from |handle| is never properly supported.
+  ALOGE("Failed to read handle %p properties", handle);
+  return nullptr;
 }
 
 }  // namespace
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/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index d142729..c60a4f5 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -44,40 +44,9 @@
 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;
-
-  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;
+  // Querying properties from |handle| is never properly supported.
+  ALOGE("Failed to read handle %p properties", handle);
+  return nullptr;
 }
 
 void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -217,19 +186,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;
 }
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/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/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..68f09c4 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",
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 5fbf5f5..212d142 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);