Merge "Add private helpers needed for job queue." into oc-dev
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index be1a434..1d21b3c 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
 
 LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_HEADER_LIBRARIES := dex2oat_headers
 LOCAL_SHARED_LIBRARIES := \
     libbase \
     libcutils \
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 82b8cc2..e8e6b56 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -33,6 +33,7 @@
 #include <android-base/strings.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
+#include <dex2oat_return_codes.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
@@ -576,7 +577,11 @@
         }
 
         // If the dexopt failed, we may have a stale boot image from a previous OTA run.
-        // Try to delete and retry.
+        // Then regenerate and retry.
+        if (WEXITSTATUS(dexopt_result) !=
+                static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+            return dexopt_result;
+        }
 
         if (!PrepareBootImage(/* force */ true)) {
             LOG(ERROR) << "Forced boot image creating failed. Original error return was "
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index bd0b224..804afc9 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -6,6 +6,7 @@
 	vrscreencap.cpp
 
 LOCAL_STATIC_LIBRARIES := \
+	libbufferhub \
 	libdisplay \
 	libimageio \
 	libpdx_default_transport \
@@ -14,7 +15,8 @@
 	libcutils \
 	liblog \
 	libpng \
-	libsync
+	libsync \
+	libui \
 
 LOCAL_MODULE := vrscreencap
 
diff --git a/data/etc/android.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/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/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/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/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index bd7c6a1..9ee9838 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -20,6 +20,9 @@
 
 #include <ui/Gralloc1On0Adapter.h>
 
+#include <algorithm>
+#include <array>
+
 #include <grallocusage/GrallocUsageConversion.h>
 
 #include <hardware/gralloc.h>
@@ -67,13 +70,18 @@
 void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
         int32_t* outCapabilities)
 {
+    constexpr std::array<int32_t, 2> supportedCapabilities = {{
+        GRALLOC1_CAPABILITY_ON_ADAPTER,
+        GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE,
+    }};
+
     if (outCapabilities == nullptr) {
-        *outCount = 1;
-        return;
-    }
-    if (*outCount >= 1) {
-        *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
-        *outCount = 1;
+        *outCount = supportedCapabilities.size();
+    } else {
+        *outCount = std::min(*outCount, static_cast<uint32_t>(
+                    supportedCapabilities.size()));
+        std::copy_n(supportedCapabilities.begin(),
+                *outCount, outCapabilities);
     }
 }
 
@@ -325,6 +333,9 @@
         if (result != 0) {
             ALOGE("gralloc0 unregister failed: %d", result);
         }
+
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle_t*>(handle));
     }
 
     mBuffers.erase(handle);
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
new file mode 100644
index 0000000..75f5686
--- /dev/null
+++ b/libs/ui/Gralloc2.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Gralloc2"
+
+#include <ui/Gralloc2.h>
+
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+namespace android {
+
+namespace Gralloc2 {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+Mapper::Mapper()
+{
+    mMapper = IMapper::getService();
+    if (mMapper != nullptr && mMapper->isRemote()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+    }
+}
+
+Error Mapper::createDescriptor(
+        const IMapper::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor* outDescriptor) const
+{
+    Error error;
+    auto ret = mMapper->createDescriptor(descriptorInfo,
+            [&](const auto& tmpError, const auto& tmpDescriptor)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outDescriptor = tmpDescriptor;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+        buffer_handle_t* outBufferHandle) const
+{
+    Error error;
+    auto ret = mMapper->importBuffer(rawHandle,
+            [&](const auto& tmpError, const auto& tmpBuffer)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->freeBuffer(buffer);
+
+    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+    ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
+            buffer, error);
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, void** outData) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpData)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outData = tmpData;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, YCbCrLayout* outLayout) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
+            acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outLayout = tmpLayout;
+            });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+int Mapper::unlock(buffer_handle_t bufferHandle) const
+{
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    Error error;
+    auto ret = mMapper->unlock(buffer,
+            [&](const auto& tmpError, const auto& tmpReleaseFence)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle && fenceHandle->numFds == 1) {
+                    int fd = dup(fenceHandle->data[0]);
+                    if (fd >= 0) {
+                        releaseFence = fd;
+                    } else {
+                        ALOGD("failed to dup unlock release fence");
+                        sync_wait(fenceHandle->data[0], -1);
+                    }
+                }
+            });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", buffer, error);
+    }
+
+    return releaseFence;
+}
+
+Allocator::Allocator(const Mapper& mapper)
+    : mMapper(mapper)
+{
+    if (mMapper.valid()) {
+        mAllocator = IAllocator::getService();
+    }
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+    std::string debugInfo;
+
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
+        debugInfo = tmpDebugInfo.c_str();
+    });
+
+    return debugInfo;
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
+        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+{
+    Error error;
+    auto ret = mAllocator->allocate(descriptor, count,
+            [&](const auto& tmpError, const auto& tmpStride,
+                const auto& tmpBuffers) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                // import buffers
+                for (uint32_t i = 0; i < count; i++) {
+                    error = mMapper.importBuffer(tmpBuffers[i],
+                            &outBufferHandles[i]);
+                    if (error != Error::NONE) {
+                        for (uint32_t j = 0; j < i; j++) {
+                            mMapper.freeBuffer(outBufferHandles[j]);
+                            outBufferHandles[j] = nullptr;
+                        }
+                        return;
+                    }
+                }
+
+                *outStride = tmpStride;
+            });
+
+    return (ret.isOk()) ? error : kTransactionError;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
deleted file mode 100644
index 7af55e7..0000000
--- a/libs/ui/GrallocAllocator.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocAllocator"
-
-#include <ui/GrallocAllocator.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Allocator::Allocator()
-{
-    mAllocator = IAllocator::getService();
-    if (mAllocator != nullptr) {
-        mAllocator->createClient(
-                [&](const auto& tmpError, const auto& tmpClient) {
-                    if (tmpError == Error::NONE) {
-                        mClient = tmpClient;
-                    }
-                });
-        if (mClient == nullptr) {
-            mAllocator.clear();
-        }
-    }
-}
-
-std::string Allocator::dumpDebugInfo() const
-{
-    std::string info;
-
-    mAllocator->dumpDebugInfo([&](const auto& tmpInfo) {
-        info = tmpInfo.c_str();
-    });
-
-    return info;
-}
-
-Error Allocator::createBufferDescriptor(
-        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor) const
-{
-    Error error = kDefaultError;
-    mClient->createDescriptor(descriptorInfo,
-            [&](const auto& tmpError, const auto& tmpDescriptor) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outDescriptor = tmpDescriptor;
-            });
-
-    return error;
-}
-
-void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
-{
-    mClient->destroyDescriptor(descriptor);
-}
-
-Error Allocator::allocate(BufferDescriptor descriptor,
-        Buffer* outBuffer) const
-{
-    hardware::hidl_vec<BufferDescriptor> descriptors;
-    descriptors.setToExternal(&descriptor, 1);
-
-    Error error = kDefaultError;
-    auto status = mClient->allocate(descriptors,
-            [&](const auto& tmpError, const auto& tmpBuffers) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBuffer = tmpBuffers[0];
-            });
-
-    return error;
-}
-
-void Allocator::free(Buffer buffer) const
-{
-    mClient->free(buffer);
-}
-
-Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
-        native_handle_t** outBufferHandle) const
-{
-    Error error = kDefaultError;
-    auto status = mClient->exportHandle(descriptor, buffer,
-            [&](const auto& tmpError, const auto& tmpBufferHandle) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
-
-                *outBufferHandle = native_handle_clone(tmpBufferHandle);
-                if (!*outBufferHandle) {
-                    error = Error::NO_RESOURCES;
-                }
-            });
-
-    return error;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
deleted file mode 100644
index 8095247..0000000
--- a/libs/ui/GrallocMapper.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocMapper"
-
-#include <ui/GrallocMapper.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-static constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Mapper::Mapper()
-{
-    mMapper = IMapper::getService();
-    if (mMapper != nullptr && mMapper->isRemote()) {
-        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
-    }
-}
-
-Error Mapper::retain(buffer_handle_t handle) const
-{
-    auto ret = mMapper->retain(handle);
-    return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-}
-
-void Mapper::release(buffer_handle_t handle) const
-{
-    auto ret = mMapper->release(handle);
-
-    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-    ALOGE_IF(error != Error::NONE,
-            "release(%p) failed with %d", handle, error);
-}
-
-Error Mapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    Error error = kDefaultError;
-    mMapper->getDimensions(handle,
-            [&](const auto& tmpError, const auto& tmpWidth,
-                    const auto& tmpHeight)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outWidth = tmpWidth;
-                *outHeight = tmpHeight;
-            });
-
-    return error;
-}
-
-Error Mapper::getFormat(buffer_handle_t handle, int32_t* outFormat) const
-{
-    Error error = kDefaultError;
-    mMapper->getFormat(handle,
-            [&](const auto& tmpError, const auto& tmpFormat)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outFormat = static_cast<int32_t>(tmpFormat);
-            });
-
-    return error;
-}
-
-Error Mapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    Error error = kDefaultError;
-    mMapper->getLayerCount(handle,
-            [&](const auto& tmpError, const auto& tmpLayerCount)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayerCount = tmpLayerCount;
-            });
-
-    return error;
-}
-
-Error Mapper::getProducerUsage(buffer_handle_t handle,
-    uint64_t* outProducerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getProducerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpProducerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outProducerUsage = tmpProducerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    Error error = kDefaultError;
-    mMapper->getConsumerUsageMask(handle,
-            [&](const auto& tmpError, const auto& tmpConsumerUsage)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outConsumerUsage = tmpConsumerUsage;
-            });
-
-    return error;
-}
-
-Error Mapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    Error error = kDefaultError;
-    mMapper->getBackingStore(handle,
-            [&](const auto& tmpError, const auto& tmpStore)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outBackingStore = tmpStore;
-            });
-
-    return error;
-}
-
-Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
-{
-    Error error = kDefaultError;
-    mMapper->getStride(handle,
-            [&](const auto& tmpError, const auto& tmpStride)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outStride = tmpStride;
-            });
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, void** outData) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lock(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpData)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outData = tmpData;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
-        uint64_t producerUsage,
-        uint64_t consumerUsage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, FlexLayout* outLayout) const
-{
-    hardware::hidl_handle acquireFenceHandle;
-
-    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-    if (acquireFence >= 0) {
-        auto h = native_handle_init(acquireFenceStorage, 1, 0);
-        h->data[0] = acquireFence;
-        acquireFenceHandle = h;
-    }
-
-    Error error = kDefaultError;
-    mMapper->lockFlex(handle, producerUsage, consumerUsage,
-            accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpLayout)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outLayout = tmpLayout;
-            });
-
-    if (error == Error::NONE && acquireFence >= 0) {
-        close(acquireFence);
-    }
-
-    return error;
-}
-
-int Mapper::unlock(buffer_handle_t handle) const
-{
-    int releaseFence = -1;
-
-    Error error = kDefaultError;
-    mMapper->unlock(handle,
-            [&](const auto& tmpError, const auto& tmpReleaseFence)
-            {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                auto fenceHandle = tmpReleaseFence.getNativeHandle();
-                if (fenceHandle && fenceHandle->numFds == 1) {
-                    int fd = dup(fenceHandle->data[0]);
-                    if (fd >= 0) {
-                        releaseFence = fd;
-                    } else {
-                        error = Error::NO_RESOURCES;
-                    }
-                } else {
-                    releaseFence = -1;
-                }
-            });
-
-    if (error != Error::NONE) {
-        ALOGE("unlock(%p) failed with %d", handle, error);
-        releaseFence = -1;
-    }
-
-    return releaseFence;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index d21758d..eb5c7b6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,7 @@
 
 #include <grallocusage/GrallocUsageConversion.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
 
@@ -104,11 +104,7 @@
 void GraphicBuffer::free_handle()
 {
     if (mOwner == ownHandle) {
-        mBufferMapper.unregisterBuffer(handle);
-        if (!mBufferMapper.getGrallocMapper().valid()) {
-            native_handle_close(handle);
-            native_handle_delete(const_cast<native_handle*>(handle));
-        }
+        mBufferMapper.freeBuffer(handle);
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
@@ -217,7 +213,7 @@
     mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
 
     if (method == TAKE_UNREGISTERED_HANDLE) {
-        status_t err = mBufferMapper.registerBuffer(this);
+        status_t err = mBufferMapper.importBuffer(this);
         if (err != NO_ERROR) {
             // clean up cloned handle
             if (clone) {
@@ -451,7 +447,7 @@
     mOwner = ownHandle;
 
     if (handle != 0) {
-        status_t err = mBufferMapper.registerBuffer(this);
+        status_t err = mBufferMapper.importBuffer(this);
         if (err != NO_ERROR) {
             width = height = stride = format = layerCount = usage = 0;
             handle = NULL;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 3f18bbc..1f6c537 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -22,13 +22,14 @@
 
 #include <stdio.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 #include <log/log.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocAllocator.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBufferMapper.h>
 
 namespace android {
@@ -41,8 +42,9 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-  : mAllocator(std::make_unique<Gralloc2::Allocator>()),
-    mMapper(GraphicBufferMapper::getInstance())
+  : mMapper(GraphicBufferMapper::getInstance()),
+    mAllocator(std::make_unique<Gralloc2::Allocator>(
+                mMapper.getGrallocMapper()))
 {
     if (!mAllocator->valid()) {
         mLoader = std::make_unique<Gralloc1::Loader>();
@@ -102,109 +104,6 @@
     ALOGD("%s", s.string());
 }
 
-namespace {
-
-class HalBuffer {
-public:
-    HalBuffer(const Gralloc2::Allocator* allocator,
-            uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
-            uint64_t consumerUsage)
-        : mAllocator(allocator), mBufferValid(false)
-    {
-        Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
-        info.width = width;
-        info.height = height;
-        info.format = static_cast<Gralloc2::PixelFormat>(format);
-        info.layerCount = layerCount;
-        info.producerUsageMask = producerUsage;
-        info.consumerUsageMask = consumerUsage;
-
-        Gralloc2::BufferDescriptor descriptor;
-        auto error = mAllocator->createBufferDescriptor(info, &descriptor);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            return;
-        }
-
-        error = mAllocator->allocate(descriptor, &mBuffer);
-        if (error == Gralloc2::Error::NOT_SHARED) {
-            error = Gralloc2::Error::NONE;
-        }
-
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
-                    " consumerUsage %" PRIx64 ": %d",
-                    width, height, layerCount, format, producerUsage,
-                    consumerUsage, error);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGE("Failed to export handle");
-            mAllocator->free(mBuffer);
-            mAllocator->destroyBufferDescriptor(descriptor);
-            return;
-        }
-
-        mAllocator->destroyBufferDescriptor(descriptor);
-
-        mBufferValid = true;
-    }
-
-    ~HalBuffer()
-    {
-        if (mBufferValid) {
-            if (mHandle) {
-                native_handle_close(mHandle);
-                native_handle_delete(mHandle);
-            }
-
-            mAllocator->free(mBuffer);
-        }
-    }
-
-    bool exportHandle(GraphicBufferMapper& mapper,
-            buffer_handle_t* handle, uint32_t* stride)
-    {
-        if (!mBufferValid) {
-            return false;
-        }
-
-        if (mapper.registerBuffer(mHandle)) {
-            return false;
-        }
-
-        *handle = mHandle;
-
-        auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
-        if (error != Gralloc2::Error::NONE) {
-            ALOGW("Failed to get stride from buffer: %d", error);
-            *stride = 0;
-        }
-
-        mHandle = nullptr;
-        mAllocator->free(mBuffer);
-        mBufferValid = false;
-
-        return true;
-    }
-
-private:
-    const Gralloc2::Allocator* mAllocator;
-
-    bool mBufferValid;
-    Gralloc2::Buffer mBuffer;
-    native_handle_t* mHandle;
-};
-
-} // namespace
-
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
         PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
         uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
@@ -223,12 +122,18 @@
 
     gralloc1_error_t error;
     if (mAllocator->valid()) {
-        HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
-                producerUsage, consumerUsage);
-        if (!buffer.exportHandle(mMapper, handle, stride)) {
+        Gralloc2::IMapper::BufferDescriptorInfo info = {};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = static_cast<Gralloc2::PixelFormat>(format);
+        info.usage = static_cast<uint64_t>(android_convertGralloc1To0Usage(
+                producerUsage, consumerUsage));
+        error = static_cast<gralloc1_error_t>(mAllocator->allocate(info,
+                    stride, handle));
+        if (error != GRALLOC1_ERROR_NONE) {
             return NO_MEMORY;
         }
-        error = GRALLOC1_ERROR_NONE;
     } else {
         auto descriptor = mDevice->createDescriptor();
         error = descriptor->setDimensions(width, height);
@@ -310,8 +215,7 @@
 
     gralloc1_error_t error;
     if (mAllocator->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper.unregisterBuffer(handle));
+        error = static_cast<gralloc1_error_t>(mMapper.freeBuffer(handle));
     } else {
         error = mDevice->release(handle);
     }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 656472f..87519bf 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
 
 #include <ui/GraphicBufferMapper.h>
 
+#include <grallocusage/GrallocUsageConversion.h>
+
 // We would eliminate the non-conforming zero-length array, but we can't since
 // this is effectively included from the Linux kernel
 #pragma clang diagnostic push
@@ -30,7 +32,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
 #include <ui/GraphicBuffer.h>
 
 #include <system/graphics.h>
@@ -49,63 +51,84 @@
     }
 }
 
-
-
-status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+        buffer_handle_t* outHandle)
 {
     ATRACE_CALL();
 
+    Gralloc2::Error error;
+    if (mMapper->valid()) {
+        error = mMapper->importBuffer(hardware::hidl_handle(rawHandle),
+                outHandle);
+    } else {
+        error = Gralloc2::Error::UNSUPPORTED;
+    }
+
+    ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
+            rawHandle, error);
+
+    return static_cast<status_t>(error);
+}
+
+status_t GraphicBufferMapper::importBuffer(const GraphicBuffer* buffer)
+{
+    ATRACE_CALL();
+
+    ANativeWindowBuffer* nativeBuffer = buffer->getNativeBuffer();
+    buffer_handle_t rawHandle = nativeBuffer->handle;
+
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+        buffer_handle_t importedHandle;
+        error = static_cast<gralloc1_error_t>(mMapper->importBuffer(
+                    hardware::hidl_handle(rawHandle), &importedHandle));
+        if (error == GRALLOC1_ERROR_NONE) {
+            nativeBuffer->handle = importedHandle;
+        }
     } else {
-        // This always returns GRALLOC1_BAD_HANDLE when handle is from a
-        // remote process and mDevice is backed by Gralloc1On0Adapter.
-        error = mDevice->retain(handle);
-        if (error == GRALLOC1_ERROR_BAD_HANDLE &&
-                mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-            ALOGE("registerBuffer by handle is not supported with "
-                  "Gralloc1On0Adapter");
+        native_handle_t* clonedHandle = native_handle_clone(rawHandle);
+        if (clonedHandle) {
+            nativeBuffer->handle = clonedHandle;
+            error = mDevice->retain(buffer);
+            if (error != GRALLOC1_ERROR_NONE) {
+                nativeBuffer->handle = rawHandle;
+                native_handle_close(clonedHandle);
+                native_handle_delete(clonedHandle);
+            }
+        } else {
+            error = GRALLOC1_ERROR_NO_RESOURCES;
         }
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper->retain(buffer->getNativeBuffer()->handle));
-    } else {
-        error = mDevice->retain(buffer);
+    // the raw handle is owned by GraphicBuffer and is now replaced
+    if (error == GRALLOC1_ERROR_NONE) {
+        native_handle_close(rawHandle);
+        native_handle_delete(const_cast<native_handle_t*>(rawHandle));
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
-            buffer->getNativeBuffer()->handle, error);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "importBuffer(%p) failed: %d",
+            rawHandle, error);
 
     return error;
 }
 
-status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
 {
     ATRACE_CALL();
 
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        mMapper->release(handle);
+        mMapper->freeBuffer(handle);
         error = GRALLOC1_ERROR_NONE;
     } else {
         error = mDevice->release(handle);
+        if (!mDevice->hasCapability(GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE)) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle_t*>(handle));
+        }
     }
 
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "freeBuffer(%p): failed %d",
             handle, error);
 
     return error;
@@ -120,138 +143,13 @@
     return outRect;
 }
 
-
-status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
-        uint32_t* outWidth, uint32_t* outHeight) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getDimensions(handle, outWidth, outHeight);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getDimensions(handle, outWidth, outHeight);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
-        int32_t* outFormat) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getFormat(handle, outFormat);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getFormat(handle, outFormat);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
-        uint32_t* outLayerCount) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getLayerCount(handle, outLayerCount);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getLayerCount(handle, outLayerCount);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
-            handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
-        uint64_t* outProducerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getProducerUsage(handle, outProducerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getProducerUsage(handle, outProducerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getProducerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
-        uint64_t* outConsumerUsage) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getConsumerUsage(handle, outConsumerUsage);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getConsumerUsage(handle, outConsumerUsage);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getConsumerUsage(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
-        uint64_t* outBackingStore) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getBackingStore(handle, outBackingStore);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getBackingStore(handle, outBackingStore);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE,
-            "getBackingStore(%p, ...): failed %d", handle, error);
-
-    return error;
-}
-
-status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
-        uint32_t* outStride) const
-{
-    ATRACE_CALL();
-
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        mMapper->getStride(handle, outStride);
-        error = GRALLOC1_ERROR_NONE;
-    } else {
-        error = mDevice->getStride(handle, outStride);
-    }
-
-    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
-            handle, error);
-
-    return error;
+static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
+    Gralloc2::IMapper::Rect outRect{};
+    outRect.left = rect.left;
+    outRect.top = rect.top;
+    outRect.width = rect.width();
+    outRect.height = rect.height();
+    return outRect;
 }
 
 status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
@@ -289,15 +187,15 @@
 {
     ATRACE_CALL();
 
-    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, producerUsage, consumerUsage, accessRect,
-                    fenceFd, vaddr));
+        const uint64_t usage =
+            static_cast<uint64_t>(android_convertGralloc1To0Usage(
+                        producerUsage, consumerUsage));
+        error = static_cast<gralloc1_error_t>(mMapper->lock(handle,
+                usage, asGralloc2Rect(bounds), fenceFd, vaddr));
     } else {
+        gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
         sp<Fence> fence = new Fence(fenceFd);
         error = mDevice->lock(handle,
                 static_cast<gralloc1_producer_usage_t>(producerUsage),
@@ -346,22 +244,19 @@
     gralloc1_error_t error;
 
     if (mMapper->valid()) {
-        const Gralloc2::IMapper::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
-        Gralloc2::FlexLayout layout{};
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, usage, usage, accessRect, fenceFd, &layout));
-
+        Gralloc2::YCbCrLayout layout;
+        error = static_cast<gralloc1_error_t>(mMapper->lock(handle, usage,
+                asGralloc2Rect(bounds), fenceFd, &layout));
         if (error == GRALLOC1_ERROR_NONE) {
-            planes.resize(layout.planes.size());
-            memcpy(planes.data(), layout.planes.data(),
-                    sizeof(planes[0]) * planes.size());
-
-            flexLayout.format = static_cast<android_flex_format_t>(
-                    layout.format);
-            flexLayout.num_planes = static_cast<uint32_t>(planes.size());
-            flexLayout.planes = planes.data();
+            ycbcr->y = layout.y;
+            ycbcr->cb = layout.cb;
+            ycbcr->cr = layout.cr;
+            ycbcr->ystride = static_cast<size_t>(layout.yStride);
+            ycbcr->cstride = static_cast<size_t>(layout.cStride);
+            ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
         }
+
+        return error;
     } else {
         sp<Fence> fence = new Fence(fenceFd);
 
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b55c212..6733505 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -25,9 +25,3 @@
     shared_libs: ["libui"],
     srcs: ["colorspace_test.cpp"],
 }
-
-cc_test {
-    name: "Gralloc1Mapper_test",
-    shared_libs: ["libui", "libutils"],
-    srcs: ["Gralloc1Mapper_test.cpp"],
-}
diff --git a/libs/ui/tests/Gralloc1Mapper_test.cpp b/libs/ui/tests/Gralloc1Mapper_test.cpp
deleted file mode 100644
index b7c9f0f..0000000
--- a/libs/ui/tests/Gralloc1Mapper_test.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Gralloc1Mapper_test"
-//#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <utils/Errors.h>
-
-#include <gtest/gtest.h>
-
-using namespace android;
-
-class Gralloc1MapperTest : public ::testing::Test
-{
-public:
-    ~Gralloc1MapperTest() override = default;
-
-protected:
-    void SetUp() override {
-        buffer = new GraphicBuffer(4, 8, HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
-                GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, "Gralloc1MapperTest");
-        ASSERT_NE(nullptr, buffer.get());
-
-        handle = static_cast<buffer_handle_t>(buffer->handle);
-
-        mapper = &GraphicBufferMapper::get();
-    }
-
-    sp<GraphicBuffer> buffer;
-    buffer_handle_t handle;
-    GraphicBufferMapper* mapper;
-};
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getDimensions) {
-    uint32_t width = 0;
-    uint32_t height = 0;
-    status_t err = mapper->getDimensions(handle, &width, &height);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(4U, width);
-    EXPECT_EQ(8U, height);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getFormat) {
-    int32_t value = 0;
-    status_t err = mapper->getFormat(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getLayerCount) {
-    uint32_t value = 0;
-    status_t err = mapper->getLayerCount(handle, &value);
-    if (err != GRALLOC1_ERROR_UNSUPPORTED) {
-        EXPECT_EQ(1U, value);
-    }
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getProducerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getProducerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getConsumerUsage) {
-    uint64_t value = 0;
-    status_t err = mapper->getConsumerUsage(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    EXPECT_EQ(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getBackingStore) {
-    uint64_t value = 0;
-    status_t err = mapper->getBackingStore(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getStride) {
-    uint32_t value = 0;
-    status_t err = mapper->getStride(handle, &value);
-    ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-    // The stride should be at least the width of the buffer.
-    EXPECT_LE(4U, value);
-}
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 2749fd1..a1f952e 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -20,6 +20,7 @@
 
 namespace {
 
+// TODO(hendrikw): These flags can not be hard coded.
 constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
                                         GRALLOC_USAGE_SW_WRITE_RARELY |
                                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -110,6 +111,7 @@
 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
   int width = static_cast<int>(size);
   int height = 1;
+  // TODO(hendrikw): These flags can not be hard coded.
   constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
                         GRALLOC_USAGE_SW_WRITE_RARELY |
                         GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -196,18 +198,27 @@
       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
 }
 
-BufferProducer::BufferProducer(int width, int height, int format, int usage,
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                               uint32_t usage, size_t metadata_size,
+                               size_t slice_count)
+    : BufferProducer(width, height, format, usage, usage, metadata_size,
+                     slice_count) {}
+
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                               uint64_t producer_usage, uint64_t consumer_usage,
                                size_t metadata_size, size_t slice_count)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
-           "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
-           "usage=%d, metadata_size=%zu, slice_count=%zu",
-           event_fd(), width, height, format, usage, metadata_size,
-           slice_count);
+           "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " metadata_size=%zu slice_count=%zu",
+           event_fd(), width, height, format, producer_usage, consumer_usage,
+           metadata_size, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, metadata_size, slice_count);
+      width, height, format, producer_usage, consumer_usage, metadata_size,
+      slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -226,21 +237,29 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int width, int height, int format,
-                               int usage, size_t meta_size_bytes,
+                               int group_id, uint32_t width, uint32_t height,
+                               uint32_t format, uint32_t usage,
+                               size_t meta_size_bytes, size_t slice_count)
+    : BufferProducer(name, user_id, group_id, width, height, format, usage,
+                     usage, meta_size_bytes, slice_count) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+                               int group_id, uint32_t width, uint32_t height,
+                               uint32_t format, uint64_t producer_usage,
+                               uint64_t consumer_usage, size_t meta_size_bytes,
                                size_t slice_count)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
-           "group_id=%d width=%d height=%d format=%d usage=%d, "
-           "meta_size_bytes=%zu, slice_count=%zu",
+           "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
            event_fd(), name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,18 +279,25 @@
   }
 }
 
-BufferProducer::BufferProducer(int usage, size_t size)
+BufferProducer::BufferProducer(uint32_t usage, size_t size)
+    : BufferProducer(usage, usage, size) {}
+
+BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
+                               size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
-  ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
-           size);
+  ALOGD_IF(TRACE,
+           "BufferProducer::BufferProducer: producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " size=%zu",
+           producer_usage, consumer_usage, size);
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
   const size_t slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
-      width, height, format, usage, meta_size_bytes, slice_count);
+      width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+      slice_count);
   if (!status) {
     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
           status.GetErrorMessage().c_str());
@@ -289,21 +315,27 @@
 }
 
 BufferProducer::BufferProducer(const std::string& name, int user_id,
-                               int group_id, int usage, size_t size)
+                               int group_id, uint32_t usage, size_t size)
+    : BufferProducer(name, user_id, group_id, usage, usage, size) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+                               int group_id, uint64_t producer_usage,
+                               uint64_t consumer_usage, size_t size)
     : BASE(BufferHubRPC::kClientPath) {
   ATRACE_NAME("BufferProducer::BufferProducer");
   ALOGD_IF(TRACE,
            "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
-           "usage=%d size=%zu",
-           name.c_str(), user_id, group_id, usage, size);
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
+           name.c_str(), user_id, group_id, producer_usage, consumer_usage,
+           size);
   const int width = static_cast<int>(size);
   const int height = 1;
   const int format = HAL_PIXEL_FORMAT_BLOB;
   const size_t meta_size_bytes = 0;
   const size_t slice_count = 1;
   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
-      name, user_id, group_id, width, height, format, usage, meta_size_bytes,
-      slice_count);
+      name, user_id, group_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count);
   if (!status) {
     ALOGE(
         "BufferProducer::BufferProducer: Failed to create persistent "
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index dfeed50..c772ed3 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -107,11 +107,14 @@
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
-  int width() const { return slices_[0].width(); }
-  int height() const { return slices_[0].height(); }
-  int stride() const { return slices_[0].stride(); }
-  int format() const { return slices_[0].format(); }
-  int usage() const { return slices_[0].usage(); }
+  uint32_t width() const { return slices_[0].width(); }
+  uint32_t height() const { return slices_[0].height(); }
+  uint32_t stride() const { return slices_[0].stride(); }
+  uint32_t format() const { return slices_[0].format(); }
+  uint32_t usage() const { return slices_[0].usage(); }
+  uint32_t layer_count() const { return slices_[0].layer_count(); }
+  uint64_t producer_usage() const { return slices_[0].producer_usage(); }
+  uint64_t consumer_usage() const { return slices_[0].consumer_usage(); }
 
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -218,8 +221,12 @@
   // arguments as the constructors.
 
   // Constructs a buffer with the given geometry and parameters.
-  BufferProducer(int width, int height, int format, int usage,
-                 size_t metadata_size = 0, size_t slice_count = 1);
+  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                 uint32_t usage, size_t metadata_size = 0,
+                 size_t slice_count = 1);
+  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+                 uint64_t producer_usage, uint64_t consumer_usage,
+                 size_t metadata_size, size_t slice_count);
 
   // Constructs a persistent buffer with the given geometry and parameters and
   // binds it to |name| in one shot. If a persistent buffer with the same name
@@ -233,16 +240,24 @@
   // created and cannot be changed. A user or group id of -1 disables checks for
   // that respective id. A user or group id of 0 is substituted with the
   // effective user or group id of the calling process.
-  BufferProducer(const std::string& name, int user_id, int group_id, int width,
-                 int height, int format, int usage, size_t metadata_size = 0,
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint32_t width, uint32_t height, uint32_t format,
+                 uint32_t usage, size_t metadata_size = 0,
                  size_t slice_count = 1);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint32_t width, uint32_t height, uint32_t format,
+                 uint64_t producer_usage, uint64_t consumer_usage,
+                 size_t metadata_size, size_t slice_count);
 
   // Constructs a blob (flat) buffer with the given usage flags.
-  BufferProducer(int usage, size_t size);
+  BufferProducer(uint32_t usage, size_t size);
+  BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a persistent blob (flat) buffer and binds it to |name|.
-  BufferProducer(const std::string& name, int user_id, int group_id, int usage,
-                 size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint32_t usage, size_t size);
+  BufferProducer(const std::string& name, int user_id, int group_id,
+                 uint64_t producer_usage, uint64_t consumer_usage, size_t size);
 
   // Constructs a channel to persistent buffer by name only. The buffer must
   // have been previously created or made persistent.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 7ed024f..b6302f1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,7 +24,8 @@
         width_(buffer.width()),
         height_(buffer.height()),
         format_(buffer.format()),
-        usage_(buffer.usage()) {
+        producer_usage_(buffer.producer_usage()),
+        consumer_usage_(buffer.consumer_usage()) {
     // Populate the fd and int vectors: native_handle->data[] is an array of fds
     // followed by an array of opaque ints.
     const int fd_count = buffer.handle()->numFds;
@@ -37,6 +38,7 @@
     }
   }
   NativeBufferHandle(NativeBufferHandle&& other) = default;
+  NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
 
   // Imports the native handle into the given IonBuffer instance.
   int Import(IonBuffer* buffer) {
@@ -46,9 +48,10 @@
     for (const auto& fd : fds_)
       fd_ints.push_back(fd.Get());
 
-    const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
-                                   opaque_ints_.data(), opaque_ints_.size(),
-                                   width_, height_, stride_, format_, usage_);
+    const int ret =
+        buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+                       opaque_ints_.size(), width_, height_, stride_, format_,
+                       producer_usage_, consumer_usage_);
     if (ret < 0)
       return ret;
 
@@ -68,24 +71,32 @@
 
  private:
   int id_;
-  int stride_;
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
+  uint32_t stride_;
+  uint32_t width_;
+  uint32_t height_;
+  uint32_t format_;
+  uint64_t producer_usage_;
+  uint64_t consumer_usage_;
   std::vector<int> opaque_ints_;
   std::vector<FileHandleType> fds_;
 
-  void Clear() { id_ = stride_ = width_ = height_ = format_ = usage_ = -1; }
+  void Clear() {
+    id_ = -1;
+    stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
+        0;
+  }
 
   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
-                           width_, height_, format_, usage_, opaque_ints_,
-                           fds_);
+                           width_, height_, format_, producer_usage_,
+                           consumer_usage_, opaque_ints_, fds_);
 
   NativeBufferHandle(const NativeBufferHandle&) = delete;
   void operator=(const NativeBufferHandle&) = delete;
 };
 
+using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
+using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
+
 template <typename FileHandleType>
 class FenceHandle {
  public:
@@ -127,6 +138,23 @@
   PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
 };
 
+struct UsagePolicy {
+  uint64_t producer_set_mask;
+  uint64_t producer_clear_mask;
+  uint64_t producer_deny_set_mask;
+  uint64_t producer_deny_clear_mask;
+  uint64_t consumer_set_mask;
+  uint64_t consumer_clear_mask;
+  uint64_t consumer_deny_set_mask;
+  uint64_t consumer_deny_clear_mask;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
+                           producer_deny_set_mask, producer_deny_clear_mask,
+                           consumer_set_mask, consumer_clear_mask,
+                           consumer_deny_set_mask, consumer_deny_clear_mask);
+};
+
 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
 // type signatures supported by bufferhubd.
 struct BufferHubRPC {
@@ -173,44 +201,46 @@
 
   // Methods.
   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
-                    int(int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    void(uint32_t width, uint32_t height, uint32_t format,
+                         uint64_t producer_usage, uint64_t consumer_usage,
+                         size_t meta_size_bytes, size_t slice_count));
   PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
-                    int(const std::string& name, int user_id, int group_id,
-                        int width, int height, int format, int usage,
-                        size_t meta_size_bytes, size_t slice_count));
+                    void(const std::string& name, int user_id, int group_id,
+                         uint32_t width, uint32_t height, uint32_t format,
+                         uint64_t producer_usage, uint64_t consumer_usage,
+                         size_t meta_size_bytes, size_t slice_count));
   PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
-                    int(const std::string& name));
+                    void(const std::string& name));
   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
                     NativeBufferHandle<LocalHandle>(unsigned index));
   PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
                     std::vector<NativeBufferHandle<LocalHandle>>(Void));
   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
-                    int(const std::string& name, int user_id, int group_id));
+                    void(const std::string& name, int user_id, int group_id));
   PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
-                    int(Void));
+                    void(Void));
   PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
-                    int(LocalFence acquire_fence, MetaData));
+                    void(LocalFence acquire_fence, MetaData));
   PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
   PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
                     std::pair<LocalFence, MetaData>(std::size_t metadata_size));
   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
-                    int(LocalFence release_fence));
-  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, int(bool ignore));
+                    void(LocalFence release_fence));
+  PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    QueueInfo(size_t meta_size_bytes, int usage_set_mask,
-                              int usage_clear_mask, int usage_deny_set_mask,
-                              int usage_deny_clear_mask));
+                    QueueInfo(size_t meta_size_bytes,
+                              const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
                     LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
                     kOpProducerQueueAllocateBuffers,
                     std::vector<std::pair<LocalChannelHandle, size_t>>(
-                        int width, int height, int format, int usage,
+                        uint32_t width, uint32_t height, uint32_t format,
+                        uint64_t producer_usage, uint64_t consumer_usage,
                         size_t slice_count, size_t buffer_count));
   PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
                     void(size_t slot));
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index ffc42d6..e167a17 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,11 +12,20 @@
 class IonBuffer {
  public:
   IonBuffer();
-  IonBuffer(int width, int height, int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-            int format, int usage);
-  IonBuffer(buffer_handle_t handle, int width, int height, int layer_count,
-            int stride, int layer_stride, int format, int usage);
+  IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+  IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+            uint64_t producer_usage, uint64_t consumer_usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t format, uint32_t usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t format, uint64_t producer_usage,
+            uint64_t consumer_usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+            uint32_t format, uint32_t usage);
+  IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+            uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+            uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
   ~IonBuffer();
 
   IonBuffer(IonBuffer&& other);
@@ -30,25 +39,36 @@
   // previous native handle if necessary. Returns 0 on success or a negative
   // errno code otherwise. If allocation fails the previous native handle is
   // left intact.
-  int Alloc(int width, int height, int format, int usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+  int Alloc(uint32_t width, uint32_t height, uint32_t format,
+            uint64_t producer_usage, uint64_t consumer_usage);
 
   // Resets the underlying native handle and parameters, freeing the previous
   // native handle if necessary.
-  void Reset(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage);
+  void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint32_t usage);
+  void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint64_t producer_usage,
+             uint64_t consumer_usage);
 
   // Like Reset but also registers the native handle, which is necessary for
   // native handles received over IPC. Returns 0 on success or a negative errno
   // code otherwise. If import fails the previous native handle is left intact.
-  int Import(buffer_handle_t handle, int width, int height, int stride,
-             int format, int usage);
+  int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint32_t usage);
+  int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+             uint32_t stride, uint32_t format, uint64_t producer_usage,
+             uint64_t consumer_usage);
 
   // Like Reset but imports a native handle from raw fd and int arrays. Returns
   // 0 on success or a negative errno code otherwise. If import fails the
   // previous native handle is left intact.
   int Import(const int* fd_array, int fd_count, const int* int_array,
-             int int_count, int width, int height, int stride, int format,
-             int usage);
+             int int_count, uint32_t width, uint32_t height, uint32_t stride,
+             uint32_t format, uint32_t usage);
+  int Import(const int* fd_array, int fd_count, const int* int_array,
+             int int_count, uint32_t width, uint32_t height, uint32_t stride,
+             uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
 
   // Duplicates the native handle underlying |other| and then imports it. This
   // is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -56,8 +76,8 @@
   // duplication or import fail the previous native handle is left intact.
   int Duplicate(const IonBuffer* other);
 
-  int Lock(int usage, int x, int y, int width, int height, void** address);
-  int LockYUV(int usage, int x, int y, int width, int height,
+  int Lock(uint32_t usage, int x, int y, int width, int height, void** address);
+  int LockYUV(uint32_t usage, int x, int y, int width, int height,
               struct android_ycbcr* yuv);
   int Unlock();
 
@@ -65,19 +85,29 @@
   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 {
+  uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+  uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+  uint32_t layer_count() const {
     return buffer_.get() ? buffer_->getLayerCount() : 0;
   }
-  int stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
-  int layer_stride() const { return 0; }
-  int format() const { return buffer_.get() ? buffer_->getPixelFormat() : 0; }
-  int usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
+  uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
+  uint32_t layer_stride() const { return 0; }
+  uint32_t format() const {
+    return buffer_.get() ? buffer_->getPixelFormat() : 0;
+  }
+  uint64_t producer_usage() const { return producer_usage_; }
+  uint64_t consumer_usage() const { return consumer_usage_; }
+  uint32_t usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
 
  private:
   sp<GraphicBuffer> buffer_;
 
+  // GraphicBuffer doesn't expose these separately. Keep these values cached for
+  // BufferHub to check policy against. Clients that import these buffers won't
+  // get the full picture, which is okay.
+  uint64_t producer_usage_;
+  uint64_t consumer_usage_;
+
   IonBuffer(const IonBuffer&) = delete;
   void operator=(const IonBuffer&) = delete;
 };
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index e5a56c1..df9ae81 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -6,40 +6,59 @@
 
 #include <mutex>
 
+namespace {
+
+constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
+
+}  // anonymous namespace
+
 namespace android {
 namespace dvr {
 
 IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
 
-IonBuffer::IonBuffer(int width, int height, int format, int usage)
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage)
+    : IonBuffer(width, height, format, usage, usage) {}
+
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage)
     : IonBuffer() {
-  Alloc(width, height, format, usage);
+  Alloc(width, height, format, producer_usage, consumer_usage);
 }
 
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
-                     int format, int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t stride, uint32_t format, uint32_t usage)
     : IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
 
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t layer_count, uint32_t stride,
+                     uint32_t layer_stride, uint32_t format, uint32_t usage)
+    : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
+                format, usage, usage) {}
 
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
-                     int layer_count, int stride, int layer_stride, int format,
-                     int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+                     uint32_t layer_count, uint32_t stride,
+                     uint32_t layer_stride, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage)
     : buffer_(nullptr) {
   ALOGD_IF(TRACE,
-         "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
-         "stride=%d layer stride=%d format=%d usage=%d",
-         handle, width, height, layer_count, stride, layer_stride,
-         format, usage);
+           "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
+           "stride=%u layer stride=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64,
+           handle, width, height, layer_count, stride, layer_stride, format,
+           producer_usage, consumer_usage);
   if (handle != 0) {
-    Import(handle, width, height, stride, format, usage);
+    Import(handle, width, height, stride, format, producer_usage,
+           consumer_usage);
   }
 }
 
 IonBuffer::~IonBuffer() {
   ALOGD_IF(TRACE,
-           "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
-           "format=%d usage=%d",
-           handle() , width(), height(), stride(), format(), usage());
+           "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
+           "format=%u usage=%x",
+           handle(), width(), height(), stride(), format(), usage());
   FreeHandle();
 }
 
@@ -62,55 +81,101 @@
   if (buffer_.get()) {
     // GraphicBuffer unregisters and cleans up the handle if needed
     buffer_ = nullptr;
+    producer_usage_ = 0;
+    consumer_usage_ = 0;
   }
 }
 
-int IonBuffer::Alloc(int width, int height, int format, int usage) {
-  ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
-           width, height, format, usage);
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage) {
+  return Alloc(width, height, format, usage, usage);
+}
 
-  buffer_ = new GraphicBuffer(width, height, format, usage);
-  if (buffer_->initCheck() != OK) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage) {
+  ALOGD_IF(
+      TRACE,
+      "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
+      " consumer_usage=%" PRIx64,
+      width, height, format, producer_usage, consumer_usage);
+
+  sp<GraphicBuffer> buffer =
+      new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
+                        producer_usage, consumer_usage);
+  if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
+    return -EINVAL;
+  } else {
+    buffer_ = buffer;
+    producer_usage_ = producer_usage;
+    consumer_usage_ = consumer_usage;
+    return 0;
   }
-  return 0;
 }
 
-void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int usage) {
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  Reset(handle, width, height, stride, format, usage, usage);
+}
+
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ALOGD_IF(TRACE,
-           "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
-           "usage=%d",
-           handle, width, height, stride, format, usage);
-  Import(handle, width, height, stride, format, usage);
+           "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+           handle, width, height, stride, format, producer_usage,
+           consumer_usage);
+  Import(handle, width, height, stride, format, producer_usage, consumer_usage);
 }
 
-int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
-                      int format, int usage) {
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  return Import(handle, width, height, stride, format, usage, usage);
+}
+
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ATRACE_NAME("IonBuffer::Import1");
   ALOGD_IF(
       TRACE,
-      "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
-      "usage=%d",
-      handle, width, height, stride, format, usage);
+      "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
+      "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+      handle, width, height, stride, format, producer_usage, consumer_usage);
   FreeHandle();
-  buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
-          width, height, format, 1, usage, stride);
-  if (buffer_->initCheck() != OK) {
+  sp<GraphicBuffer> buffer = new GraphicBuffer(
+      handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
+      kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
+  if (buffer->initCheck() != OK) {
     ALOGE("IonBuffer::Import: Failed to import buffer");
     return -EINVAL;
+  } else {
+    buffer_ = buffer;
+    producer_usage_ = producer_usage;
+    consumer_usage_ = consumer_usage;
+    return 0;
   }
-  return 0;
 }
 
 int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
-                      int int_count, int width, int height, int stride,
-                      int format, int usage) {
+                      int int_count, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint32_t usage) {
+  return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
+                format, usage, usage);
+}
+
+int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
+                      int int_count, uint32_t width, uint32_t height,
+                      uint32_t stride, uint32_t format, uint64_t producer_usage,
+                      uint64_t consumer_usage) {
   ATRACE_NAME("IonBuffer::Import2");
   ALOGD_IF(TRACE,
-           "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
-           "stride=%d format=%d usage=%d",
-           fd_count, int_count, width, height, stride, format, usage);
+           "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
+           "stride=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64,
+           fd_count, int_count, width, height, stride, format, producer_usage,
+           consumer_usage);
 
   if (fd_count < 0 || int_count < 0) {
     ALOGE("IonBuffer::Import: invalid arguments.");
@@ -128,7 +193,8 @@
   memcpy(handle->data, fd_array, sizeof(int) * fd_count);
   memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
 
-  int ret = Import(handle, width, height, stride, format, usage);
+  const int ret = Import(handle, width, height, stride, format, producer_usage,
+                         consumer_usage);
   if (ret < 0) {
     ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
           strerror(-ret));
@@ -163,8 +229,9 @@
   memcpy(handle->data + fd_count, other->handle()->data + fd_count,
          sizeof(int) * int_count);
 
-  const int ret = Import(handle, other->width(), other->height(),
-                         other->stride(), other->format(), other->usage());
+  const int ret =
+      Import(handle, other->width(), other->height(), other->stride(),
+             other->format(), other->producer_usage(), other->consumer_usage());
   if (ret < 0) {
     ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
           strerror(-ret));
@@ -175,7 +242,7 @@
   return ret;
 }
 
-int IonBuffer::Lock(int usage, int x, int y, int width, int height,
+int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
                     void** address) {
   ATRACE_NAME("IonBuffer::Lock");
   ALOGD_IF(TRACE,
@@ -183,23 +250,23 @@
            "address=%p",
            handle(), usage, x, y, width, height, address);
 
-  status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
-                               address);
+  status_t err =
+      buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
   if (err != NO_ERROR)
     return -EINVAL;
   else
     return 0;
 }
 
-int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
+int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
                        struct android_ycbcr* yuv) {
   ATRACE_NAME("IonBuffer::LockYUV");
   ALOGD_IF(TRACE,
            "IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
            handle(), usage, x, y, width, height);
 
-  status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
-                                    yuv);
+  status_t err =
+      buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
   if (err != NO_ERROR)
     return -EINVAL;
   else
@@ -216,5 +283,5 @@
   else
     return 0;
 }
-} // namespace dvr
-} // namespace android
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index e491abc..b431d2f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -317,7 +317,7 @@
 }
 
 ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+    : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
 
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
@@ -329,13 +329,22 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, int usage_set_mask,
-                             int usage_clear_mask, int usage_deny_set_mask,
-                             int usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+                             uint64_t producer_usage_clear_mask,
+                             uint64_t producer_usage_deny_set_mask,
+                             uint64_t producer_usage_deny_clear_mask,
+                             uint64_t consumer_usage_set_mask,
+                             uint64_t consumer_usage_clear_mask,
+                             uint64_t consumer_usage_deny_set_mask,
+                             uint64_t consumer_usage_deny_clear_mask)
     : BASE(BufferHubRPC::kClientPath) {
   auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
-      usage_deny_clear_mask);
+      meta_size,
+      UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
+                  producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
+                  consumer_usage_set_mask, consumer_usage_clear_mask,
+                  consumer_usage_deny_set_mask,
+                  consumer_usage_deny_clear_mask});
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -346,8 +355,17 @@
   SetupQueue(status.get().meta_size_bytes, status.get().id);
 }
 
-int ProducerQueue::AllocateBuffer(int width, int height, int format, int usage,
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                  uint32_t format, uint32_t usage,
                                   size_t slice_count, size_t* out_slot) {
+  return AllocateBuffer(width, height, format, usage, usage, slice_count,
+                        out_slot);
+}
+
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+                                  uint32_t format, uint64_t producer_usage,
+                                  uint64_t consumer_usage, size_t slice_count,
+                                  size_t* out_slot) {
   if (out_slot == nullptr) {
     ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
     return -EINVAL;
@@ -363,7 +381,8 @@
 
   Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
       InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
-          width, height, format, usage, slice_count, kBufferCount);
+          width, height, format, producer_usage, consumer_usage, slice_count,
+          kBufferCount);
   if (!status) {
     ALOGE(
         "ProducerQueue::AllocateBuffer failed to create producer buffer "
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 3fe7642..ebd7da0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -38,22 +38,8 @@
   }
 
   const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+  sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
 
-  // Create new GraphicBuffer based on the newly created |buffer_producer|. Here
-  // we have to cast |buffer_handle_t| to |native_handle_t|, it's OK because
-  // internally, GraphicBuffer is still an |ANativeWindowBuffer| and |handle|
-  // is still type of |buffer_handle_t| and bears const property.
-  sp<GraphicBuffer> graphic_buffer(new GraphicBuffer(
-      buffer_producer->width(), buffer_producer->height(),
-      buffer_producer->format(),
-      1, /* layer count */
-      buffer_producer->usage(),
-      buffer_producer->stride(),
-      const_cast<native_handle_t*>(buffer_producer->buffer()->handle()),
-      false));
-
-  LOG_ALWAYS_FATAL_IF(NO_ERROR != graphic_buffer->initCheck(),
-                      "Failed to init GraphicBuffer.");
   core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
   core_->buffers_[slot].mRequestBufferCalled = true;
 
@@ -155,9 +141,9 @@
     if (!buffer_producer)
       return NO_MEMORY;
 
-    if (static_cast<int>(width) == buffer_producer->width() &&
-        static_cast<int>(height) == buffer_producer->height() &&
-        static_cast<int>(format) == buffer_producer->format()) {
+    if (width == buffer_producer->width() &&
+        height == buffer_producer->height() &&
+        static_cast<uint32_t>(format) == buffer_producer->format()) {
       // The producer queue returns a buffer producer matches the request.
       break;
     }
@@ -165,8 +151,8 @@
     // Needs reallocation.
     // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
     ALOGI(
-        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%d) is different "
-        "from the buffer returned at slot: %zu (w=%d, h=%d, format=%d). Need "
+        "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+        "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
         "re-allocattion.",
         width, height, format, slot, buffer_producer->width(),
         buffer_producer->height(), buffer_producer->format());
@@ -322,7 +308,7 @@
 
   output->width = buffer_producer->width();
   output->height = buffer_producer->height();
-  output->transformHint = 0; // default value, we don't use it yet.
+  output->transformHint = 0;  // default value, we don't use it yet.
 
   // |numPendingBuffers| counts of the number of buffers that has been enqueued
   // by the producer but not yet acquired by the consumer. Due to the nature
@@ -456,7 +442,7 @@
   return NO_ERROR;
 }
 
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode mode) {
+status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
   // Consumer interaction are actually handled by buffer hub, and we need
   // to maintain consumer operations here.  We only need to perform basic input
   // parameter checks here.
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 2b70c5b..255793f 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -274,12 +274,27 @@
   // |usage_deny_clear_mask| shall not conflict with each other. Such
   // configuration will be treated as invalid input on creation.
   template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(int usage_set_mask,
-                                               int usage_clear_mask,
-                                               int usage_deny_set_mask,
-                                               int usage_deny_clear_mask) {
+  static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
+                                               uint32_t usage_clear_mask,
+                                               uint32_t usage_deny_set_mask,
+                                               uint32_t usage_deny_clear_mask) {
     return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
+                        usage_deny_set_mask, usage_deny_clear_mask,
+                        usage_set_mask, usage_clear_mask, usage_deny_set_mask,
+                        usage_deny_clear_mask);
+  }
+  template <typename Meta>
+  static std::unique_ptr<ProducerQueue> Create(
+      uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
+      uint64_t producer_usage_deny_set_mask,
+      uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
+      uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
+      uint64_t consumer_usage_deny_clear_mask) {
+    return BASE::Create(sizeof(Meta), producer_usage_set_mask,
+                        producer_usage_clear_mask, producer_usage_deny_set_mask,
+                        producer_usage_deny_clear_mask, consumer_usage_set_mask,
+                        consumer_usage_clear_mask, consumer_usage_deny_set_mask,
+                        consumer_usage_deny_clear_mask);
   }
 
   // Import a |ProducerQueue| from a channel handle.
@@ -301,7 +316,10 @@
   // use (i.e. in |Gain|'ed mode).
   // Returns Zero on success and negative error code when buffer allocation
   // fails.
-  int AllocateBuffer(int width, int height, int format, int usage,
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint32_t usage, size_t slice_count, size_t* out_slot);
+  int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+                     uint64_t producer_usage, uint64_t consumer_usage,
                      size_t slice_count, size_t* out_slot);
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
@@ -327,8 +345,14 @@
   // arguments as the constructors.
   explicit ProducerQueue(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);
+  ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+                uint64_t producer_usage_clear_mask,
+                uint64_t producer_usage_deny_set_mask,
+                uint64_t producer_usage_deny_clear_mask,
+                uint64_t consumer_usage_set_mask,
+                uint64_t consumer_usage_clear_mask,
+                uint64_t consumer_usage_deny_set_mask,
+                uint64_t consumer_usage_deny_clear_mask);
 
   int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
                     LocalHandle* release_fence) override;
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 6d39cdb..ef50a0f 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -216,7 +216,8 @@
   return 0;
 }
 
-pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) {
+pdx::Status<void> DisplayClient::SetViewerParams(
+    const ViewerParams& viewer_params) {
   auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
   if (!status) {
     ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
@@ -252,16 +253,20 @@
   return DisplaySurfaceClient::Create(width, height, format, usage, flags);
 }
 
-std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
-  auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+    const std::string& name) {
+  auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
   if (!status) {
     ALOGE(
-        "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+        "error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return nullptr;
   }
 
-  return BufferConsumer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 bool DisplayClient::IsVrAppRunning() {
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 7993fce..44b3c4b 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,19 +31,22 @@
   return 0;
 }
 
-std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-      extended_region_size, usage);
+std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
+    const std::string& name, size_t size, uint64_t producer_usage,
+    uint64_t consumer_usage) {
+  auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+      name, size, producer_usage, consumer_usage);
   if (!status) {
     ALOGE(
-        "DisplayManagerClient::SetupPoseBuffer: Failed to create the pose "
-        "buffer %s",
-        status.GetErrorMessage().c_str());
+        "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
+        "buffer: name=%s, error=%s",
+        name.c_str(), status.GetErrorMessage().c_str());
     return {};
   }
 
-  return BufferProducer::Import(std::move(status));
+  auto ion_buffer = std::make_unique<IonBuffer>();
+  status.take().Import(ion_buffer.get());
+  return ion_buffer;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 378f67c..fec2ea5 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -108,7 +108,7 @@
   std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
       int width, int height, int format, int usage, int flags);
 
-  std::unique_ptr<BufferConsumer> GetPoseBuffer();
+  std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   bool IsVrAppRunning();
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
index 144cd3b..b0a7d13 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
@@ -17,8 +17,10 @@
 
   int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
 
-  std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
-                                                  int usage);
+  std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
+                                              size_t size,
+                                              uint64_t producer_usage,
+                                              uint64_t consumer_usage);
 
   using Client::event_fd;
   using Client::GetChannel;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index ac08650..c12b090 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -9,6 +9,7 @@
 #include <pdx/rpc/remote_method.h>
 #include <pdx/rpc/serializable.h>
 #include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/display_types.h>
 
 namespace android {
@@ -218,7 +219,7 @@
     kOpCreateVideoMeshSurface,
     kOpVideoMeshSurfaceCreateProducerQueue,
     kOpSetViewerParams,
-    kOpGetPoseBuffer,
+    kOpGetNamedBuffer,
     kOpIsVrAppRunning,
   };
 
@@ -247,8 +248,8 @@
                     LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
                     void(const ViewerParams& viewer_params));
-  PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
-                    LocalChannelHandle(Void));
+  PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name));
   PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
 };
 
@@ -260,7 +261,7 @@
   enum {
     kOpGetSurfaceList = 0,
     kOpUpdateSurfaces,
-    kOpSetupPoseBuffer,
+    kOpSetupNamedBuffer,
   };
 
   // Aliases.
@@ -273,8 +274,11 @@
   PDX_REMOTE_METHOD(
       UpdateSurfaces, kOpUpdateSurfaces,
       int(const std::map<int, DisplaySurfaceAttributes>& updates));
-  PDX_REMOTE_METHOD(SetupPoseBuffer, kOpSetupPoseBuffer,
-                    LocalChannelHandle(size_t extended_region_size, int usage));
+  PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+                    LocalNativeBufferHandle(const std::string& name,
+                                            size_t size,
+                                            uint64_t producer_usage,
+                                            uint64_t consumer_usage));
 };
 
 struct ScreenshotData {
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
index 7cbfc21..9247d53 100644
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -42,14 +42,16 @@
   delete client;
 }
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1) {
-  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
-  auto buffer_producer = client->client->SetupPoseBuffer(
-      extended_region_size, static_cast<int>(usage0));
-  if (buffer_producer) {
-    return CreateDvrWriteBufferFromBufferProducer(std::move(buffer_producer));
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+                                             const char* name, size_t size,
+                                             uint64_t producer_usage,
+                                             uint64_t consumer_usage) {
+  // TODO(hendrikw): When we move to gralloc1, pass both producer_usage and
+  // consumer_usage down.
+  auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
+                                                     consumer_usage);
+  if (ion_buffer) {
+    return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
   }
   return nullptr;
 }
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 49702fd..b91de8f 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -31,8 +31,8 @@
         dvrDisplayManagerClientGetSurfaceList;
     dvr_api->display_manager_client_surface_list_destroy =
         dvrDisplayManagerClientSurfaceListDestroy;
-    dvr_api->display_manager_setup_pose_buffer =
-        dvrDisplayManagerSetupPoseBuffer;
+    dvr_api->display_manager_setup_named_buffer =
+        dvrDisplayManagerSetupNamedBuffer;
     dvr_api->display_manager_client_surface_list_get_size =
         dvrDisplayManagerClientSurfaceListGetSize;
     dvr_api->display_manager_client_surface_list_get_surface_id =
@@ -48,7 +48,6 @@
 
     // dvr_buffer.h
     dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
-    dvr_api->write_buffer_get_blob_fds = dvrWriteBufferGetBlobFds;
     dvr_api->write_buffer_get_ahardwarebuffer =
         dvrWriteBufferGetAHardwareBuffer;
     dvr_api->write_buffer_post = dvrWriteBufferPost;
@@ -56,11 +55,12 @@
     dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
 
     dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
-    dvr_api->read_buffer_get_blob_fds = dvrReadBufferGetBlobFds;
     dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
     dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
     dvr_api->read_buffer_release = dvrReadBufferRelease;
     dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
+    dvr_api->buffer_destroy = dvrBufferDestroy;
+    dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
 
     // dvr_buffer_queue.h
     dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
@@ -77,7 +77,7 @@
     dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
 
     // dvr_surface.h
-    dvr_api->get_pose_buffer = dvrGetPoseBuffer;
+    dvr_api->get_named_buffer = dvrGetNamedBuffer;
     dvr_api->surface_create = dvrSurfaceCreate;
     dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
 
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 25128a6..0942b3d 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -6,13 +6,15 @@
 using namespace android;
 
 struct DvrWriteBuffer {
-  std::shared_ptr<dvr::BufferProducer> write_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferProducer> write_buffer;
 };
 
 struct DvrReadBuffer {
-  std::shared_ptr<dvr::BufferConsumer> read_buffer_;
-  sp<GraphicBuffer> graphic_buffer_;
+  std::shared_ptr<dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+  std::shared_ptr<dvr::IonBuffer> buffer;
 };
 
 namespace android {
@@ -20,16 +22,23 @@
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
-  DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
-  write_buffer->write_buffer_ = std::move(buffer_producer);
-  return write_buffer;
+  if (!buffer_producer)
+    return nullptr;
+  return new DvrWriteBuffer{std::move(buffer_producer)};
 }
 
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
     const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
-  DvrReadBuffer* read_buffer = new DvrReadBuffer;
-  read_buffer->read_buffer_ = std::move(buffer_consumer);
-  return read_buffer;
+  if (!buffer_consumer)
+    return nullptr;
+  return new DvrReadBuffer{std::move(buffer_consumer)};
+}
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer) {
+  if (!ion_buffer)
+    return nullptr;
+  return new DvrBuffer{std::move(ion_buffer)};
 }
 
 }  // namespace dvr
@@ -49,79 +58,82 @@
 
 extern "C" {
 
-void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
-
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count) {
-  client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
+  delete write_buffer;
 }
 
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->id();
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->write_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+      write_buffer->write_buffer->buffer()->buffer().get());
   return 0;
 }
 
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle fence(ready_fence_fd);
-  int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
-  fence.Release();
+  int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
   return result;
 }
 
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
   pdx::LocalHandle release_fence;
-  int result = client->write_buffer_->Gain(&release_fence);
+  int result = write_buffer->write_buffer->Gain(&release_fence);
   *release_fence_fd = release_fence.Release();
   return result;
 }
 
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
-  return client->write_buffer_->GainAsync();
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+  return write_buffer->write_buffer->GainAsync();
 }
 
-void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
 
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count) {
-  client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->id();
 }
 
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer) {
-  if (!client->graphic_buffer_.get()) {
-    InitializeGraphicBuffer(client->read_buffer_.get(),
-                            &client->graphic_buffer_);
-  }
-  *hardware_buffer =
-      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+      read_buffer->read_buffer->buffer()->buffer().get());
   return 0;
 }
 
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes) {
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes) {
   pdx::LocalHandle ready_fence;
   int result =
-      client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+      read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
   *ready_fence_fd = ready_fence.Release();
   return result;
 }
 
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
   pdx::LocalHandle fence(release_fence_fd);
-  int result = client->read_buffer_->Release(fence);
-  fence.Release();
+  int result = read_buffer->read_buffer->Release(fence);
   return result;
 }
 
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
-  return client->read_buffer_->ReleaseAsync();
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+  return read_buffer->read_buffer->ReleaseAsync();
+}
+
+void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
+
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer) {
+  if (!hardware_buffer) {
+    return -EINVAL;
+  }
+
+  *hardware_buffer =
+      reinterpret_cast<AHardwareBuffer*>(buffer->buffer->buffer().get());
+  return 0;
 }
 
 }  // extern "C"
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3cbba5..a04ed50 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -58,14 +58,25 @@
   return 0;
 }
 
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
   auto client = android::dvr::DisplayClient::Create();
   if (!client) {
-    ALOGE("Failed to create display client!");
+    ALOGE("dvrGetNamedBuffer: Failed to create display client!");
     return -ECOMM;
   }
 
-  *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+  if (out_buffer == nullptr || name == nullptr) {
+    ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+          out_buffer);
+    return -EINVAL;
+  }
+
+  auto named_buffer = client->GetNamedBuffer(name);
+  if (!named_buffer) {
+    ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
+    return -EINVAL;
+  }
+  *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
   return 0;
 }
 
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
index 0928d43..4e1f227 100644
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ b/libs/vr/libdvr/include/dvr/display_manager_client.h
@@ -14,15 +14,16 @@
     DvrDisplayManagerClientSurfaceList;
 typedef struct DvrDisplayManagerClientSurfaceBuffers
     DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrBuffer DvrBuffer;
 
 DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
 
 void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
 
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1);
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+                                             const char* name, size_t size,
+                                             uint64_t producer_usage,
+                                             uint64_t consumer_usage);
 
 // Return an event fd for checking if there was an event on the server
 // Note that the only event which will be flagged is POLLIN. You must use
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index a4fef19..c46684b 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -30,6 +30,7 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
@@ -43,9 +44,9 @@
     DvrDisplayManagerClientSurfaceList** surface_list);
 typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
-    DvrDisplayManagerClient* client, size_t extended_region_size,
-    uint64_t usage0, uint64_t usage1);
+typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
+    DvrDisplayManagerClient* client, const char* name, size_t size,
+    uint64_t producer_usage, uint64_t consumer_usage);
 typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
     DvrDisplayManagerClientSurfaceList* surface_list);
 typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
@@ -62,9 +63,6 @@
 
 // dvr_buffer.h
 typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
-typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
-                                            size_t* fds_count,
-                                            size_t max_fds_count);
 typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
     DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
@@ -74,9 +72,6 @@
 typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
 
 typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
-typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
-                                           size_t* fds_count,
-                                           size_t max_fds_count);
 typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
     DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
 typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
@@ -85,6 +80,9 @@
 typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
                                        int release_fence_fd);
 typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
+                                           AHardwareBuffer** hardware_buffer);
 
 // dvr_buffer_queue.h
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
@@ -110,7 +108,7 @@
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
-typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
 typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
                                    uint64_t usage0, uint64_t usage1, int flags,
                                    DvrSurface** out_surface);
@@ -149,7 +147,7 @@
 // dvr_hardware_composer_client.h
 typedef struct DvrHwcClient DvrHwcClient;
 typedef struct DvrHwcFrame DvrHwcFrame;
-typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
+typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
 typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback,
                                                void* client_state);
 typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client);
@@ -159,7 +157,8 @@
 typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame);
 typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame);
 typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame);
-typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, size_t layer_index);
+typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame,
+                                          size_t layer_index);
 typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame,
                                                          size_t layer_index);
 typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame,
@@ -185,7 +184,7 @@
       display_manager_client_get_surface_list;
   DvrDisplayManagerClientSurfaceListDestroyPtr
       display_manager_client_surface_list_destroy;
-  DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer;
+  DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
   DvrDisplayManagerClientSurfaceListGetSizePtr
       display_manager_client_surface_list_get_size;
   DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
@@ -201,7 +200,6 @@
 
   // Write buffer
   DvrWriteBufferDestroyPtr write_buffer_destroy;
-  DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds;
   DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
   DvrWriteBufferPostPtr write_buffer_post;
   DvrWriteBufferGainPtr write_buffer_gain;
@@ -209,11 +207,12 @@
 
   // Read buffer
   DvrReadBufferDestroyPtr read_buffer_destroy;
-  DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds;
   DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
   DvrReadBufferAcquirePtr read_buffer_acquire;
   DvrReadBufferReleasePtr read_buffer_release;
   DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
+  DvrBufferDestroy buffer_destroy;
+  DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
 
   // Write buffer queue
   DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
@@ -235,7 +234,7 @@
   DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
 
   // Display surface
-  DvrGetPoseBufferPtr get_pose_buffer;
+  DvrGetNamedBufferPtr get_named_buffer;
   DvrSurfaceCreatePtr surface_create;
   DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index bbfbb00..6c9c4d3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -1,9 +1,9 @@
 #ifndef ANDROID_DVR_BUFFER_H_
 #define ANDROID_DVR_BUFFER_H_
 
-#include <memory>
 #include <stdbool.h>
 #include <stdint.h>
+#include <memory>
 
 #ifdef __cplusplus
 extern "C" {
@@ -11,29 +11,33 @@
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
 // Write buffer
-void dvrWriteBufferDestroy(DvrWriteBuffer* client);
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
-                              size_t* fds_count, size_t max_fds_count);
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes);
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
 
 // Read buffer
-void dvrReadBufferDestroy(DvrReadBuffer* client);
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
-                             size_t max_fds_count);
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
-                         size_t meta_size_bytes);
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+                         void* meta, size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// Buffer
+void dvrBufferDestroy(DvrBuffer* buffer);
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+                                AHardwareBuffer** hardware_buffer);
 
 #ifdef __cplusplus
 }  // extern "C"
@@ -44,11 +48,14 @@
 
 class BufferProducer;
 class BufferConsumer;
+class IonBuffer;
 
 DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
     const std::shared_ptr<BufferProducer>& buffer_producer);
 DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
     const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer);
 
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 2712f24..e5228d6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -12,7 +12,7 @@
 typedef struct DvrSurfaceParameter DvrSurfaceParameter;
 
 // Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
 
 int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
                      uint64_t usage1, int flags, DvrSurface** out_surface);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 75e2a7d..29cdc13 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -17,14 +17,18 @@
     libbufferhub \
     libchrome \
     libdvrcommon \
+    libdisplay \
     libpdx_default_transport \
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_SRC_FILES := \
+    dvr_buffer_queue-test.cpp \
+    dvr_named_buffer-test.cpp \
+
 LOCAL_STATIC_LIBRARIES := $(static_libraries)
 LOCAL_SHARED_LIBRARIES := $(shared_libraries)
 LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_api-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_api-test
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
new file mode 100644
index 0000000..cd3285f
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -0,0 +1,122 @@
+#include <android/hardware_buffer.h>
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_surface.h>
+#include <system/graphics.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class DvrNamedBufferTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    client_ = dvrDisplayManagerClientCreate();
+    ASSERT_NE(nullptr, client_);
+  }
+
+  void TearDown() override {
+    if (client_ != nullptr) {
+      dvrDisplayManagerClientDestroy(client_);
+      client_ = nullptr;
+    }
+  }
+
+  DvrDisplayManagerClient* client_ = nullptr;
+};
+
+TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
+  const char* buffer_name = "same_name";
+  DvrBuffer* buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer1);
+
+  DvrBuffer* buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  ASSERT_NE(nullptr, buffer2);
+
+  AHardwareBuffer* hardware_buffer1 = nullptr;
+  int e1 = dvrBufferGetAHardwareBuffer(buffer1, &hardware_buffer1);
+  ASSERT_EQ(0, e1);
+
+  AHardwareBuffer* hardware_buffer2 = nullptr;
+  int e2 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer2);
+  ASSERT_EQ(0, e2);
+  ASSERT_NE(nullptr, hardware_buffer1);
+
+  AHardwareBuffer_Desc desc1 = {};
+  AHardwareBuffer_describe(hardware_buffer1, &desc1);
+  AHardwareBuffer_Desc desc2 = {};
+  AHardwareBuffer_describe(hardware_buffer2, &desc2);
+  ASSERT_EQ(desc1.width, 10u);
+  ASSERT_EQ(desc1.height, 1u);
+  ASSERT_EQ(desc1.layers, 1u);
+  ASSERT_EQ(desc1.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc1.usage0, 0u);
+  ASSERT_EQ(desc1.usage1, 0u);
+  ASSERT_EQ(desc2.width, 10u);
+  ASSERT_EQ(desc2.height, 1u);
+  ASSERT_EQ(desc2.layers, 1u);
+  ASSERT_EQ(desc2.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc2.usage0, 0u);
+  ASSERT_EQ(desc2.usage1, 0u);
+
+  dvrBufferDestroy(buffer1);
+  dvrBufferDestroy(buffer2);
+
+  DvrBuffer* buffer3 = nullptr;
+  int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+  ASSERT_NE(nullptr, buffer3);
+  ASSERT_EQ(0, e3);
+
+  AHardwareBuffer* hardware_buffer3 = nullptr;
+  int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+  ASSERT_EQ(0, e4);
+  ASSERT_NE(nullptr, hardware_buffer3);
+
+  AHardwareBuffer_Desc desc3 = {};
+  AHardwareBuffer_describe(hardware_buffer3, &desc3);
+  ASSERT_EQ(desc3.width, 10u);
+  ASSERT_EQ(desc3.height, 1u);
+  ASSERT_EQ(desc3.layers, 1u);
+  ASSERT_EQ(desc3.format, HAL_PIXEL_FORMAT_BLOB);
+  ASSERT_EQ(desc3.usage0, 0u);
+  ASSERT_EQ(desc3.usage1, 0u);
+
+  dvrBufferDestroy(buffer3);
+}
+
+TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
+  const char* buffer_name1 = "test1";
+  const char* buffer_name2 = "test2";
+  DvrBuffer* setup_buffer1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer1);
+  dvrBufferDestroy(setup_buffer1);
+
+  DvrBuffer* setup_buffer2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+  ASSERT_NE(nullptr, setup_buffer2);
+  dvrBufferDestroy(setup_buffer2);
+
+  DvrBuffer* buffer1 = nullptr;
+  int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+  ASSERT_NE(nullptr, buffer1);
+  ASSERT_EQ(0, e1);
+  dvrBufferDestroy(buffer1);
+
+  DvrBuffer* buffer2 = nullptr;
+  int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+  ASSERT_NE(nullptr, buffer2);
+  ASSERT_EQ(0, e2);
+  dvrBufferDestroy(buffer2);
+}
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 0daab64..632978b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,6 +47,7 @@
 ]
 
 sharedLibraries = [
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.allocator@2.0",
     "android.hardware.graphics.composer@2.1",
     "libbinder",
@@ -75,7 +76,7 @@
     cflags: [
         "-DLOG_TAG=\"vr_flinger\"",
         "-DTRACE=0",
-	"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
         "-DGL_GLEXT_PROTOTYPES",
         "-DEGL_EGLEXT_PROTOTYPES",
     ],
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 49b6f09..99f93bf 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -2,7 +2,9 @@
 
 #include <pdx/channel_handle.h>
 #include <pdx/default_transport/service_endpoint.h>
+#include <private/android_filesystem_config.h>
 #include <private/dvr/display_rpc.h>
+#include <private/dvr/trusted_uids.h>
 #include <sys/poll.h>
 
 #include <array>
@@ -82,9 +84,9 @@
           *this, &DisplayManagerService::OnUpdateSurfaces, message);
       return {};
 
-  case DisplayManagerRPC::SetupPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
-          *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+    case DisplayManagerRPC::SetupNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+          *this, &DisplayManagerService::OnSetupNamedBuffer, message);
       return {};
 
     default:
@@ -188,9 +190,20 @@
   return 0;
 }
 
-pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
-    pdx::Message& /*message*/, size_t extended_region_size, int usage) {
-  return display_service_->SetupPoseBuffer(extended_region_size, usage);
+pdx::Status<BorrowedNativeBufferHandle>
+DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
+                                          const std::string& name, size_t size,
+                                          uint64_t producer_usage,
+                                          uint64_t consumer_usage) {
+  if (message.GetEffectiveUserId() != AID_ROOT &&
+      !IsTrustedUid(message.GetEffectiveUserId())) {
+    // Only trusted users can setup named buffers.
+    ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
+          message.GetEffectiveUserId());
+    return {};
+  }
+  return display_service_->SetupNamedBuffer(name, size, producer_usage,
+                                            consumer_usage);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 80324fd..7b037de 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,9 +54,9 @@
   int OnUpdateSurfaces(pdx::Message& message,
                        const std::map<int, DisplaySurfaceAttributes>& updates);
 
-  pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
-                                               size_t extended_region_size,
-                                               int usage);
+  pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
+      pdx::Message& message, const std::string& name, size_t size,
+      uint64_t producer_usage, uint64_t consumer_usage);
 
   // Called by the display service to indicate changes to display surfaces that
   // the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index bb8613c..8cf9d64 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,5 +1,6 @@
 #include "display_service.h"
 
+#include <unistd.h>
 #include <vector>
 
 #include <pdx/default_transport/service_endpoint.h>
@@ -18,20 +19,10 @@
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
 
-namespace {
-
-constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
-const int kPersistentPoseBufferUserId = 0;
-const int kPersistentPoseBufferGroupId = 0;
-const size_t kTimingDataSizeOffset = 128;
-
-}  // anonymous namespace
-
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService()
-    : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
 
 DisplayService::DisplayService(Hwc2::Composer* hidl)
     : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -89,9 +80,9 @@
           *this, &DisplayService::OnSetViewerParams, message);
       return {};
 
-    case DisplayRPC::GetPoseBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
-          *this, &DisplayService::OnGetPoseBuffer, message);
+    case DisplayRPC::GetNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+          *this, &DisplayService::OnGetNamedBuffer, message);
       return {};
 
     case DisplayRPC::IsVrAppRunning::Opcode:
@@ -254,13 +245,14 @@
   compositor->UpdateHeadMountMetrics(head_mount_metrics);
 }
 
-pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
-  if (pose_buffer_) {
-    return pose_buffer_->CreateConsumer().take();
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
+    pdx::Message& /* message */, const std::string& name) {
+  auto named_buffer = named_buffers_.find(name);
+  if (named_buffer != named_buffers_.end()) {
+    return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
   }
 
-  pdx::rpc::RemoteMethodError(message, EAGAIN);
-  return {};
+  return pdx::ErrorStatus(EINVAL);
 }
 
 // Calls the message handler for the DisplaySurface associated with this
@@ -334,16 +326,22 @@
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
-pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
-    size_t extended_region_size, int usage) {
-  if (!pose_buffer_) {
-    pose_buffer_ = BufferProducer::Create(
-        kPersistentPoseBufferName, kPersistentPoseBufferUserId,
-        kPersistentPoseBufferGroupId, usage,
-        extended_region_size + kTimingDataSizeOffset);
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
+    const std::string& name, size_t size, int producer_usage,
+    int consumer_usage) {
+  auto named_buffer = named_buffers_.find(name);
+  if (named_buffer == named_buffers_.end()) {
+    // TODO(hendrikw): Update BufferProducer to take producer_usage and
+    // consumer_usage flags.
+    auto ion_buffer = std::make_unique<IonBuffer>(
+        static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB,
+        producer_usage | consumer_usage);
+    named_buffer =
+        named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+            .first;
   }
 
-  return pose_buffer_->GetChannelHandle().Borrow();
+  return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
 }
 
 void DisplayService::OnHardwareComposerRefresh() {
@@ -362,10 +360,11 @@
 
 int DisplayService::IsVrAppRunning(pdx::Message& message) {
   bool visible = false;
-  ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
-    if (surface->client_z_order() == 0 && surface->IsVisible())
-      visible = true;
-  });
+  ForEachDisplaySurface(
+      [&visible](const std::shared_ptr<DisplaySurface>& surface) {
+        if (surface->client_z_order() == 0 && surface->IsVisible())
+          visible = true;
+      });
 
   REPLY_SUCCESS_RETURN(message, visible, 0);
 }
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index da80a84..db89064 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -3,6 +3,7 @@
 
 #include <pdx/service.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/display_rpc.h>
 #include <private/dvr/late_latch.h>
 
@@ -38,8 +39,9 @@
   // any change to client/manager attributes that affect visibility or z order.
   void UpdateActiveDisplaySurfaces();
 
-  pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
-                                             int usage);
+  pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
+      const std::string& name, size_t size, int producer_usage,
+      int consumer_usage);
 
   template <class A>
   void ForEachDisplaySurface(A action) const {
@@ -85,7 +87,8 @@
 
   void OnSetViewerParams(pdx::Message& message,
                          const ViewerParams& view_params);
-  pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
+  pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
+      pdx::Message& message, const std::string& name);
 
   // Temporary query for current VR status. Will be removed later.
   int IsVrAppRunning(pdx::Message& message);
@@ -102,7 +105,7 @@
   HardwareComposer hardware_composer_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
-  std::unique_ptr<BufferProducer> pose_buffer_;
+  std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 542bbd9..6602d78 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1416,7 +1416,7 @@
 
 void Layer::Prepare() {
   int right, bottom;
-  buffer_handle_t handle;
+  sp<GraphicBuffer> handle;
 
   if (surface_) {
     // Only update the acquired buffer when one is either available or this is
@@ -1465,14 +1465,14 @@
     }
     right = acquired_buffer_.buffer()->width();
     bottom = acquired_buffer_.buffer()->height();
-    handle = acquired_buffer_.buffer()->native_handle();
+    handle = acquired_buffer_.buffer()->buffer()->buffer();
     acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
   } else {
     // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
     // mechanism to accept distorted layers from VrCore.
     right = direct_buffer_->width();
     bottom = direct_buffer_->height();
-    handle = direct_buffer_->handle();
+    handle = direct_buffer_->buffer();
     acquire_fence_fd_.Close();
   }
 
diff --git a/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/services/schedulerservice/SchedulingPolicyService.cpp b/services/schedulerservice/SchedulingPolicyService.cpp
index 522a8c0..a1106cf 100644
--- a/services/schedulerservice/SchedulingPolicyService.cpp
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -29,23 +29,37 @@
 namespace V1_0 {
 namespace implementation {
 
-Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
+bool SchedulingPolicyService::isAllowed() {
     using ::android::hardware::IPCThreadState;
 
+    return IPCThreadState::self()->getCallingUid() == AID_CAMERASERVER;
+}
+
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
     if (priority < static_cast<int32_t>(Priority::MIN) ||
             priority > static_cast<int32_t>(Priority::MAX)) {
         return false;
     }
 
-    if (IPCThreadState::self()->getCallingUid() != AID_CAMERASERVER) {
+    if (!isAllowed()) {
         return false;
     }
 
+    // TODO(b/37226359): decouple from and remove AIDL service
     // this should always be allowed since we are in system_server.
     int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
     return value == 0 /* success */;
 }
 
+Return<int32_t> SchedulingPolicyService::getMaxAllowedPriority() {
+    if (!isAllowed()) {
+        return 0;
+    }
+
+    // TODO(b/37226359): decouple from and remove AIDL service
+    return 3;
+}
+
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace schedulerservice
diff --git a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
index eb5a4ae..7d1c478 100644
--- a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -38,6 +38,9 @@
 
 struct SchedulingPolicyService : public ISchedulingPolicyService {
     Return<bool> requestPriority(int32_t pid, int32_t tid, int32_t priority) override;
+    Return<int32_t> getMaxAllowedPriority() override;
+private:
+    bool isAllowed();
 };
 
 }  // namespace implementation
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
index 773ce8c..adc4675 100644
--- a/services/sensorservice/hidl/DirectReportChannel.cpp
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -31,10 +31,13 @@
 }
 
 // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+Return<void> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate,
+        configure_cb _hidl_cb) {
     int token = mManager.configureDirectChannel(mId,
             static_cast<int>(sensorHandle), static_cast<int>(rate));
-    return token <= 0 ? convertResult(token) : Result::OK;
+    _hidl_cb(token <= 0 ? 0 : token,
+             token <= 0 ? convertResult(token) : Result::OK);
+    return Void();
 }
 
 
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
index 9134944..dd67827 100644
--- a/services/sensorservice/hidl/DirectReportChannel.h
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -47,7 +47,8 @@
     ~DirectReportChannel();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-    Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+    Return<void> configure(int32_t sensorHandle, RateLevel rate,
+            configure_cb _hidl_cb) override;
 
 private:
     ::android::SensorManager& mManager;
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index 86d365c..c0365e5 100644
--- a/services/sensorservice/hidl/EventQueue.cpp
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -39,7 +39,8 @@
 
         while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
             internalQueue->sendAck(&event, actual);
-            mCallback->onEvent(convertEvent(event));
+            Return<void> ret = mCallback->onEvent(convertEvent(event));
+            (void)ret.isOk(); // ignored
         }
 
         return 1; // continue to receive callbacks
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 0743fc3..06ff95c 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -22,12 +22,14 @@
 
 #include "SensorManager.h"
 
+#include <sched.h>
+
+#include <thread>
+
 #include "EventQueue.h"
 #include "DirectReportChannel.h"
 #include "utils.h"
 
-#include <thread>
-
 namespace android {
 namespace frameworks {
 namespace sensorservice {
@@ -131,6 +133,14 @@
         std::condition_variable looperSet;
 
         std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+
+            struct sched_param p = {0};
+            p.sched_priority = 10;
+            if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
+                LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
+                        << strerror(errno);
+            }
+
             std::unique_lock<std::mutex> lock(mutex);
             looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
             lock.unlock();
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 33aa759..262ab62 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,6 @@
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
 
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <inttypes.h>
 #include <log/log.h>
 #include <gui/BufferQueue.h>
@@ -26,7 +25,6 @@
 
 namespace android {
 
-using frameworks::vr::composer::V1_0::IVrComposerClient;
 using hardware::Return;
 using hardware::hidl_vec;
 using hardware::hidl_handle;
@@ -124,6 +122,41 @@
     endCommand();
 }
 
+void Composer::CommandWriter::setClientTargetMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetClientTargetMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
+        kSetClientTargetMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::setLayerBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    constexpr uint16_t kSetLayerBufferMetadataLength = 7;
+    beginCommand(
+        static_cast<IComposerClient::Command>(
+            IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
+        kSetLayerBufferMetadataLength);
+    writeBufferMetadata(metadata);
+    endCommand();
+}
+
+void Composer::CommandWriter::writeBufferMetadata(
+        const IVrComposerClient::BufferMetadata& metadata)
+{
+    write(metadata.width);
+    write(metadata.height);
+    write(metadata.stride);
+    write(metadata.layerCount);
+    writeSigned(static_cast<int32_t>(metadata.format));
+    write64(metadata.usage);
+}
+
 Composer::Composer(bool useVrComposer)
     : mWriter(kWriterInitialSize),
       mIsUsingVrComposer(useVrComposer)
@@ -426,12 +459,29 @@
 }
 
 Error Composer::setClientTarget(Display display, uint32_t slot,
-        const native_handle_t* target,
+        const sp<GraphicBuffer>& target,
         int acquireFence, Dataspace dataspace,
         const std::vector<IComposerClient::Rect>& damage)
 {
     mWriter.selectDisplay(display);
-    mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
+    if (mIsUsingVrComposer && target.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = target->getWidth(),
+            .height = target->getHeight(),
+            .stride = target->getStride(),
+            .layerCount = target->getLayerCount(),
+            .format = static_cast<PixelFormat>(target->getPixelFormat()),
+            .usage = target->getUsage(),
+        };
+        mWriter.setClientTargetMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (target.get()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
     return Error::NONE;
 }
 
@@ -502,11 +552,28 @@
 }
 
 Error Composer::setLayerBuffer(Display display, Layer layer,
-        uint32_t slot, const native_handle_t* buffer, int acquireFence)
+        uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
 {
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
-    mWriter.setLayerBuffer(slot, buffer, acquireFence);
+    if (mIsUsingVrComposer && buffer.get()) {
+        IVrComposerClient::BufferMetadata metadata = {
+            .width = buffer->getWidth(),
+            .height = buffer->getHeight(),
+            .stride = buffer->getStride(),
+            .layerCount = buffer->getLayerCount(),
+            .format = static_cast<PixelFormat>(buffer->getPixelFormat()),
+            .usage = buffer->getUsage(),
+        };
+        mWriter.setLayerBufferMetadata(metadata);
+    }
+
+    const native_handle_t* handle = nullptr;
+    if (buffer.get()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
+    mWriter.setLayerBuffer(slot, handle, acquireFence);
     return Error::NONE;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 18af9dd..37b7766 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,6 +23,7 @@
 #include <utility>
 #include <vector>
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <utils/StrongPointer.h>
 #include <IComposerCommandBuffer.h>
@@ -31,6 +32,8 @@
 
 namespace Hwc2 {
 
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Dataspace;
@@ -179,7 +182,7 @@
      * When target is not nullptr, the cache is updated with the new target.
      */
     Error setClientTarget(Display display, uint32_t slot,
-            const native_handle_t* target,
+            const sp<GraphicBuffer>& target,
             int acquireFence, Dataspace dataspace,
             const std::vector<IComposerClient::Rect>& damage);
     Error setColorMode(Display display, ColorMode mode);
@@ -199,7 +202,7 @@
             int32_t x, int32_t y);
     /* see setClientTarget for the purpose of slot */
     Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
-            const native_handle_t* buffer, int acquireFence);
+            const sp<GraphicBuffer>& buffer, int acquireFence);
     Error setLayerSurfaceDamage(Display display, Layer layer,
             const std::vector<IComposerClient::Rect>& damage);
     Error setLayerBlendMode(Display display, Layer layer,
@@ -232,6 +235,14 @@
         ~CommandWriter() override;
 
         void setLayerInfo(uint32_t type, uint32_t appId);
+        void setClientTargetMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+        void setLayerBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
+
+    private:
+        void writeBufferMetadata(
+                const IVrComposerClient::BufferMetadata& metadata);
     };
 
     // Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e49e734..8270c39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -244,7 +244,7 @@
         ALOGE("Failed to get display by id");
         return Error::BadDisplay;
     }
-    (*outDisplay)->setVirtual();
+    (*outDisplay)->setConnected(true);
     return Error::None;
 }
 
@@ -531,15 +531,28 @@
   : mDevice(device),
     mId(id),
     mIsConnected(false),
-    mIsVirtual(false)
+    mType(DisplayType::Invalid)
 {
     ALOGV("Created display %" PRIu64, id);
+
+#ifdef BYPASS_IHWC
+    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+            reinterpret_cast<int32_t *>(&mType));
+#else
+    auto intError = mDevice.mComposer->getDisplayType(mId,
+            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
+#endif
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
+              id, to_string(error).c_str(), intError);
+    }
 }
 
 Display::~Display()
 {
     ALOGV("Destroyed display %" PRIu64, mId);
-    if (mIsVirtual) {
+    if (mType == DisplayType::Virtual) {
         mDevice.destroyVirtualDisplay(mId);
     }
 }
@@ -802,21 +815,7 @@
 
 Error Display::getType(DisplayType* outType) const
 {
-#ifdef BYPASS_IHWC
-    int32_t intType = 0;
-    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
-            &intType);
-#else
-    Hwc2::IComposerClient::DisplayType intType =
-        Hwc2::IComposerClient::DisplayType::INVALID;
-    auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
-#endif
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    *outType = static_cast<DisplayType>(intType);
+    *outType = mType;
     return Error::None;
 }
 
@@ -961,14 +960,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
         const sp<Fence>& acquireFence, android_dataspace_t dataspace)
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
-    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+    buffer_handle_t handle = nullptr;
+    if (target.get() && target->getNativeBuffer()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+
+    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
             fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
 #else
     auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
@@ -1195,14 +1199,19 @@
     return static_cast<Error>(intError);
 }
 
-Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
 #ifdef BYPASS_IHWC
     (void) slot;
+    buffer_handle_t handle = nullptr;
+    if (buffer.get() && buffer->getNativeBuffer()) {
+        handle = buffer->getNativeBuffer()->handle;
+    }
+
     int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
-            mId, buffer, fenceFd);
+            mId, handle, fenceFd);
 #else
     auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
             mId, slot, buffer, fenceFd);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4419dc1..643b1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -329,7 +329,7 @@
     [[clang::warn_unused_result]] Error setActiveConfig(
             const std::shared_ptr<const Config>& config);
     [[clang::warn_unused_result]] Error setClientTarget(
-            uint32_t slot, buffer_handle_t target,
+            uint32_t slot, const android::sp<android::GraphicBuffer>& target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
     [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -352,12 +352,6 @@
 private:
     // For use by Device
 
-    // Virtual displays are always connected
-    void setVirtual() {
-        mIsVirtual = true;
-        mIsConnected = true;
-    }
-
     void setConnected(bool connected) { mIsConnected = connected; }
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
     void loadConfig(hwc2_config_t configId);
@@ -375,7 +369,7 @@
     Device& mDevice;
     hwc2_display_t mId;
     bool mIsConnected;
-    bool mIsVirtual;
+    DisplayType mType;
     std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
 };
@@ -392,7 +386,7 @@
 
     [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
     [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
-            buffer_handle_t buffer,
+            const android::sp<android::GraphicBuffer>& buffer,
             const android::sp<android::Fence>& acquireFence);
     [[clang::warn_unused_result]] Error setSurfaceDamage(
             const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 09434f6..40979c9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -206,7 +206,7 @@
         }
         disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-    mEventHandler->onHotplugReceived(disp,
+    mEventHandler->onHotplugReceived(this, disp,
             connected == HWC2::Connection::Connected);
 }
 
@@ -465,12 +465,7 @@
 
     ALOGV("setClientTarget for display %d", displayId);
     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    buffer_handle_t handle = nullptr;
-    if ((target != nullptr) && target->getNativeBuffer()) {
-        handle = target->getNativeBuffer()->handle;
-    }
-    auto error = hwcDisplay->setClientTarget(slot, handle,
-            acquireFence, dataspace);
+    auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
     if (error != HWC2::Error::None) {
         ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 81f1619..78d0307 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -70,7 +70,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 5b5f1cf..dcb2913 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -315,7 +315,7 @@
     queryDisplayProperties(disp);
     // Do not teardown or recreate the primary display
     if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(disp, bool(connected));
+        mEventHandler.onHotplugReceived(this, disp, bool(connected));
     }
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index f64d69a..4bc63bb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -62,7 +62,7 @@
         friend class HWComposer;
         virtual void onVSyncReceived(
             HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0;
         virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c211c7b..598a65a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -852,18 +852,12 @@
     }
 
     uint32_t hwcSlot = 0;
-    buffer_handle_t hwcHandle = nullptr;
-    {
-        sp<GraphicBuffer> hwcBuffer;
-        hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
-                &hwcSlot, &hwcBuffer);
-        if (hwcBuffer != nullptr) {
-            hwcHandle = hwcBuffer->handle;
-        }
-    }
+    sp<GraphicBuffer> hwcBuffer;
+    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+            &hwcSlot, &hwcBuffer);
 
     auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-    error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
+    error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
                 mActiveBuffer->handle, to_string(error).c_str(),
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 26baaae..76a5d06 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -598,7 +598,7 @@
 
     // make the GLContext current so that we can create textures when creating
     // Layers (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -714,8 +714,11 @@
             info.density = density;
 
             // TODO: this needs to go away (currently needed only by webkit)
-            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-            info.orientation = hw->getOrientation();
+            {
+                Mutex::Autolock _l(mStateLock);
+                sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
+                info.orientation = hw->getOrientation();
+            }
         } else {
             // TODO: where should this value come from?
             static const int TV_DENSITY = 213;
@@ -772,10 +775,13 @@
         ALOGE("%s : display is NULL", __func__);
         return BAD_VALUE;
     }
+
+    Mutex::Autolock _l(mStateLock);
     sp<DisplayDevice> device(getDisplayDevice(display));
     if (device != NULL) {
         return device->getActiveConfig();
     }
+
     return BAD_VALUE;
 }
 
@@ -863,6 +869,7 @@
 }
 
 android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    Mutex::Autolock _l(mStateLock);
     sp<DisplayDevice> device(getDisplayDevice(display));
     if (device != nullptr) {
         return device->getActiveColorMode();
@@ -1124,55 +1131,60 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
+void SurfaceFlinger::createDefaultDisplayDevice() {
+    const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+    wp<IBinder> token = mBuiltinDisplays[type];
+
+    // All non-virtual displays are currently considered secure.
+    const bool isSecure = true;
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc());
+
+    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, type, consumer);
+
+    bool hasWideColorModes = false;
+    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(
+        type);
+    for (android_color_mode_t colorMode : modes) {
+        switch (colorMode) {
+            case HAL_COLOR_MODE_DISPLAY_P3:
+            case HAL_COLOR_MODE_ADOBE_RGB:
+            case HAL_COLOR_MODE_DCI_P3:
+                hasWideColorModes = true;
+                break;
+            default:
+                break;
+        }
+    }
+    sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
+                                             token, fbs, producer, mRenderEngine->getEGLConfig(),
+                                             hasWideColorModes && hasWideColorDisplay);
+    mDisplays.add(token, hw);
+    android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+    if (hasWideColorModes && hasWideColorDisplay) {
+        defaultColorMode = HAL_COLOR_MODE_SRGB;
+    }
+    setActiveColorModeInternal(hw, defaultColorMode);
+}
+
+void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
     ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+
+    if (composer->isUsingVrComposer()) {
+        // We handle initializing the primary display device for the VR
+        // window manager hwc explicitly at the time of transition.
+        if (disp != DisplayDevice::DISPLAY_PRIMARY) {
+            ALOGE("External displays are not supported by the vr hardware composer.");
+        }
+        return;
+    }
+
     if (disp == DisplayDevice::DISPLAY_PRIMARY) {
         Mutex::Autolock lock(mStateLock);
-
-        // All non-virtual displays are currently considered secure.
-        bool isSecure = true;
-
-        int32_t type = DisplayDevice::DISPLAY_PRIMARY;
-
-        // When we're using the vr composer, the assumption is that we've
-        // already created the IBinder object for the primary display.
-        if (!mHwc->isUsingVrComposer()) {
-            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
-        }
-
-        wp<IBinder> token = mBuiltinDisplays[type];
-
-        sp<IGraphicBufferProducer> producer;
-        sp<IGraphicBufferConsumer> consumer;
-        BufferQueue::createBufferQueue(&producer, &consumer,
-                new GraphicBufferAlloc());
-
-        sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
-                DisplayDevice::DISPLAY_PRIMARY, consumer);
-
-        bool hasWideColorModes = false;
-        std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
-        for (android_color_mode_t colorMode : modes) {
-            switch (colorMode) {
-                case HAL_COLOR_MODE_DISPLAY_P3:
-                case HAL_COLOR_MODE_ADOBE_RGB:
-                case HAL_COLOR_MODE_DCI_P3:
-                    hasWideColorModes = true;
-                    break;
-                default:
-                    break;
-            }
-        }
-        sp<DisplayDevice> hw =
-                new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
-                                  producer, mRenderEngine->getEGLConfig(),
-                                  hasWideColorModes && hasWideColorDisplay);
-        mDisplays.add(token, hw);
-        android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
-        if (hasWideColorModes && hasWideColorDisplay) {
-            defaultColorMode = HAL_COLOR_MODE_SRGB;
-        }
-        setActiveColorModeInternal(hw, defaultColorMode);
+        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+        createDefaultDisplayDevice();
     } else {
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
         Mutex::Autolock _l(mStateLock);
@@ -1214,6 +1226,7 @@
     }
 }
 
+// Note: it is assumed the caller holds |mStateLock| when this is called
 void SurfaceFlinger::resetHwc() {
     disableHardwareVsync(true);
     clearHwcLayers(mDrawingState.layersSortedByZ);
@@ -1234,36 +1247,46 @@
     if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) {
         return;
     }
+
+    bool vrHwcNewlyInitialized = false;
+
     if (vrFlingerRequestsDisplay && !mVrHwc) {
         // Construct new HWComposer without holding any locks.
         mVrHwc = new HWComposer(true);
+        vrHwcNewlyInitialized = true;
         ALOGV("Vr HWC created");
     }
-    {
-        Mutex::Autolock _l(mStateLock);
 
-        if (vrFlingerRequestsDisplay) {
-            resetHwc();
+    Mutex::Autolock _l(mStateLock);
 
-            mHwc = mVrHwc;
-            mVrFlinger->GrantDisplayOwnership();
-        } else {
-            mVrFlinger->SeizeDisplayOwnership();
+    if (vrFlingerRequestsDisplay) {
+        resetHwc();
 
-            resetHwc();
+        mHwc = mVrHwc;
+        mVrFlinger->GrantDisplayOwnership();
 
-            mHwc = mRealHwc;
-            enableHardwareVsync();
+        if (vrHwcNewlyInitialized) {
+            mVrHwc->setEventHandler(
+                static_cast<HWComposer::EventHandler*>(this));
         }
+    } else {
+        mVrFlinger->SeizeDisplayOwnership();
 
-        mVisibleRegionsDirty = true;
-        invalidateHwcGeometry();
-        android_atomic_or(1, &mRepaintEverything);
-        setTransactionFlags(eDisplayTransactionNeeded);
+        resetHwc();
+
+        mHwc = mRealHwc;
+        enableHardwareVsync();
     }
-    if (mVrHwc) {
-        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-    }
+
+    mVisibleRegionsDirty = true;
+    invalidateHwcGeometry();
+
+    // Explicitly re-initialize the primary display. This is because some other
+    // parts of this class rely on the primary display always being available.
+    createDefaultDisplayDevice();
+
+    android_atomic_or(1, &mRepaintEverything);
+    setTransactionFlags(eDisplayTransactionNeeded);
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -1473,7 +1496,8 @@
         layer->releasePendingBuffer(dequeueReadyTime);
     }
 
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    // |mStateLock| not needed as we are on the main thread
+    const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
     if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
@@ -1821,7 +1845,8 @@
     mLastSwapBufferTime = systemTime() - now;
     mDebugInSwapBuffers = 0;
 
-    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
+    // |mStateLock| not needed as we are on the main thread
+    uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
     if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
         logFrameStats();
     }
@@ -1906,7 +1931,7 @@
                         // Call makeCurrent() on the primary display so we can
                         // be sure that nothing associated with this display
                         // is current.
-                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                         defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                         sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                         if (hw != NULL)
@@ -2096,7 +2121,7 @@
                 // could be null when this layer is using a layerStack
                 // that is not visible on any display. Also can occur at
                 // screen off/on times.
-                disp = getDefaultDisplayDevice();
+                disp = getDefaultDisplayDeviceLocked();
             }
             layer->updateTransformHint(disp);
 
@@ -2452,7 +2477,9 @@
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   displayDevice->getDisplayName().string());
             eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
+
+            // |mStateLock| not needed as we are on the main thread
+            if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
             }
             return false;
@@ -3539,7 +3566,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
@@ -3769,7 +3796,7 @@
                 return NO_ERROR;
             case 1013: {
                 Mutex::Autolock _l(mStateLock);
-                sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+                sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
                 reply->writeInt32(hw->getPageFlipCount());
                 return NO_ERROR;
             }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 46121cf..219d662 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -184,8 +184,9 @@
     void repaintEverything();
 
     // returns the default Display
-    sp<const DisplayDevice> getDefaultDisplayDevice() const {
-        return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+    sp<const DisplayDevice> getDefaultDisplayDevice() {
+        Mutex::Autolock _l(mStateLock);
+        return getDefaultDisplayDeviceLocked();
     }
 
     // utility function to delete a texture on the main thread
@@ -304,7 +305,7 @@
      * HWComposer::EventHandler interface
      */
     virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
-    virtual void onHotplugReceived(int disp, bool connected);
+    virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
     virtual void onInvalidateReceived(HWComposer* composer);
 
     /* ------------------------------------------------------------------------
@@ -439,6 +440,12 @@
         return mDisplays.valueFor(dpy);
     }
 
+    sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
+        return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+    }
+
+    void createDefaultDisplayDevice();
+
     int32_t getDisplayType(const sp<IBinder>& display) {
         if (!display.get()) return NAME_NOT_FOUND;
         for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index e640ef7..cd2acef 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -584,7 +584,7 @@
 
     // make the GLContext current so that we can create textures when creating Layers
     // (which may happens before we render something)
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -1040,7 +1040,7 @@
     *compositorTiming = mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
+void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
     if (mEventThread == NULL) {
         // This is a temporary workaround for b/7145521.  A non-null pointer
         // does not mean EventThread has finished initializing, so this
@@ -3222,7 +3222,7 @@
     colorizer.reset(result);
 
     HWComposer& hwc(getHwComposer());
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 2ce60e5..4b1a522 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -1,5 +1,6 @@
 #include "buffer_hub.h"
 
+#include <inttypes.h>
 #include <log/log.h>
 #include <poll.h>
 #include <utils/Trace.h>
@@ -52,7 +53,7 @@
   stream << " ";
   stream << std::setw(6) << "Format";
   stream << " ";
-  stream << std::setw(10) << "Usage";
+  stream << std::setw(21) << "Usage";
   stream << " ";
   stream << "Name";
   stream << std::endl;
@@ -79,7 +80,9 @@
       stream << std::setw(6) << info.format;
       stream << " ";
       stream << "0x" << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage;
+      stream << std::setw(8) << info.producer_usage;
+      stream << "0x";
+      stream << std::setw(8) << info.consumer_usage;
       stream << std::dec << std::setfill(' ');
       stream << " ";
       stream << info.name;
@@ -137,6 +140,10 @@
   stream << " UsageClearMask";
   stream << " UsageDenySetMask";
   stream << " UsageDenyClearMask";
+  stream << " UsageSetMask";
+  stream << " UsageClearMask";
+  stream << " UsageDenySetMask";
+  stream << " UsageDenyClearMask";
   stream << " ";
   stream << std::endl;
 
@@ -150,16 +157,30 @@
       stream << std::right << std::setw(12) << info.consumer_count;
       stream << std::setw(5) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_set_mask;
       stream << std::setw(7) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_clear_mask;
+      stream << std::setw(8) << info.usage_policy.producer_clear_mask;
       stream << std::setw(9) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_set_mask;
+      stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
       stream << std::setw(11) << std::setfill(' ') << "0x";
       stream << std::hex << std::setfill('0');
-      stream << std::setw(8) << info.usage_deny_clear_mask;
+      stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
+      stream << std::setw(5) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_set_mask;
+      stream << std::setw(7) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
+      stream << std::setw(9) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
+      stream << std::setw(11) << std::setfill(' ') << "0x";
+      stream << std::hex << std::setfill('0');
+      stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+      stream << std::hex << std::setfill('0');
+      stream << std::endl;
     }
   }
 
@@ -177,6 +198,7 @@
 
       stream << std::right << std::setw(6) << info.id;
       stream << std::right << std::setw(12) << info.capacity;
+      stream << std::endl;
     }
   }
 
@@ -235,48 +257,53 @@
     buffer->Detach();
 }
 
-int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
-                                     int format, int usage,
-                                     size_t meta_size_bytes,
-                                     size_t slice_count) {
+Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
+                                              uint32_t height, uint32_t format,
+                                              uint64_t producer_usage,
+                                              uint64_t consumer_usage,
+                                              size_t meta_size_bytes,
+                                              size_t slice_count) {
   // Use the producer channel id as the global buffer id.
   const int buffer_id = message.GetChannelId();
   ALOGD_IF(TRACE,
-           "BufferHubService::OnCreateBuffer: buffer_id=%d width=%d height=%d "
-           "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
-           buffer_id, width, height, format, usage, meta_size_bytes,
-           slice_count);
+           "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
+           "format=%u producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " meta_size_bytes=%zu slice_count=%zu",
+           buffer_id, width, height, format, producer_usage, consumer_usage,
+           meta_size_bytes, slice_count);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
     ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
           buffer_id);
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel =
-          ProducerChannel::Create(this, buffer_id, width, height, format, usage,
-                                  meta_size_bytes, slice_count, &error)) {
-    message.SetChannel(producer_channel);
-    return 0;
+  auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
+                                        producer_usage, consumer_usage,
+                                        meta_size_bytes, slice_count);
+  if (status) {
+    message.SetChannel(status.take());
+    return {};
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
+          status.GetErrorMessage().c_str());
+    return status.error_status();
   }
 }
 
-int BufferHubService::OnCreatePersistentBuffer(
+Status<void> BufferHubService::OnCreatePersistentBuffer(
     Message& message, const std::string& name, int user_id, int group_id,
-    int width, int height, int format, int usage, size_t meta_size_bytes,
-    size_t slice_count) {
+    uint32_t width, uint32_t height, uint32_t format, uint64_t producer_usage,
+    uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
-           "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
-           "meta_size_bytes=%zu slice_count=%zu",
+           "user_id=%d group_id=%d width=%u height=%u format=%u "
+           "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+           " meta_size_bytes=%zu slice_count=%zu",
            channel_id, name.c_str(), user_id, group_id, width, height, format,
-           usage, meta_size_bytes, slice_count);
+           producer_usage, consumer_usage, meta_size_bytes, slice_count);
 
   // See if this channel is already attached to a buffer.
   if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -284,12 +311,11 @@
         "BufferHubService::OnCreatePersistentBuffer: Channel already attached "
         "to buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
   const int egid = message.GetEffectiveGroupId();
-  int error;
 
   if (auto buffer = GetNamedBuffer(name)) {
     if (!buffer->CheckAccess(euid, egid)) {
@@ -297,41 +323,45 @@
           "BufferHubService::OnCreatePersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, euid);
-      return -EPERM;
-    } else if (!buffer->CheckParameters(width, height, format, usage,
-                                        meta_size_bytes, slice_count)) {
+      return ErrorStatus(EPERM);
+    } else if (!buffer->CheckParameters(width, height, format, producer_usage,
+                                        consumer_usage, meta_size_bytes,
+                                        slice_count)) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requested an existing "
           "buffer with different parameters: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
-  } else if (auto buffer = ProducerChannel::Create(
-                 this, channel_id, width, height, format, usage,
-                 meta_size_bytes, slice_count, &error)) {
-    const int ret =
-        buffer->OnProducerMakePersistent(message, name, user_id, group_id);
-    if (!ret)
-      message.SetChannel(buffer);
-    return ret;
   } else {
-    ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return error;
+    auto status = ProducerChannel::Create(
+        this, channel_id, width, height, format, producer_usage, consumer_usage,
+        meta_size_bytes, slice_count);
+    if (!status) {
+      ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
+      return status.error_status();
+    }
+    auto persistent_buffer = status.take();
+    auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
+        message, name, user_id, group_id);
+    if (make_persistent_status)
+      message.SetChannel(persistent_buffer);
+    return make_persistent_status;
   }
 }
 
-int BufferHubService::OnGetPersistentBuffer(Message& message,
-                                            const std::string& name) {
+Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
+                                                     const std::string& name) {
   const int channel_id = message.GetChannelId();
   ALOGD_IF(TRACE,
            "BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
@@ -343,7 +373,7 @@
         "BufferHubService::OnGetPersistentBuffer: Channel already attached to "
         "buffer: channel_id=%d buffer_id=%d",
         channel_id, channel->buffer_id());
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 
   const int euid = message.GetEffectiveUserId();
@@ -355,28 +385,28 @@
           "BufferHubService::OnGetPersistentBuffer: Requesting process does "
           "not have permission to access named buffer: name=%s euid=%d egid=%d",
           name.c_str(), euid, egid);
-      return -EPERM;
+      return ErrorStatus(EPERM);
     } else if (!buffer->IsDetached()) {
       ALOGE(
           "BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
           "buffer that is already attached to a channel: name=%s",
           name.c_str());
-      return -EINVAL;
+      return ErrorStatus(EINVAL);
     } else {
       buffer->Attach(channel_id);
       message.SetChannel(buffer);
-      return 0;
+      return {};
     }
   } else {
     ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
           name.c_str());
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
   }
 }
 
 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) {
+    pdx::Message& message, size_t meta_size_bytes,
+    const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
   ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
@@ -389,15 +419,14 @@
     return ErrorStatus(EALREADY);
   }
 
-  int error;
-  if (const auto producer_channel = ProducerQueueChannel::Create(
-          this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-          usage_deny_set_mask, usage_deny_clear_mask, &error)) {
-    message.SetChannel(producer_channel);
+  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+                                             usage_policy);
+  if (status) {
+    message.SetChannel(status.take());
     return {{meta_size_bytes, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
-    return ErrorStatus(-error);
+    return status.error_status();
   }
 }
 
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 150e399..4cb1eb9 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -48,43 +48,40 @@
     size_t consumer_count = 0;
 
     // Data field for buffer producer.
-    int width = 0;
-    int height = 0;
-    int format = 0;
-    int usage = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint64_t producer_usage = 0;
+    uint64_t consumer_usage = 0;
     size_t slice_count = 0;
     std::string name;
 
     // Data filed for producer queue.
     size_t capacity = 0;
-    int usage_set_mask = 0;
-    int usage_clear_mask = 0;
-    int usage_deny_set_mask = 0;
-    int usage_deny_clear_mask = 0;
+    UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
 
-    BufferInfo(int id, size_t consumer_count, int width, int height, int format,
-               int usage, size_t slice_count, const std::string& name)
+    BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
+               uint32_t format, uint64_t producer_usage,
+               uint64_t consumer_usage, size_t slice_count,
+               const std::string& name)
         : id(id),
           type(kProducerType),
           consumer_count(consumer_count),
           width(width),
           height(height),
           format(format),
-          usage(usage),
+          producer_usage(producer_usage),
+          consumer_usage(consumer_usage),
           slice_count(slice_count),
           name(name) {}
 
     BufferInfo(int id, size_t consumer_count, size_t capacity,
-               int usage_set_mask, int usage_clear_mask,
-               int usage_deny_set_mask, int usage_deny_clear_mask)
+               const UsagePolicy& usage_policy)
         : id(id),
           type(kProducerQueueType),
           consumer_count(consumer_count),
           capacity(capacity),
-          usage_set_mask(usage_set_mask),
-          usage_clear_mask(usage_clear_mask),
-          usage_deny_set_mask(usage_deny_set_mask),
-          usage_deny_clear_mask(usage_deny_clear_mask) {}
+          usage_policy(usage_policy) {}
 
     BufferInfo() {}
   };
@@ -162,16 +159,19 @@
   std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
       named_buffers_;
 
-  int OnCreateBuffer(pdx::Message& message, int width, int height, int format,
-                     int usage, size_t meta_size_bytes, size_t slice_count);
-  int OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
-                               int user_id, int group_id, int width, int height,
-                               int format, int usage, size_t meta_size_bytes,
-                               size_t slice_count);
-  int OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
-  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);
+  pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, uint32_t height,
+                     uint32_t format, uint64_t producer_usage,
+                     uint64_t consumer_usage, size_t meta_size_bytes,
+                     size_t slice_count);
+  pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
+                               int user_id, int group_id, uint32_t width,
+                               uint32_t height, uint32_t format,
+                               uint64_t producer_usage, uint64_t consumer_usage,
+                               size_t meta_size_bytes, size_t slice_count);
+  pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
+  pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
+                                               size_t meta_size_bytes,
+                                               const UsagePolicy& usage_policy);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 2264cef..311f5c6 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,11 @@
 #include <private/dvr/bufferhub_rpc.h>
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
 using android::pdx::BorrowedHandle;
 using android::pdx::Channel;
 using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -103,53 +105,53 @@
   }
 }
 
-std::pair<BorrowedFence, ConsumerChannel::MetaData>
+Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
 ConsumerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
   auto producer = GetProducer();
   if (!producer)
-    REPLY_ERROR_RETURN(message, EPIPE, {});
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
     return producer->OnConsumerAcquire(message, metadata_size);
   }
 }
 
-int ConsumerChannel::OnConsumerRelease(Message& message,
-                                       LocalFence release_fence) {
+Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   if (ignored_ || handled_) {
     ALOGE(
         "ConsumerChannel::OnConsumerRelease: Release when not acquired: "
         "ignored=%d handled=%d channel_id=%d buffer_id=%d",
         ignored_, handled_, message.GetChannelId(), producer->buffer_id());
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   } else {
     ClearAvailable();
-    const int ret =
+    auto status =
         producer->OnConsumerRelease(message, std::move(release_fence));
-    handled_ = ret == 0;
-    return ret;
+    handled_ = !!status;
+    return status;
   }
 }
 
-int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
+Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
   ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
   auto producer = GetProducer();
   if (!producer)
-    return -EPIPE;
+    return ErrorStatus(EPIPE);
 
   ignored_ = ignored;
   if (ignored_ && !handled_) {
@@ -160,7 +162,7 @@
     handled_ = false;
   }
 
-  return 0;
+  return {};
 }
 
 bool ConsumerChannel::OnProducerPosted() {
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d2a078f..d84055c 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -32,10 +32,11 @@
 
   std::shared_ptr<ProducerChannel> GetProducer() const;
 
-  std::pair<BorrowedFence, MetaData> OnConsumerAcquire(
+  pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
       Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
-  int OnConsumerSetIgnore(Message& message, bool ignore);
+  pdx::Status<void> OnConsumerRelease(Message& message,
+                                      LocalFence release_fence);
+  pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
 
   bool handled_;  // True if we have processed RELEASE.
   bool ignored_;  // True if we are ignoring events.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index cc16f1f..7422751 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -4,7 +4,9 @@
 
 #include "producer_channel.h"
 
+using android::pdx::ErrorStatus;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::DispatchRemoteMethod;
 
 namespace android {
@@ -83,7 +85,7 @@
   SignalAvailable();
 }
 
-std::vector<std::pair<RemoteChannelHandle, size_t>>
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
 ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
   ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
@@ -106,31 +108,30 @@
       continue;
     }
 
-    RemoteChannelHandle consumer_handle(
-        producer_channel->CreateConsumer(message));
+    auto status = producer_channel->CreateConsumer(message);
 
     // If no buffers are imported successfully, clear available and return an
     // error. Otherwise, return all consumer handles already imported
     // successfully, but keep available bits on, so that the client can retry
     // importing remaining consumer buffers.
-    if (!consumer_handle.valid()) {
+    if (!status) {
       ALOGE(
-          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: imported "
-          "consumer handle is invalid.");
+          "ConsumerQueueChannel::OnConsumerQueueImportBuffers: Failed create "
+          "consumer: %s",
+          status.GetErrorMessage().c_str());
       if (buffer_handles.empty()) {
         ClearAvailable();
-        REPLY_ERROR_RETURN(message, EIO, {});
+        return status.error_status();
       } else {
-        return buffer_handles;
+        return {std::move(buffer_handles)};
       }
     }
 
-    // Move consumer_handle into buffer_handles.
-    buffer_handles.emplace_back(std::move(consumer_handle), producer_slot);
+    buffer_handles.emplace_back(status.take(), producer_slot);
   }
 
   ClearAvailable();
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index b345595..e1005e4 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -36,7 +36,7 @@
   // allocated. Clients uses kOpConsumerQueueImportBuffers to import new
   // consumer buffers and this handler returns a vector of fd representing
   // BufferConsumers that clients can import.
-  std::vector<std::pair<RemoteChannelHandle, size_t>>
+  pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
   OnConsumerQueueImportBuffers(Message& message);
 
  private:
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 903d174..c946a8d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -13,8 +13,10 @@
 #include "consumer_channel.h"
 
 using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
 using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
 using android::pdx::rpc::BufferWrapper;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::WrapBuffer;
@@ -23,7 +25,9 @@
 namespace dvr {
 
 ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
-                                 int width, int height, int format, int usage,
+                                 uint32_t width, uint32_t height,
+                                 uint32_t format, uint64_t producer_usage,
+                                 uint64_t consumer_usage,
                                  size_t meta_size_bytes, size_t slice_count,
                                  int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -33,7 +37,8 @@
       meta_size_bytes_(meta_size_bytes),
       meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
   for (auto& ion_buffer : slices_) {
-    const int ret = ion_buffer.Alloc(width, height, format, usage);
+    const int ret =
+        ion_buffer.Alloc(width, height, format, producer_usage, consumer_usage);
     if (ret < 0) {
       ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
             strerror(-ret));
@@ -46,17 +51,18 @@
   *error = 0;
 }
 
-std::shared_ptr<ProducerChannel> ProducerChannel::Create(
-    BufferHubService* service, int channel_id, int width, int height,
-    int format, int usage, size_t meta_size_bytes, size_t slice_count,
-    int* error) {
-  std::shared_ptr<ProducerChannel> producer(
-      new ProducerChannel(service, channel_id, width, height, format, usage,
-                          meta_size_bytes, slice_count, error));
-  if (*error < 0)
-    return nullptr;
+Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
+    BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
+    uint32_t format, uint64_t producer_usage, uint64_t consumer_usage,
+    size_t meta_size_bytes, size_t slice_count) {
+  int error;
+  std::shared_ptr<ProducerChannel> producer(new ProducerChannel(
+      service, channel_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes, slice_count, &error));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 ProducerChannel::~ProducerChannel() {
@@ -70,7 +76,8 @@
 BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
   return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
                     slices_[0].height(), slices_[0].format(),
-                    slices_[0].usage(), slices_.size(), name_);
+                    slices_[0].producer_usage(), slices_[0].consumer_usage(),
+                    slices_.size(), name_);
 }
 
 void ProducerChannel::HandleImpulse(Message& message) {
@@ -125,28 +132,28 @@
   }
 }
 
-NativeBufferHandle<BorrowedHandle> ProducerChannel::OnGetBuffer(
+Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
     Message& message, unsigned index) {
   ATRACE_NAME("ProducerChannel::OnGetBuffer");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
   if (index < slices_.size()) {
-    return NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id());
+    return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
   } else {
-    REPLY_ERROR_RETURN(message, EINVAL, NativeBufferHandle<BorrowedHandle>());
+    return ErrorStatus(EINVAL);
   }
 }
 
-std::vector<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffers(
-    Message&) {
+Status<std::vector<NativeBufferHandle<BorrowedHandle>>>
+ProducerChannel::OnGetBuffers(Message&) {
   ATRACE_NAME("ProducerChannel::OnGetBuffers");
   ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffers: buffer_id=%d", buffer_id());
   std::vector<NativeBufferHandle<BorrowedHandle>> buffer_handles;
   for (const auto& buffer : slices_)
     buffer_handles.emplace_back(buffer, buffer_id());
-  return buffer_handles;
+  return {std::move(buffer_handles)};
 }
 
-RemoteChannelHandle ProducerChannel::CreateConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::CreateConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
 
@@ -154,9 +161,9 @@
   auto status = message.PushChannel(0, nullptr, &channel_id);
   if (!status) {
     ALOGE(
-        "ProducerChannel::CreateConsumer: failed to push consumer channel: %s",
+        "ProducerChannel::CreateConsumer: Failed to push consumer channel: %s",
         status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   auto consumer = std::make_shared<ConsumerChannel>(
@@ -167,7 +174,7 @@
         "ProducerChannel::CreateConsumer: failed to set new consumer channel: "
         "%s",
         channel_status.GetErrorMessage().c_str());
-    return RemoteChannelHandle();
+    return ErrorStatus(ENOMEM);
   }
 
   if (!producer_owns_) {
@@ -176,33 +183,27 @@
       pending_consumers_++;
   }
 
-  return status.take();
+  return {status.take()};
 }
 
-RemoteChannelHandle ProducerChannel::OnNewConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
   ATRACE_NAME("ProducerChannel::OnNewConsumer");
   ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
-
-  RemoteChannelHandle consumer_handle(CreateConsumer(message));
-
-  if (consumer_handle.valid())
-    return consumer_handle;
-  else
-    REPLY_ERROR_RETURN(message, ENOMEM, RemoteChannelHandle());
+  return CreateConsumer(message);
 }
 
-int ProducerChannel::OnProducerPost(
+Status<void> ProducerChannel::OnProducerPost(
     Message&, LocalFence acquire_fence,
     BufferWrapper<std::vector<std::uint8_t>> metadata) {
   ATRACE_NAME("ProducerChannel::OnProducerPost");
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
   if (!producer_owns_) {
     ALOGE("ProducerChannel::OnProducerPost: Not in gained state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   if (meta_size_bytes_ != metadata.size())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   std::copy(metadata.begin(), metadata.end(), meta_.get());
 
   post_fence_ = std::move(acquire_fence);
@@ -220,29 +221,29 @@
   ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
            pending_consumers_);
 
-  return 0;
+  return {};
 }
 
-LocalFence ProducerChannel::OnProducerGain(Message& message) {
+Status<LocalFence> ProducerChannel::OnProducerGain(Message& message) {
   ATRACE_NAME("ProducerChannel::OnGain");
   ALOGD_IF(TRACE, "ProducerChannel::OnGain: buffer_id=%d", buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChanneL::OnGain: Already in gained state: channel=%d",
           channel_id());
-    REPLY_ERROR_RETURN(message, EALREADY, {});
+    return ErrorStatus(EALREADY);
   }
 
   // There are still pending consumers, return busy.
   if (pending_consumers_ > 0)
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
 
   ClearAvailable();
   producer_owns_ = true;
   post_fence_.close();
-  return std::move(returned_fence_);
+  return {std::move(returned_fence_)};
 }
 
-std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>
+Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
 ProducerChannel::OnConsumerAcquire(Message& message,
                                    std::size_t metadata_size) {
   ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
@@ -250,26 +251,27 @@
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerAcquire: Not in posted state!");
-    REPLY_ERROR_RETURN(message, EBUSY, {});
+    return ErrorStatus(EBUSY);
   }
 
   // Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
   // Serialization just needs to read the handle.
   if (metadata_size == 0)
-    return std::make_pair(post_fence_.borrow(),
-                          WrapBuffer<std::uint8_t>(nullptr, 0));
+    return {std::make_pair(post_fence_.borrow(),
+                           WrapBuffer<std::uint8_t>(nullptr, 0))};
   else
-    return std::make_pair(post_fence_.borrow(),
-                          WrapBuffer(meta_.get(), meta_size_bytes_));
+    return {std::make_pair(post_fence_.borrow(),
+                           WrapBuffer(meta_.get(), meta_size_bytes_))};
 }
 
-int ProducerChannel::OnConsumerRelease(Message&, LocalFence release_fence) {
+Status<void> ProducerChannel::OnConsumerRelease(Message&,
+                                                LocalFence release_fence) {
   ATRACE_NAME("ProducerChannel::OnConsumerRelease");
   ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
            buffer_id());
   if (producer_owns_) {
     ALOGE("ProducerChannel::OnConsumerRelease: Not in acquired state!");
-    return -EBUSY;
+    return ErrorStatus(EBUSY);
   }
 
   // Attempt to merge the fences if necessary.
@@ -282,7 +284,7 @@
       if (!merged_fence) {
         ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
               strerror(error));
-        return -error;
+        return ErrorStatus(error);
       }
       returned_fence_ = std::move(merged_fence);
     } else {
@@ -291,7 +293,7 @@
   }
 
   OnConsumerIgnored();
-  return 0;
+  return {};
 }
 
 void ProducerChannel::OnConsumerIgnored() {
@@ -302,9 +304,10 @@
            buffer_id(), pending_consumers_);
 }
 
-int ProducerChannel::OnProducerMakePersistent(Message& message,
-                                              const std::string& name,
-                                              int user_id, int group_id) {
+Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
+                                                       const std::string& name,
+                                                       int user_id,
+                                                       int group_id) {
   ATRACE_NAME("ProducerChannel::OnProducerMakePersistent");
   ALOGD_IF(TRACE,
            "ProducerChannel::OnProducerMakePersistent: buffer_id=%d name=%s "
@@ -313,7 +316,7 @@
 
   if (name.empty() || (user_id < 0 && user_id != kNoCheckId) ||
       (group_id < 0 && group_id != kNoCheckId)) {
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
   }
 
   // Try to add this buffer with the requested name.
@@ -331,18 +334,18 @@
     owner_user_id_ = user_id;
     owner_group_id_ = group_id;
     name_ = name;
-    return 0;
+    return {};
   } else {
     // Otherwise a buffer with that name already exists.
-    return -EALREADY;
+    return ErrorStatus(EALREADY);
   }
 }
 
-int ProducerChannel::OnRemovePersistence(Message&) {
+Status<void> ProducerChannel::OnRemovePersistence(Message&) {
   if (service()->RemoveNamedBuffer(*this))
-    return 0;
+    return {};
   else
-    return -ENOENT;
+    return ErrorStatus(ENOENT);
 }
 
 void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -365,12 +368,16 @@
 }
 
 // Returns true if the given parameters match the underlying buffer parameters.
-bool ProducerChannel::CheckParameters(int width, int height, int format,
-                                      int usage, size_t meta_size_bytes,
+bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
+                                      uint32_t format, uint64_t producer_usage,
+                                      uint64_t consumer_usage,
+                                      size_t meta_size_bytes,
                                       size_t slice_count) {
   return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
          slices_[0].width() == width && slices_[0].height() == height &&
-         slices_[0].format() == format && slices_[0].usage() == usage;
+         slices_[0].format() == format &&
+         slices_[0].producer_usage() == producer_usage &&
+         slices_[0].consumer_usage() == consumer_usage;
 }
 
 }  // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index e7ca459..f04c8a5 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,10 +30,10 @@
   template <typename T>
   using BufferWrapper = pdx::rpc::BufferWrapper<T>;
 
-  static std::shared_ptr<ProducerChannel> Create(
-      BufferHubService* service, int channel_id, int width, int height,
-      int format, int usage, size_t meta_size_bytes, size_t slice_count,
-      int* error);
+  static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
+      BufferHubService* service, int channel_id, uint32_t width,
+      uint32_t height, uint32_t format, uint64_t producer_usage,
+      uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count);
 
   ~ProducerChannel() override;
 
@@ -42,17 +42,18 @@
 
   BufferInfo GetBufferInfo() const override;
 
-  NativeBufferHandle<BorrowedHandle> OnGetBuffer(Message& message,
-                                                 unsigned index);
-  std::vector<NativeBufferHandle<BorrowedHandle>> OnGetBuffers(
+  pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
+                                                              unsigned index);
+  pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
       Message& message);
 
-  RemoteChannelHandle CreateConsumer(Message& message);
-  RemoteChannelHandle OnNewConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
+  pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
 
-  std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>> OnConsumerAcquire(
-      Message& message, std::size_t metadata_size);
-  int OnConsumerRelease(Message& message, LocalFence release_fence);
+  pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
+  OnConsumerAcquire(Message& message, std::size_t metadata_size);
+  pdx::Status<void> OnConsumerRelease(Message& message,
+                                      LocalFence release_fence);
 
   void OnConsumerIgnored();
 
@@ -60,12 +61,14 @@
   void RemoveConsumer(ConsumerChannel* channel);
 
   bool CheckAccess(int euid, int egid);
-  bool CheckParameters(int width, int height, int format, int usage,
+  bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
+                       uint64_t producer_usage, uint64_t consumer_usage,
                        size_t meta_size_bytes, size_t slice_count);
 
-  int OnProducerMakePersistent(Message& message, const std::string& name,
-                               int user_id, int group_id);
-  int OnRemovePersistence(Message& message);
+  pdx::Status<void> OnProducerMakePersistent(Message& message,
+                                             const std::string& name,
+                                             int user_id, int group_id);
+  pdx::Status<void> OnRemovePersistence(Message& message);
 
  private:
   std::vector<ConsumerChannel*> consumer_channels_;
@@ -91,13 +94,15 @@
 
   std::string name_;
 
-  ProducerChannel(BufferHubService* service, int channel, int width, int height,
-                  int format, int usage, size_t meta_size_bytes,
+  ProducerChannel(BufferHubService* service, int channel, uint32_t width,
+                  uint32_t height, uint32_t format, uint64_t producer_usage,
+                  uint64_t consumer_usage, size_t meta_size_bytes,
                   size_t slice_count, int* error);
 
-  int OnProducerPost(Message& message, LocalFence acquire_fence,
-                     BufferWrapper<std::vector<std::uint8_t>> metadata);
-  LocalFence OnProducerGain(Message& message);
+  pdx::Status<void> OnProducerPost(
+      Message& message, LocalFence acquire_fence,
+      BufferWrapper<std::vector<std::uint8_t>> metadata);
+  pdx::Status<LocalFence> OnProducerGain(Message& message);
 
   ProducerChannel(const ProducerChannel&) = delete;
   void operator=(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7741058..dc2a47e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -1,5 +1,7 @@
 #include "producer_queue_channel.h"
 
+#include <inttypes.h>
+
 #include "consumer_queue_channel.h"
 #include "producer_channel.h"
 
@@ -12,16 +14,14 @@
 namespace android {
 namespace dvr {
 
-ProducerQueueChannel::ProducerQueueChannel(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error)
+ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
+                                           int channel_id,
+                                           size_t meta_size_bytes,
+                                           const UsagePolicy& usage_policy,
+                                           int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
       meta_size_bytes_(meta_size_bytes),
-      usage_set_mask_(usage_set_mask),
-      usage_clear_mask_(usage_clear_mask),
-      usage_deny_set_mask_(usage_deny_set_mask),
-      usage_deny_clear_mask_(usage_deny_clear_mask),
+      usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
 }
@@ -29,28 +29,34 @@
 ProducerQueueChannel::~ProducerQueueChannel() {}
 
 /* static */
-std::shared_ptr<ProducerQueueChannel> ProducerQueueChannel::Create(
+Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
     BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-    int usage_deny_clear_mask, int* error) {
+    const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
-  if (usage_deny_set_mask & usage_deny_clear_mask) {
+  if ((usage_policy.producer_deny_set_mask &
+       usage_policy.producer_deny_clear_mask) ||
+      (usage_policy.consumer_deny_set_mask &
+       usage_policy.consumer_deny_clear_mask)) {
     ALOGE(
         "BufferHubService::OnCreateProducerQueue: illegal usage mask "
-        "configuration: usage_deny_set_mask=%d, usage_deny_clear_mask=%d",
-        usage_deny_set_mask, usage_deny_clear_mask);
-    *error = -EINVAL;
-    return nullptr;
+        "configuration: producer_deny_set_mask=%" PRIx64
+        " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
+        " consumer_deny_clear_mask=%" PRIx64,
+        usage_policy.producer_deny_set_mask,
+        usage_policy.producer_deny_clear_mask,
+        usage_policy.consumer_deny_set_mask,
+        usage_policy.consumer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
   }
 
+  int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
-      usage_deny_set_mask, usage_deny_clear_mask, error));
-  if (*error < 0)
-    return nullptr;
+      service, channel_id, meta_size_bytes, usage_policy, &error));
+  if (error < 0)
+    return ErrorStatus(-error);
   else
-    return producer;
+    return {std::move(producer)};
 }
 
 bool ProducerQueueChannel::HandleMessage(Message& message) {
@@ -88,8 +94,7 @@
 
 BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
   return BufferInfo(channel_id(), consumer_channels_.size(), capacity_,
-                    usage_set_mask_, usage_clear_mask_, usage_deny_set_mask_,
-                    usage_deny_clear_mask_);
+                    usage_policy_);
 }
 
 Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
@@ -127,11 +132,10 @@
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
-ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
-                                                     int width, int height,
-                                                     int format, int usage,
-                                                     size_t slice_count,
-                                                     size_t buffer_count) {
+ProducerQueueChannel::OnProducerQueueAllocateBuffers(
+    Message& message, uint32_t width, uint32_t height, uint32_t format,
+    uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count,
+    size_t buffer_count) {
   ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
   ALOGD_IF(TRACE,
            "ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -141,31 +145,58 @@
   std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
 
   // Deny buffer allocation violating preset rules.
-  if (usage & usage_deny_set_mask_) {
+  if (producer_usage & usage_policy_.producer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_set_mask, the following bits "
-        "shall not be set: %d.",
-        usage, usage_deny_set_mask_);
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating producer_deny_set_mask, the following "
+        "bits shall not be set: %" PRIx64 ".",
+        producer_usage, usage_policy_.producer_deny_set_mask);
     return ErrorStatus(EINVAL);
   }
 
-  if (~usage & usage_deny_clear_mask_) {
+  if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
     ALOGE(
-        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
-        "not permitted. Violating usage_deny_clear_mask, the following bits "
-        "must be set: %d.",
-        usage, usage_deny_clear_mask_);
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating consumer_deny_set_mask, the following "
+        "bits shall not be set: %" PRIx64 ".",
+        consumer_usage, usage_policy_.consumer_deny_set_mask);
     return ErrorStatus(EINVAL);
   }
 
-  // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
-  // and will overwrite |usage_clear_mask_|.
-  int effective_usage = (usage & ~usage_clear_mask_) | usage_set_mask_;
+  if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
+    ALOGE(
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating producer_deny_clear_mask, the following "
+        "bits must be set: %" PRIx64 ".",
+        producer_usage, usage_policy_.producer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
+  }
+
+  if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
+    ALOGE(
+        "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+        "%" PRIx64
+        " is not permitted. Violating consumer_deny_clear_mask, the following "
+        "bits must be set: %" PRIx64 ".",
+        consumer_usage, usage_policy_.consumer_deny_clear_mask);
+    return ErrorStatus(EINVAL);
+  }
+  // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
+  // precedence and will overwrite |usage_policy_.X_clear_mask|.
+  uint64_t effective_producer_usage =
+      (producer_usage & ~usage_policy_.producer_clear_mask) |
+      usage_policy_.producer_set_mask;
+  uint64_t effective_consumer_usage =
+      (consumer_usage & ~usage_policy_.consumer_clear_mask) |
+      usage_policy_.consumer_set_mask;
 
   for (size_t i = 0; i < buffer_count; i++) {
-    auto status = AllocateBuffer(message, width, height, format,
-                                 effective_usage, slice_count);
+    auto status =
+        AllocateBuffer(message, width, height, format, effective_producer_usage,
+                       effective_consumer_usage, slice_count);
     if (!status) {
       ALOGE(
           "ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -179,8 +210,10 @@
 }
 
 Status<std::pair<RemoteChannelHandle, size_t>>
-ProducerQueueChannel::AllocateBuffer(Message& message, int width, int height,
-                                     int format, int usage,
+ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint64_t producer_usage,
+                                     uint64_t consumer_usage,
                                      size_t slice_count) {
   ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
   ALOGD_IF(TRACE,
@@ -205,21 +238,24 @@
   }
 
   ALOGD_IF(TRACE,
-           "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%d "
-           "height=%d format=%d usage=%d slice_count=%zu",
-           buffer_id, width, height, format, usage, slice_count);
+           "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
+           "height=%u format=%u producer_usage=%" PRIx64
+           " consumer_usage=%" PRIx64 " slice_count=%zu",
+           buffer_id, width, height, format, producer_usage, consumer_usage,
+           slice_count);
   auto buffer_handle = status.take();
 
-  int error;
-  const auto producer_channel =
-      ProducerChannel::Create(service(), buffer_id, width, height, format,
-                              usage, meta_size_bytes_, slice_count, &error);
-  if (!producer_channel) {
+  auto producer_channel_status = ProducerChannel::Create(
+      service(), buffer_id, width, height, format, producer_usage,
+      consumer_usage, meta_size_bytes_, slice_count);
+  if (!producer_channel_status) {
     ALOGE(
-        "ProducerQueueChannel::AllocateBuffer: Failed to create "
-        "BufferHubBuffer producer!!");
+        "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
+        "buffer: %s",
+        producer_channel_status.GetErrorMessage().c_str());
     return ErrorStatus(ENOMEM);
   }
+  auto producer_channel = producer_channel_status.take();
 
   ALOGD_IF(
       TRACE,
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index a12a37d..09b0243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -11,10 +11,9 @@
 
 class ProducerQueueChannel : public BufferHubChannel {
  public:
-  static std::shared_ptr<ProducerQueueChannel> Create(
+  static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
       BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
-      int usage_deny_clear_mask, int* error);
+      const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
   bool HandleMessage(pdx::Message& message) override;
@@ -34,8 +33,10 @@
   // Allocate a new BufferHubProducer according to the input spec. Client may
   // handle this as if a new producer is created through kOpCreateBuffer.
   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,
+  OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
+                                 uint32_t height, uint32_t format,
+                                 uint64_t producer_usage,
+                                 uint64_t consumer_usage, size_t slice_count,
                                  size_t buffer_count);
 
   // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
@@ -48,18 +49,17 @@
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, int usage_set_mask,
-                       int usage_clear_mask, int usage_deny_set_mask,
-                       int usage_deny_clear_mask, int* error);
+                       size_t meta_size_bytes, const UsagePolicy& usage_policy,
+                       int* error);
 
   // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
   // Note that the newly created buffer's file handle will be pushed to client
   // and our return type is a RemoteChannelHandle.
-  // Returns the remote channdel handle and the slot number for the newly
+  // Returns the remote channel handle and the slot number for the newly
   // allocated buffer.
   pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
-      pdx::Message& message, int width, int height, int format, int usage,
-      size_t slice_count);
+      pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
+      uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
 
   // Size of the meta data associated with all the buffers allocated from the
   // queue. Now we assume the metadata size is immutable once the queue is
@@ -68,10 +68,7 @@
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
-  int usage_set_mask_;
-  int usage_clear_mask_;
-  int usage_deny_set_mask_;
-  int usage_deny_clear_mask_;
+  UsagePolicy usage_policy_;
 
   // Provides access to the |channel_id| of all consumer channels associated
   // with this producer.
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
index 999d71e..15f63fa 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -7,41 +7,6 @@
 
 namespace android {
 namespace dvr {
-namespace {
-
-sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
-
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  // Need to register |handle| otherwise we can't read its properties.
-  if (mapper.registerBuffer(handle) != OK) {
-    ALOGE("Failed to register buffer");
-    return nullptr;
-  }
-
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-
-  return buffer;
-}
-
-}  // namespace
 
 ParcelableComposerLayer::ParcelableComposerLayer() {}
 
@@ -54,7 +19,7 @@
   status_t ret = parcel->writeUint64(layer_.id);
   if (ret != OK) return ret;
 
-  ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+  ret = parcel->write(*layer_.buffer);
   if (ret != OK) return ret;
 
   ret = parcel->writeBool(layer_.fence->isValid());
@@ -108,11 +73,12 @@
   status_t ret = parcel->readUint64(&layer_.id);
   if (ret != OK) return ret;
 
-  native_handle* handle = parcel->readNativeHandle();
-  if (!handle) return BAD_VALUE;
-
-  layer_.buffer = GetBufferFromHandle(handle);
-  if (!layer_.buffer.get()) return BAD_VALUE;
+  layer_.buffer = new GraphicBuffer();
+  ret = parcel->read(*layer_.buffer);
+  if (ret != OK) {
+    layer_.buffer.clear();
+    return ret;
+  }
 
   bool has_fence = 0;
   ret = parcel->readBool(&has_fence);
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index 007251f..f01bb28 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -35,6 +35,7 @@
   ],
 
   export_shared_lib_headers: [
+    "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
   ],
 
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
index acf0dac..e0bdf1c 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
@@ -50,6 +50,10 @@
   switch (vrCommand) {
     case IVrComposerClient::VrCommand::SET_LAYER_INFO:
       return parseSetLayerInfo(length);
+    case IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA:
+      return parseSetClientTargetMetadata(length);
+    case IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA:
+      return parseSetLayerBufferMetadata(length);
     default:
       return CommandReader::parseCommand(command, length);
   }
@@ -68,5 +72,43 @@
   return true;
 }
 
+bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setClientTargetMetadata(mDisplay, readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+    uint16_t length) {
+  if (length != 7)
+    return false;
+
+  auto err = mVrHal.setLayerBufferMetadata(mDisplay, mLayer,
+                                           readBufferMetadata());
+  if (err != Error::NONE)
+    mWriter.setError(getCommandLoc(), err);
+
+  return true;
+}
+
+IVrComposerClient::BufferMetadata
+VrComposerClient::VrCommandReader::readBufferMetadata() {
+  IVrComposerClient::BufferMetadata metadata = {
+    .width = read(),
+    .height = read(),
+    .stride = read(),
+    .layerCount = read(),
+    .format = static_cast<PixelFormat>(readSigned()),
+    .usage = read64(),
+  };
+  return metadata;
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
index 8f0c562..8d601ab 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
@@ -17,6 +17,7 @@
 #ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
 #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
 
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <ComposerClient.h>
 #include <IComposerCommandBuffer.h>
 
@@ -44,6 +45,10 @@
 
    private:
     bool parseSetLayerInfo(uint16_t length);
+    bool parseSetClientTargetMetadata(uint16_t length);
+    bool parseSetLayerBufferMetadata(uint16_t length);
+
+    IVrComposerClient::BufferMetadata readBufferMetadata();
 
     VrComposerClient& mVrClient;
     android::dvr::VrHwc& mVrHal;
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index 9ba01f9..5efc482 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -16,8 +16,6 @@
 #include "vr_hwc.h"
 
 #include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
 
 #include <mutex>
 
@@ -43,35 +41,19 @@
 const Display kDefaultDisplayId = 1;
 const Config kDefaultConfigId = 1;
 
-sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
-  uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
-  uint64_t producer_usage = 0, consumer_usage = 0;
-  int32_t format = 0;
+sp<GraphicBuffer> CreateGraphicBuffer(
+    const native_handle_t* handle,
+    const IVrComposerClient::BufferMetadata& metadata) {
+   sp<GraphicBuffer> buffer = new GraphicBuffer(
+      handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
+      static_cast<int32_t>(metadata.format), metadata.layerCount,
+      metadata.usage, metadata.usage, metadata.stride);
+   if (buffer->initCheck() != OK) {
+     ALOGE("Failed to create graphic buffer");
+     return nullptr;
+   }
 
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
-  if (mapper.getDimensions(handle, &width, &height) ||
-      mapper.getStride(handle, &stride) ||
-      mapper.getFormat(handle, &format) ||
-      mapper.getProducerUsage(handle, &producer_usage) ||
-      mapper.getConsumerUsage(handle, &consumer_usage)) {
-    ALOGE("Failed to read handle properties");
-    return nullptr;
-  }
-
-  // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
-  // capability. Otherwise assume a count of 1.
-  mapper.getLayerCount(handle, &layer_count);
-
-  // NOTE: Can't re-use |handle| since we don't own it.
-  sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
-      GraphicBuffer::CLONE_HANDLE, width, height, format, layer_count,
-      producer_usage, consumer_usage, stride);
-  if (buffer->initCheck() != OK) {
-    ALOGE("Failed to register cloned buffer");
-    return nullptr;
-  }
-
-  return buffer;
+   return buffer;
 }
 
 void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -109,12 +91,17 @@
 bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
                                  base::unique_fd fence) {
   if (handle)
-    buffer_ = GetBufferFromHandle(handle);
+    buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);
 
   fence_ = new Fence(fence.release());
   return true;
 }
 
+void HwcDisplay::SetClientTargetMetadata(
+    const IVrComposerClient::BufferMetadata& metadata) {
+  buffer_metadata_ = metadata;
+}
+
 HwcLayer* HwcDisplay::CreateLayer() {
   uint64_t layer_id = layer_ids_++;
   layers_.push_back(HwcLayer(layer_id));
@@ -553,7 +540,8 @@
   if (!hwc_layer)
     return Error::BAD_LAYER;
 
-  hwc_layer->info.buffer = GetBufferFromHandle(buffer);
+  hwc_layer->info.buffer = CreateGraphicBuffer(
+      buffer, hwc_layer->buffer_metadata);
   hwc_layer->info.fence = new Fence(fence.release());
 
   return Error::NONE;
@@ -719,6 +707,35 @@
   return Error::NONE;
 }
 
+Error VrHwc::setClientTargetMetadata(
+    Display display, const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  display_ptr->SetClientTargetMetadata(metadata);
+
+  return Error::NONE;
+}
+
+Error VrHwc::setLayerBufferMetadata(
+    Display display, Layer layer,
+    const IVrComposerClient::BufferMetadata& metadata) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  auto display_ptr = FindDisplay(display);
+  if (!display_ptr)
+    return Error::BAD_DISPLAY;
+
+  HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+  if (!hwc_layer)
+    return Error::BAD_LAYER;
+
+  hwc_layer->buffer_metadata = metadata;
+
+  return Error::NONE;
+}
+
 Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
   hidl_cb(hidl_vec<Capability>());
   return Void();
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.h b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
index bfca9a6..3da2fb8 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
@@ -17,6 +17,7 @@
 #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
 
 #include <android-base/unique_fd.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <ComposerBase.h>
 #include <ui/Fence.h>
@@ -26,6 +27,7 @@
 #include <mutex>
 #include <unordered_map>
 
+using namespace android::frameworks::vr::composer::V1_0;
 using namespace android::hardware::graphics::common::V1_0;
 using namespace android::hardware::graphics::composer::V2_1;
 
@@ -38,7 +40,6 @@
 namespace android {
 
 class Fence;
-class GraphicBuffer;
 
 namespace dvr {
 
@@ -105,6 +106,7 @@
   Composition composition_type;
   uint32_t z_order;
   ComposerView::ComposerLayer info;
+  IVrComposerClient::BufferMetadata buffer_metadata;
 };
 
 class HwcDisplay {
@@ -120,6 +122,8 @@
   HwcLayer* GetLayer(Layer id);
 
   bool SetClientTarget(const native_handle_t* handle, base::unique_fd fence);
+  void SetClientTargetMetadata(
+      const IVrComposerClient::BufferMetadata& metadata);
 
   void GetChangedCompositionTypes(
       std::vector<Layer>* layer_ids,
@@ -131,8 +135,8 @@
 
  private:
   // The client target buffer and the associated fence.
-  // TODO(dnicoara): Replace this with a list of ComposerView::ComposerLayer.
   sp<GraphicBuffer> buffer_;
+  IVrComposerClient::BufferMetadata buffer_metadata_;
   sp<Fence> fence_;
 
   // List of currently active layers.
@@ -159,6 +163,11 @@
 
   Error setLayerInfo(Display display, Layer layer, uint32_t type,
                      uint32_t appId);
+  Error setClientTargetMetadata(
+      Display display, const IVrComposerClient::BufferMetadata& metadata);
+  Error setLayerBufferMetadata(
+      Display display, Layer layer,
+      const IVrComposerClient::BufferMetadata& metadata);
 
   // ComposerBase
   void removeClient() override;
diff --git a/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);