Merge "Surface: Do not copy back if front and back buffer are identical"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 8d9442b..457d203 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <zlib.h>
 
+#include <fstream>
 #include <memory>
 
 #include <binder/IBinder.h>
@@ -172,6 +173,7 @@
         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
+        { REQ,      "events/lowmemorykiller/enable" },
     } },
     { "regulators",  "Voltage and Current Regulators", 0, {
         { REQ,      "events/regulator/enable" },
@@ -434,56 +436,31 @@
     return writeStr(k_traceBufferSizePath, str);
 }
 
-// Read the trace_clock sysfs file and return true if it matches the requested
-// value.  The trace_clock file format is:
-// local [global] counter uptime perf
-static bool isTraceClock(const char *mode)
-{
-    int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-
-    char buf[4097];
-    ssize_t n = read(fd, buf, 4096);
-    close(fd);
-    if (n == -1) {
-        fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
-            strerror(errno), errno);
-        return false;
-    }
-    buf[n] = '\0';
-
-    char *start = strchr(buf, '[');
-    if (start == NULL) {
-        return false;
-    }
-    start++;
-
-    char *end = strchr(start, ']');
-    if (end == NULL) {
-        return false;
-    }
-    *end = '\0';
-
-    return strcmp(mode, start) == 0;
-}
-
-// Enable or disable the kernel's use of the global clock.  Disabling the global
-// clock will result in the kernel using a per-CPU local clock.
+// Set the clock to the best available option while tracing. Use 'boot' if it's
+// available; otherwise, use 'mono'. If neither are available use 'global'.
 // Any write to the trace_clock sysfs file will reset the buffer, so only
 // update it if the requested value is not the current value.
-static bool setGlobalClockEnable(bool enable)
+static bool setClock()
 {
-    const char *clock = enable ? "global" : "local";
+    std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
+    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
+        std::istreambuf_iterator<char>());
 
-    if (isTraceClock(clock)) {
-        return true;
+    std::string newClock;
+    if (clockStr.find("boot") != std::string::npos) {
+        newClock = "boot";
+    } else if (clockStr.find("mono") != std::string::npos) {
+        newClock = "mono";
+    } else {
+        newClock = "global";
     }
 
-    return writeStr(k_traceClockPath, clock);
+    size_t begin = clockStr.find("[") + 1;
+    size_t end = clockStr.find("]");
+    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
+        return true;
+    }
+    return writeStr(k_traceClockPath, newClock.c_str());
 }
 
 static bool setPrintTgidEnableIfPresent(bool enable)
@@ -776,7 +753,7 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    ok &= setGlobalClockEnable(true);
+    ok &= setClock();
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
 
@@ -848,7 +825,6 @@
     // Set the options back to their defaults.
     setTraceOverwriteEnable(true);
     setTraceBufferSizeKB(1);
-    setGlobalClockEnable(false);
     setPrintTgidEnableIfPresent(false);
     setKernelTraceFuncs(NULL);
 }
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cef41be..8201d7e 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -51,6 +51,8 @@
     chown root shell /sys/kernel/tracing/events/binder/binder_locked/enable
     chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
     chown root shell /sys/kernel/tracing/events/binder/binder_unlock/enable
+    chown root shell /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chown root shell /sys/kernel/tracing/events/lowmemorykiller/enable
 
     chown root shell /sys/kernel/debug/tracing/tracing_on
     chown root shell /sys/kernel/tracing/tracing_on
@@ -119,11 +121,18 @@
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_result/enable
     chmod 0664 /sys/kernel/debug/tracing/events/i2c/smbus_reply/enable
     chmod 0664 /sys/kernel/tracing/events/i2c/smbus_reply/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
+    chmod 0664 /sys/kernel/tracing/events/lowmemorykiller/enable
 
     # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
 
+    # Set the trace clock to boot; falling back to mono or boot
+    write /d/tracing/trace_clock global
+    write /d/tracing/trace_clock mono
+    write /d/tracing/trace_clock boot
+
 # Allow only the shell group to read and truncate the kernel trace.
     chown root shell /sys/kernel/debug/tracing/trace
     chown root shell /sys/kernel/tracing/trace
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 5a78d78..7419eb4 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1763,10 +1763,20 @@
             result = false;
             continue;
         }
+
+        // Delete oat/vdex/art files.
         result = unlink_if_exists(oat_path) && result;
         result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
         result = unlink_if_exists(create_image_filename(oat_path)) && result;
 
+        // Delete profiles.
+        std::string current_profile = create_current_profile_path(
+                multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
+        std::string reference_profile = create_reference_profile_path(
+                dex_path, /*is_secondary*/true);
+        result = unlink_if_exists(current_profile) && result;
+        result = unlink_if_exists(reference_profile) && result;
+
         // Try removing the directories as well, they might be empty.
         result = rmdir_if_empty(oat_isa_dir) && result;
         result = rmdir_if_empty(oat_dir) && result;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6fefb38..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2547,16 +2547,8 @@
             objectsSize = 0;
         } else {
             while (objectsSize > 0) {
-                if (mObjects[objectsSize-1] < desired) {
-                    // Check for an object being sliced
-                    if (desired < mObjects[objectsSize-1] + sizeof(flat_binder_object)) {
-                        ALOGE("Attempt to shrink Parcel would slice an objects allocated memory");
-                        return UNKNOWN_ERROR + 0xBADF10;
-                    }
+                if (mObjects[objectsSize-1] < desired)
                     break;
-                }
-                // STOPSHIP: Above code to be replaced with following commented code:
-                // if (mObjects[objectsSize-1] + sizeof(flat_binder_object) <= desired) break;
                 objectsSize--;
             }
         }
diff --git a/libs/math/tests/mat_test.cpp b/libs/math/tests/mat_test.cpp
index c365366..3217a1a 100644
--- a/libs/math/tests/mat_test.cpp
+++ b/libs/math/tests/mat_test.cpp
@@ -487,7 +487,7 @@
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_FLOAT_EQ(v1[i], v2[i]);                      \
         }                                                       \
-    } else if (std::is_same<TypeParam,float>::value) {          \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         for (size_t i = 0; i < v1.size(); ++i) {                \
             EXPECT_DOUBLE_EQ(v1[i], v2[i]);                     \
         }                                                       \
@@ -506,7 +506,7 @@
     const decltype(T2) t2 = T2;                                 \
     if (std::is_same<TypeParam,float>::value) {                 \
         ASSERT_FLOAT_EQ(t1, t2);                                \
-    } else if (std::is_same<TypeParam,float>::value) {         \
+    } else if (std::is_same<TypeParam,double>::value) {         \
         ASSERT_DOUBLE_EQ(t1, t2);                               \
     } else {                                                    \
         ASSERT_EQ(t1, t2);                                      \
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
index 236e3aa..f2e5034 100644
--- a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -174,8 +174,6 @@
   //
   // There must be at least |MemorySize(record_count)| bytes of space already
   // allocated at |mmap|. The ring does not take ownership.
-  //
-  // Use this function for dynamically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size,
                               uint32_t record_count) {
     BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@
   //
   // There must be at least |MemorySize()| bytes of space already allocated at
   // |mmap|. The ring does not take ownership.
-  //
-  // Use this function for statically sized rings.
   static BroadcastRing Create(void* mmap, size_t mmap_size) {
-    static_assert(Traits::kUseStaticRecordCount,
-                  "Wrong Create() function called for dynamic record count");
-    return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+    return Create(mmap, mmap_size,
+                  Traits::kUseStaticRecordCount
+                      ? Traits::kStaticRecordCount
+                      : BroadcastRing::GetRecordCount(mmap_size));
   }
 
   // Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@
     return MemorySize(Traits::kStaticRecordCount);
   }
 
+  static uint32_t NextPowerOf2(uint32_t n) {
+    if (n == 0)
+      return 0;
+    n -= 1;
+    n |= n >> 16;
+    n |= n >> 8;
+    n |= n >> 4;
+    n |= n >> 2;
+    n |= n >> 1;
+    return n + 1;
+  }
+
+  // Gets the biggest power of 2 record count that can fit into this mmap.
+  //
+  // The header size has been taken into account.
+  static uint32_t GetRecordCount(size_t mmap_size) {
+    if (mmap_size <= sizeof(Header)) {
+      return 0;
+    }
+    uint32_t count =
+        static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record));
+    return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2);
+  }
+
   // Writes a record to the ring.
   //
   // The oldest record is overwritten unless the ring is not already full.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index ffdc9e2..d79d96d 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -129,19 +129,102 @@
 using LocalFence = FenceHandle<pdx::LocalHandle>;
 using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
 
-struct QueueInfo {
+struct ProducerQueueConfig {
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async;
+
+  // Default buffer width that is set during ProducerQueue's creation.
+  uint32_t default_width;
+
+  // Default buffer height that is set during ProducerQueue's creation.
+  uint32_t default_height;
+
+  // Default buffer format that is set during ProducerQueue's creation.
+  uint32_t default_format;
+
+  // Size of the meta data associated with all the buffers allocated from the
+  // queue.
   size_t meta_size_bytes;
+
+ private:
+  PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
+                           default_height, default_format, meta_size_bytes);
+};
+
+class ProducerQueueConfigBuilder {
+ public:
+  // Build a ProducerQueueConfig object.
+  ProducerQueueConfig Build() {
+    return {is_async_, default_width_, default_height_, default_format_,
+            meta_size_bytes_};
+  }
+
+  ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
+    is_async_ = is_async;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
+    default_width_ = width;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
+    default_height_ = height;
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
+    default_format_ = format;
+    return *this;
+  }
+
+  template <typename Meta>
+  ProducerQueueConfigBuilder& SetMetadata() {
+    meta_size_bytes_ = sizeof(Meta);
+    return *this;
+  }
+
+  ProducerQueueConfigBuilder& SetMetadataSize(size_t meta_size_bytes) {
+    meta_size_bytes_ = meta_size_bytes;
+    return *this;
+  }
+
+ private:
+  bool is_async_{false};
+  uint32_t default_width_{1};
+  uint32_t default_height_{1};
+  uint32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
+  size_t meta_size_bytes_{0};
+};
+
+// Explicit specializations of ProducerQueueConfigBuilder::Build for void
+// metadata type.
+template <>
+inline ProducerQueueConfigBuilder&
+ProducerQueueConfigBuilder::SetMetadata<void>() {
+  meta_size_bytes_ = 0;
+  return *this;
+}
+
+struct QueueInfo {
+  ProducerQueueConfig producer_config;
   int id;
 
  private:
-  PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
+  PDX_SERIALIZABLE_MEMBERS(QueueInfo, producer_config, id);
 };
 
 struct UsagePolicy {
-  uint64_t usage_set_mask;
-  uint64_t usage_clear_mask;
-  uint64_t usage_deny_set_mask;
-  uint64_t usage_deny_clear_mask;
+  uint64_t usage_set_mask{0};
+  uint64_t usage_clear_mask{0};
+  uint64_t usage_deny_set_mask{0};
+  uint64_t usage_deny_clear_mask{0};
 
  private:
   PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
@@ -219,7 +302,7 @@
 
   // Buffer Queue Methods.
   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
-                    QueueInfo(size_t meta_size_bytes,
+                    QueueInfo(const ProducerQueueConfig& producer_config,
                               const UsagePolicy& usage_policy));
   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
                     LocalChannelHandle(Void));
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 1978f41..e59bbb5 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -10,7 +10,6 @@
 #include <pdx/default_transport/client_channel.h>
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
 
 #define RETRY_EINTR(fnc_call)                 \
   ([&]() -> decltype(fnc_call) {              \
@@ -106,14 +105,18 @@
           status.GetErrorMessage().c_str());
     return ErrorStatus(status.error());
   } else {
-    SetupQueue(status.get().meta_size_bytes, status.get().id);
+    SetupQueue(status.get());
     return {};
   }
 }
 
-void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
-  meta_size_ = meta_size_bytes;
-  id_ = id;
+void BufferHubQueue::SetupQueue(const QueueInfo& queue_info) {
+  is_async_ = queue_info.producer_config.is_async;
+  default_width_ = queue_info.producer_config.default_width;
+  default_height_ = queue_info.producer_config.default_height;
+  default_format_ = queue_info.producer_config.default_format;
+  meta_size_ = queue_info.producer_config.meta_size_bytes;
+  id_ = queue_info.id;
 }
 
 std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
@@ -396,9 +399,6 @@
   return {std::move(buffer)};
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size)
-    : ProducerQueue(meta_size, 0, 0, 0, 0) {}
-
 ProducerQueue::ProducerQueue(LocalChannelHandle handle)
     : BASE(std::move(handle)) {
   auto status = ImportQueue();
@@ -409,14 +409,11 @@
   }
 }
 
-ProducerQueue::ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                             uint64_t usage_clear_mask,
-                             uint64_t usage_deny_set_mask,
-                             uint64_t usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(const ProducerQueueConfig& config,
+                             const UsagePolicy& usage)
     : BASE(BufferHubRPC::kClientPath) {
-  auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
-      meta_size, UsagePolicy{usage_set_mask, usage_clear_mask,
-                             usage_deny_set_mask, usage_deny_clear_mask});
+  auto status =
+      InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(config, usage);
   if (!status) {
     ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
           status.GetErrorMessage().c_str());
@@ -424,7 +421,7 @@
     return;
   }
 
-  SetupQueue(status.get().meta_size_bytes, status.get().id);
+  SetupQueue(status.get());
 }
 
 Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 932aa37..4b3dd7a 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -11,7 +11,10 @@
 /* static */
 sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
   sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
-  producer->queue_ = ProducerQueue::Create<DvrNativeBufferMetadata>();
+  auto config = ProducerQueueConfigBuilder()
+                    .SetMetadata<DvrNativeBufferMetadata>()
+                    .Build();
+  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
   return producer;
 }
 
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 d8d326b..e62e832 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
@@ -5,6 +5,7 @@
 
 #include <pdx/client.h>
 #include <pdx/status.h>
+#include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/epoll_file_descriptor.h>
 #include <private/dvr/ring_buffer.h>
@@ -32,14 +33,17 @@
   // participation in lifecycle events.
   std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
 
+  // Returns whether the buffer queue is in async mode.
+  bool is_async() const { return is_async_; }
+
   // Returns the default buffer width of this buffer queue.
-  size_t default_width() const { return default_width_; }
+  uint32_t default_width() const { return default_width_; }
 
   // Returns the default buffer height of this buffer queue.
-  size_t default_height() const { return default_height_; }
+  uint32_t default_height() const { return default_height_; }
 
   // Returns the default buffer format of this buffer queue.
-  int32_t default_format() const { return default_format_; }
+  uint32_t default_format() const { return default_format_; }
 
   // Creates a new consumer in handle form for immediate transport over RPC.
   pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle();
@@ -98,7 +102,7 @@
   pdx::Status<void> ImportQueue();
 
   // Sets up the queue with the given parameters.
-  void SetupQueue(size_t meta_size_bytes_, int id);
+  void SetupQueue(const QueueInfo& queue_info);
 
   // Register a buffer for management by the queue. Used by subclasses to add a
   // buffer to internal bookkeeping.
@@ -181,17 +185,22 @@
     return index == BufferHubQueue::kEpollQueueEventIndex;
   }
 
-  // Default buffer width that can be set to override the buffer width when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Whether the buffer queue is operating in Async mode.
+  // From GVR's perspective of view, this means a buffer can be acquired
+  // asynchronously by the compositor.
+  // From Android Surface's perspective of view, this is equivalent to
+  // IGraphicBufferProducer's async mode. When in async mode, a producer
+  // will never block even if consumer is running slow.
+  bool is_async_{false};
+
+  // Default buffer width that is set during ProducerQueue's creation.
   size_t default_width_{1};
 
-  // Default buffer height that can be set to override the buffer height when a
-  // width and height of 0 are specified in AllocateBuffer.
+  // Default buffer height that is set during ProducerQueue's creation.
   size_t default_height_{1};
 
-  // Default buffer format that can be set to override the buffer format when it
-  // isn't specified in AllocateBuffer.
-  int32_t default_format_{PIXEL_FORMAT_RGBA_8888};
+  // Default buffer format that is set during ProducerQueue's creation.
+  int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
 
   // Tracks the buffers belonging to this queue. Buffers are stored according to
   // "slot" in this vector. Each slot is a logical id of the buffer within this
@@ -222,14 +231,6 @@
 
 class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
  public:
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create() {
-    return BASE::Create(sizeof(Meta));
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes) {
-    return BASE::Create(meta_size_bytes);
-  }
-
   // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
   // in |usage_clear_mask| will be automatically masked off. Note that
   // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
@@ -241,21 +242,9 @@
   // this will be rejected. Note that |usage_deny_set_mask| and
   // |usage_deny_clear_mask| shall not conflict with each other. Such
   // configuration will be treated as invalid input on creation.
-  template <typename Meta>
-  static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
-  }
-  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
-                                               uint32_t usage_set_mask,
-                                               uint32_t usage_clear_mask,
-                                               uint32_t usage_deny_set_mask,
-                                               uint32_t usage_deny_clear_mask) {
-    return BASE::Create(meta_size_bytes, usage_set_mask, usage_clear_mask,
-                        usage_deny_set_mask, usage_deny_clear_mask);
+  static std::unique_ptr<ProducerQueue> Create(
+      const ProducerQueueConfig& config, const UsagePolicy& usage) {
+    return BASE::Create(config, usage);
   }
 
   // Import a ProducerQueue from a channel handle.
@@ -305,29 +294,13 @@
   // Constructors are automatically exposed through ProducerQueue::Create(...)
   // static template methods inherited from ClientBase, which take the same
   // arguments as the constructors.
-  explicit ProducerQueue(size_t meta_size);
   explicit ProducerQueue(pdx::LocalChannelHandle handle);
-  ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
-                uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
-                uint64_t usage_deny_clear_mask);
+  ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
 
   pdx::Status<Entry> OnBufferReady(
       const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
 };
 
-// Explicit specializations of ProducerQueue::Create for void metadata type.
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>() {
-  return ProducerQueue::Create(0);
-}
-template <>
-inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
-    uint32_t usage_set_mask, uint32_t usage_clear_mask,
-    uint32_t usage_deny_set_mask, uint32_t usage_deny_clear_mask) {
-  return ProducerQueue::Create(0, usage_set_mask, usage_clear_mask,
-                               usage_deny_set_mask, usage_deny_clear_mask);
-}
-
 class ConsumerQueue : public BufferHubQueue {
  public:
   // Get a buffer consumer. Note that the method doesn't check whether the
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index ff2e146..064e3fd 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -16,22 +16,17 @@
 
 namespace {
 
-constexpr int kBufferWidth = 100;
-constexpr int kBufferHeight = 1;
-constexpr int kBufferLayerCount = 1;
-constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
-constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+constexpr uint32_t kBufferWidth = 100;
+constexpr uint32_t kBufferHeight = 1;
+constexpr uint32_t kBufferLayerCount = 1;
+constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
 
 class BufferHubQueueTest : public ::testing::Test {
  public:
-  template <typename Meta>
-  bool CreateProducerQueue(uint64_t usage_set_mask = 0,
-                           uint64_t usage_clear_mask = 0,
-                           uint64_t usage_deny_set_mask = 0,
-                           uint64_t usage_deny_clear_mask = 0) {
-    producer_queue_ =
-        ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
-                                    usage_deny_set_mask, usage_deny_clear_mask);
+  bool CreateProducerQueue(const ProducerQueueConfig& config,
+                           const UsagePolicy& usage) {
+    producer_queue_ = ProducerQueue::Create(config, usage);
     return producer_queue_ != nullptr;
   }
 
@@ -44,14 +39,9 @@
     }
   }
 
-  template <typename Meta>
-  bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
-                    int usage_deny_set_mask = 0,
-                    int usage_deny_clear_mask = 0) {
-    return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
-                                     usage_deny_set_mask,
-                                     usage_deny_clear_mask) &&
-           CreateConsumerQueue();
+  bool CreateQueues(const ProducerQueueConfig& config,
+                    const UsagePolicy& usage) {
+    return CreateProducerQueue(config, usage) && CreateConsumerQueue();
   }
 
   void AllocateBuffer(size_t* slot_out = nullptr) {
@@ -67,6 +57,7 @@
   }
 
  protected:
+  ProducerQueueConfigBuilder config_builder_;
   std::unique_ptr<ProducerQueue> producer_queue_;
   std::unique_ptr<ConsumerQueue> consumer_queue_;
 };
@@ -74,7 +65,8 @@
 TEST_F(BufferHubQueueTest, TestDequeue) {
   const size_t nb_dequeue_times = 16;
 
-  ASSERT_TRUE(CreateQueues<size_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
+                           UsagePolicy{}));
 
   // Allocate only one buffer.
   AllocateBuffer();
@@ -104,7 +96,8 @@
   size_t slot;
   uint64_t seq;
 
-  ASSERT_TRUE(CreateQueues<uint64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+                           UsagePolicy{}));
 
   for (size_t i = 0; i < kBufferCount; i++) {
     AllocateBuffer();
@@ -175,7 +168,7 @@
 }
 
 TEST_F(BufferHubQueueTest, TestDetach) {
-  ASSERT_TRUE(CreateProducerQueue<void>());
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate buffers.
   const size_t kBufferCount = 4u;
@@ -278,7 +271,9 @@
 }
 
 TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
-  ASSERT_TRUE(CreateProducerQueue<void>());
+  // ProducerConfigureBuilder doesn't set Metadata{size}, which means there
+  // is no metadata associated with this BufferQueue's buffer.
+  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate buffers.
   const size_t kBufferCount = 4u;
@@ -356,7 +351,9 @@
 };
 
 TEST_F(BufferHubQueueTest, TestMetadata) {
-  ASSERT_TRUE(CreateQueues<TestMetadata>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   std::vector<TestMetadata> ms = {
@@ -382,7 +379,9 @@
 }
 
 TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
+
   AllocateBuffer();
 
   int64_t mi = 3;
@@ -401,7 +400,8 @@
 }
 
 TEST_F(BufferHubQueueTest, TestEnqueue) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
   AllocateBuffer();
 
   size_t slot;
@@ -418,7 +418,8 @@
 }
 
 TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
-  ASSERT_TRUE(CreateQueues<int64_t>());
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{}));
 
   size_t s1;
   AllocateBuffer();
@@ -473,7 +474,8 @@
 
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{set_mask, 0, 0, 0}));
 
   // When allocation, leave out |set_mask| from usage bits on purpose.
   size_t slot;
@@ -491,7 +493,8 @@
 
 TEST_F(BufferHubQueueTest, TestUsageClearMask) {
   const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, clear_mask, 0, 0}));
 
   // When allocation, add |clear_mask| into usage bits on purpose.
   size_t slot;
@@ -509,7 +512,8 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
   const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, deny_set_mask, 0}));
 
   // Now that |deny_set_mask| is illegal, allocation without those bits should
   // be able to succeed.
@@ -529,7 +533,8 @@
 
 TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
   const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
-  ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
+  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
+                           UsagePolicy{0, 0, 0, deny_clear_mask}));
 
   // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
   // mandatory), allocation with those bits should be able to succeed.
@@ -547,6 +552,26 @@
   ASSERT_EQ(EINVAL, status.error());
 }
 
+TEST_F(BufferHubQueueTest, TestQueueInfo) {
+  static const bool kIsAsync = true;
+  ASSERT_TRUE(CreateQueues(config_builder_.SetIsAsync(kIsAsync)
+                               .SetDefaultWidth(kBufferWidth)
+                               .SetDefaultHeight(kBufferHeight)
+                               .SetDefaultFormat(kBufferFormat)
+                               .Build(),
+                           UsagePolicy{}));
+
+  EXPECT_EQ(producer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(producer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(producer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(producer_queue_->is_async(), kIsAsync);
+
+  EXPECT_EQ(consumer_queue_->default_width(), kBufferWidth);
+  EXPECT_EQ(consumer_queue_->default_height(), kBufferHeight);
+  EXPECT_EQ(consumer_queue_->default_format(), kBufferFormat);
+  EXPECT_EQ(consumer_queue_->is_async(), kIsAsync);
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index c0c7e2f..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -17,6 +17,7 @@
     "display_manager_client.cpp",
     "display_protocol.cpp",
     "vsync_client.cpp",
+    "shared_buffer_helpers.cpp",
 ]
 
 localIncludeFiles = [
@@ -39,7 +40,7 @@
     "libdvrcommon",
     "libbufferhubqueue",
     "libbufferhub",
-    "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..249f410
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,138 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+  // This constructor will create a display client and get the buffer from it.
+  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+  // If you already have the IonBuffer, use this. It will take ownership.
+  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+  // Use this if you do not want to take ownership.
+  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+  ~CPUMappedBuffer();
+
+  // Getters.
+  size_t Size() const { return size_; }
+  void* Address() const { return address_; }
+  bool IsMapped() const { return Address() != nullptr; }
+
+  // Attempt mapping this buffer to the CPU addressable space.
+  // This will create a display client and see if the buffer exists.
+  // If the buffer has not been setup yet, you will need to try again later.
+  void TryMapping();
+
+ protected:
+  // The memory area if we managed to map it.
+  size_t size_ = 0;
+  void* address_ = nullptr;
+
+  // If we are polling the display client, the buffer key here.
+  DvrGlobalBufferKey buffer_key_;
+
+  // If we just own the IonBuffer outright, it's here.
+  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+  // If we do not own the IonBuffer, it's here
+  IonBuffer* buffer_ = nullptr;
+
+  // The usage mode.
+  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+      : CPUMappedBuffer(key, mode) {}
+
+  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(std::move(buffer), mode) {}
+
+  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(buffer, mode) {}
+
+  // Helper function for publishing records in the ring.
+  void Publish(const typename RingType::Record& record) {
+    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      ring->Put(record);
+    }
+  }
+
+  // Helper function for getting records from the ring.
+  // Returns true if we were able to retrieve the latest.
+  bool GetNewest(typename RingType::Record* record) {
+    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      return ring->GetNewest(&sequence_, record);
+    }
+
+    return false;
+  }
+
+  // Try obtaining the ring. If the named buffer has not been created yet, it
+  // will return nullptr.
+  RingType* Ring() {
+    if (IsMapped() == false) {
+      TryMapping();
+
+      if (IsMapped()) {
+        switch (usage_mode_) {
+          case CPUUsageMode::READ_OFTEN:
+          case CPUUsageMode::READ_RARELY: {
+            RingType ring;
+            bool import_ok;
+            std::tie(ring, import_ok) = RingType::Import(address_, size_);
+            if (import_ok) {
+              ring_ = std::make_unique<RingType>(ring);
+            }
+          } break;
+          case CPUUsageMode::WRITE_OFTEN:
+          case CPUUsageMode::WRITE_RARELY:
+            ring_ =
+                std::make_unique<RingType>(RingType::Create(address_, size_));
+            break;
+        }
+      }
+    }
+
+    return ring_.get();
+  }
+
+ protected:
+  std::unique_ptr<RingType> ring_ = nullptr;
+
+  uint32_t sequence_ = 0;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..00bad88
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,84 @@
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+    : buffer_key_(key), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+                                 CPUUsageMode mode)
+    : owned_buffer_(std::move(buffer)),
+      buffer_(owned_buffer_.get()),
+      usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+    : buffer_(buffer), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+  if (IsMapped()) {
+    buffer_->Unlock();
+  }
+}
+
+void CPUMappedBuffer::TryMapping() {
+  // Do we have an IonBuffer for this shared memory object?
+  if (buffer_ == nullptr) {
+    // Create a display client and get the buffer.
+    // TODO(okana): We might want to throttle this.
+    auto display_client = display::DisplayClient::Create();
+    if (display_client) {
+      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+      if (get_result.ok()) {
+        owned_buffer_ = get_result.take();
+        buffer_ = owned_buffer_.get();
+      } else {
+        ALOGW("Could not get named buffer from pose service : %s(%d)",
+              get_result.GetErrorMessage().c_str(), get_result.error());
+      }
+    } else {
+      ALOGE("Unable to create display client for shared buffer access");
+    }
+  }
+
+  if (buffer_) {
+    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+                 ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+    // Figure out the usage bits.
+    switch (usage_mode_) {
+      case CPUUsageMode::READ_OFTEN:
+        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+        break;
+      case CPUUsageMode::READ_RARELY:
+        usage |= GRALLOC_USAGE_SW_READ_RARELY;
+        break;
+      case CPUUsageMode::WRITE_OFTEN:
+        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+        break;
+      case CPUUsageMode::WRITE_RARELY:
+        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+        break;
+    }
+
+    int width = static_cast<int>(buffer_->width());
+    int height = 1;
+    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+    if (ret < 0 || !address_) {
+      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+      buffer_->Unlock();
+    } else {
+      size_ = width;
+    }
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index fa78b1c..2b4ebbe 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -34,10 +34,11 @@
 ]
 
 static_libs = [
+    "libbroadcastring",
     "libbufferhub",
     "libbufferhubqueue",
-    "libdisplay",
     "libvrsensor",
+    "libdisplay",
     "libvirtualtouchpadclient",
     "libvr_hwc-impl",
     "libvr_hwc-binder",
diff --git a/libs/vr/libdvr/build_sdk.py b/libs/vr/libdvr/build_sdk.py
new file mode 100755
index 0000000..b3c2e44
--- /dev/null
+++ b/libs/vr/libdvr/build_sdk.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+import sys
+import os
+import argparse
+
+# Run this script to generate dvr_api.h in the current directory.
+
+def make_argument_parser():
+  parser = argparse.ArgumentParser(
+      description='Process DVR API headers into exportable SDK files.')
+  return parser
+
+parser = make_argument_parser()
+
+in_file = open("include/dvr/dvr_api.h", "r")
+out_file = open("./dvr_api.h", "w")
+
+h_filename = ""
+for line in in_file:
+  if line.startswith("// dvr_") and line.endswith(".h\n"):
+    h_filename = "include/dvr/" + line[3:].strip()
+  if line.startswith("typedef ") and "(*Dvr" in line:
+    start = line.find("(*Dvr") + 5
+    end = line.find("Ptr)")
+    if end != -1:
+      name = "dvr" + line[start:end]
+      # Find the comments for this function and insert into output.
+      with open(h_filename, 'r') as h_file:
+        h_lines = h_file.readlines()
+        i = 1
+        while i < len(h_lines):
+          if name in h_lines[i]:
+            end_i = i
+            while h_lines[i - 1].startswith("//"): i -= 1
+            while i < end_i:
+              out_file.write(h_lines[i])
+              i += 1
+            break
+          i += 1
+  if line.startswith('#include "dvr_api_entries.h"'):
+    with open("include/dvr/dvr_api_entries.h") as f:
+      out_file.write(f.read())
+  else:
+    out_file.write(line)
+
+in_file.close()
+out_file.close()
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index ef2c975..06f89da 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -18,7 +18,7 @@
 typedef uint64_t DvrSurfaceUpdateFlags;
 typedef struct DvrDisplayManager DvrDisplayManager;
 typedef struct DvrSurfaceState DvrSurfaceState;
-typedef struct DvrPose DvrPose;
+typedef struct DvrPoseClient DvrPoseClient;
 typedef struct DvrVSyncClient DvrVSyncClient;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
@@ -182,14 +182,15 @@
                                              uint32_t* next_vsync_count);
 
 // pose_client.h
-typedef DvrPose* (*DvrPoseCreatePtr)(void);
-typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
-typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
-                             DvrPoseAsync* out_pose);
-typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
-typedef int (*DvrPoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
-                                       uint32_t vsync_count,
-                                       DvrPoseAsync* out_pose);
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(void);
+typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
+                                   DvrPoseAsync* out_pose);
+typedef uint32_t (*DvrPoseClientGetVsyncCountPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetControllerPtr)(DvrPoseClient* client,
+                                             int32_t controller_id,
+                                             uint32_t vsync_count,
+                                             DvrPoseAsync* out_pose);
 
 // virtual_touchpad_client.h
 typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 30d0a65..441df4f 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -89,11 +89,11 @@
 DVR_V1_API_ENTRY(GetGlobalBuffer);
 
 // Pose client
-DVR_V1_API_ENTRY(PoseCreate);
-DVR_V1_API_ENTRY(PoseDestroy);
-DVR_V1_API_ENTRY(PoseGet);
-DVR_V1_API_ENTRY(PoseGetVsyncCount);
-DVR_V1_API_ENTRY(PoseGetController);
+DVR_V1_API_ENTRY(PoseClientCreate);
+DVR_V1_API_ENTRY(PoseClientDestroy);
+DVR_V1_API_ENTRY(PoseClientGet);
+DVR_V1_API_ENTRY(PoseClientGetVsyncCount);
+DVR_V1_API_ENTRY(PoseClientGetController);
 
 // Virtual touchpad client
 DVR_V1_API_ENTRY(VirtualTouchpadCreate);
diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h
new file mode 100644
index 0000000..a7e83c9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_pose.h
@@ -0,0 +1,79 @@
+#ifndef ANDROID_DVR_PUBLIC_POSE_H_
+#define ANDROID_DVR_PUBLIC_POSE_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#ifdef __ARM_NEON
+#include <arm_neon.h>
+#else
+#ifndef __FLOAT32X4T_86
+#define __FLOAT32X4T_86
+typedef float float32x4_t __attribute__((__vector_size__(16)));
+#endif
+#endif
+
+// Represents an estimated pose, accessed asynchronously through a shared ring
+// buffer. No assumptions should be made about the data in padding space.
+// The size of this struct is 128 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
+  // Left eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+  // Left eye head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+  // Right eye head-from-start orientation quaternion x,y,z,w.
+  float32x4_t right_orientation;
+  // Right eye head-from-start position x,y,z,pad in meters.
+  float32x4_t right_position;
+  // Start-space angular velocity x,y,z,pad in radians per second.
+  float32x4_t angular_velocity;
+  // Start-space positional velocity x,y,z,pad in meters per second.
+  float32x4_t velocity;
+  // Timestamp of when this pose is predicted for, typically halfway through
+  // scanout.
+  int64_t timestamp_ns;
+  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
+  //
+  // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
+  uint64_t flags;
+  // Reserved padding to 128 bytes.
+  uint8_t pad[16];
+} DvrPoseAsync;
+
+enum {
+  DVR_POSE_FLAG_VALID = (1UL << 0),       // This pose is valid.
+  DVR_POSE_FLAG_HEAD = (1UL << 1),        // This pose is the head.
+  DVR_POSE_FLAG_CONTROLLER = (1UL << 2),  // This pose is a controller.
+};
+
+// Represents a sensor pose sample.
+typedef struct __attribute__((packed, aligned(16))) DvrPose {
+  // Head-from-start orientation quaternion x,y,z,w.
+  float32x4_t orientation;
+
+  // The angular velocity where the x,y,z is the rotation axis and the
+  // magnitude is the radians / second in the same coordinate frame as
+  // orientation.
+  float32x4_t angular_velocity;
+
+  // Head-from-start position x,y,z,pad in meters.
+  float32x4_t position;
+
+  // In meters / second in the same coordinate frame as position.
+  float32x4_t velocity;
+
+  // In meters / second ^ 2 in the same coordinate frame as position.
+  float32x4_t acceleration;
+
+  // Timestamp for the measurement in nanoseconds.
+  int64_t timestamp_ns;
+
+  // Padding to 96 bytes so the size is a multiple of 16.
+  uint8_t padding[8];
+} DvrPose;
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_PUBLIC_POSE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
new file mode 100644
index 0000000..ce17f0c
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -0,0 +1,102 @@
+#ifndef ANDROID_DVR_SHARED_BUFFERS_H_
+#define ANDROID_DVR_SHARED_BUFFERS_H_
+
+#include <dvr/dvr_pose.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
+#include <libbroadcastring/broadcast_ring.h>
+
+// This header is shared by VrCore and Android and must be kept in sync.
+namespace android {
+namespace dvr {
+
+// Increment when the layout for the buffers change.
+constexpr uint32_t kSharedBufferLayoutVersion = 1;
+
+// Note: These buffers will be mapped from various system processes as well
+// as VrCore and the application processes in a r/w manner.
+//
+// Therefore it is possible for the application to mess with the contents of
+// these buffers.
+//
+// While using them, assume garbage memory: Your logic must not crash or lead
+// to execution of unsafe code as a function of the contents of these buffers.
+
+// Sanity check for basic type sizes.
+static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
+static_assert(sizeof(DvrPose) == 96, "Unexpected size for DvrPose");
+static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+
+// A helper class that provides compile time sized traits for the BroadcastRing.
+template <class DvrType, size_t StaticCount>
+class DvrRingBufferTraits {
+ public:
+  using Record = DvrType;
+  static constexpr bool kUseStaticRecordSize = false;
+  static constexpr uint32_t kStaticRecordCount = StaticCount;
+  static constexpr int kMaxReservedRecords = 1;
+  static constexpr int kMinAvailableRecords = 1;
+};
+
+// Traits classes.
+using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
+using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
+using DvrVrFlingerConfigTraits = DvrRingBufferTraits<DvrVrFlingerConfig, 2>;
+
+// The broadcast ring classes that will expose the data.
+using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
+using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
+using DvrVrFlingerConfigRing =
+    BroadcastRing<DvrVrFlingerConfig, DvrVrFlingerConfigTraits>;
+
+// This is a shared memory buffer for passing pose data estimated at vsyncs.
+//
+// This will be primarily used for late latching and EDS where we bind this
+// buffer in a shader and extract the right vsync-predicted pose.
+struct __attribute__((packed, aligned(16))) DvrVsyncPoseBuffer {
+  enum : int {
+    // The number vsync predicted poses to keep in the ring buffer.
+    // Must be a power of 2.
+    kSize = 8,
+    kIndexMask = kSize - 1,
+
+    // The number of vsyncs (from the current vsync) we predict in vsync buffer.
+    // The other poses are left alone.
+    kMinFutureCount = 4
+  };
+
+  // The vsync predicted poses.
+  // The pose for the vsync n is:
+  // vsync_poses[n % kSize]
+  //
+  // This buffer is unsynchronized: It is possible to get torn reads as the
+  // sensor service updates the predictions as new sensor measurements come
+  // in. In particular, it is possible to get the position and an updated
+  // orientation while reading.
+  DvrPoseAsync vsync_poses[kSize];
+
+  // The latest sensor pose for GPU usage.
+  DvrPose current_pose;
+
+  // Current vsync_count (where sensord is writing poses from).
+  uint32_t vsync_count;
+
+  // For 16 byte alignment.
+  uint8_t padding[12];
+};
+
+static_assert(sizeof(DvrVsyncPoseBuffer) == 1136,
+              "Unexpected size for DvrVsyncPoseBuffer");
+
+// The keys for the dvr global buffers.
+enum DvrGlobalBuffers : int32_t {
+  kVsyncPoseBuffer = 1,
+  kVsyncBuffer = 2,
+  kSensorPoseBuffer = 3,
+  kVrFlingerConfigBufferKey = 4
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFERS_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
new file mode 100644
index 0000000..cfe9d62
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
@@ -0,0 +1,30 @@
+#ifndef ANDROID_DVR_VRFLINGER_CONFIG_H
+#define ANDROID_DVR_VRFLINGER_CONFIG_H
+
+// This header is shared by VrCore and Android and must be kept in sync.
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// This is a shared memory buffer for passing config data from VrCore to
+// libvrflinger in SurfaceFlinger.
+struct DvrVrFlingerConfig {
+  // Offset before vsync to submit frames to hardware composer.
+  int frame_post_offset_ns{4000000};
+
+  // If the number of pending fences goes over this count at the point when we
+  // are about to submit a new frame to HWC, we will drop the frame. This
+  // should be a signal that the display driver has begun queuing frames. Note
+  // that with smart displays (with RAM), the fence is signaled earlier than
+  // the next vsync, at the point when the DMA to the display completes.
+  // Currently we use a smart display and the EDS timing coincides with zero
+  // pending fences, so this is 0.
+  size_t allowed_pending_fence_count{0};
+
+  // New fields should always be added to the end for backwards compat.
+};
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_VRFLINGER_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h
deleted file mode 100644
index 108c78b..0000000
--- a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
-#define ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
-
-#include <libbroadcastring/broadcast_ring.h>
-
-// This header is shared by VrCore and Android and must be kept in sync.
-
-namespace android {
-namespace dvr {
-
-// Increment when the layout for the buffers change.
-constexpr uint32_t kSharedConfigBufferLayoutVersion = 1;
-
-// This is a shared memory buffer for passing config data from VrCore to
-// libvrflinger in SurfaceFlinger.
-struct DvrVrFlingerConfigBuffer {
-  // Offset before vsync to submit frames to hardware composer.
-  int frame_post_offset_ns{4000000};
-
-  // If the number of pending fences goes over this count at the point when we
-  // are about to submit a new frame to HWC, we will drop the frame. This
-  // should be a signal that the display driver has begun queuing frames. Note
-  // that with smart displays (with RAM), the fence is signaled earlier than
-  // the next vsync, at the point when the DMA to the display completes.
-  // Currently we use a smart display and the EDS timing coincides with zero
-  // pending fences, so this is 0.
-  size_t allowed_pending_fence_count{0};
-
-  // New fields should always be added to the end for backwards compat.
-};
-
-class DvrVrFlingerConfigBufferTraits {
- public:
-  using Record = DvrVrFlingerConfigBuffer;
-  static constexpr bool kUseStaticRecordSize = false;
-  static constexpr uint32_t kStaticRecordCount = 2;
-  static constexpr int kMaxReservedRecords = 1;
-  static constexpr int kMinAvailableRecords = 1;
-};
-
-// The broadcast ring classes that will expose the data.
-using DvrVrFlingerConfigRing =
-    BroadcastRing<DvrVrFlingerConfigBuffer, DvrVrFlingerConfigBufferTraits>;
-
-// Common buffers.
-constexpr int kVrFlingerConfigBufferKey = 5;
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
index 1eea3d9..87fdf31 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vsync.h
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -8,6 +8,27 @@
 
 typedef struct DvrVSyncClient DvrVSyncClient;
 
+// Represents a vsync sample. The size of this struct is 32 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrVsync {
+  // The timestamp for the last vsync in nanoseconds.
+  uint64_t vsync_timestamp_ns;
+
+  // The index of the last vsync.
+  uint32_t vsync_count;
+
+  // Scan out for the left eye = vsync_timestamp_ns + vsync_left_eye_offset_ns.
+  int32_t vsync_left_eye_offset_ns;
+
+  // Scan out for the right eye = vsync_timestamp_ns + vsync_right_eye_offset_ns
+  int32_t vsync_right_eye_offset_ns;
+
+  // The period of a vsync in nanoseconds.
+  uint32_t vsync_period_ns;
+
+  // Padding to 32 bytes so the size is a multiple of 16.
+  uint8_t padding[8];
+} DvrVsync;
+
 // Creates a new client to the system vsync service.
 int dvrVSyncClientCreate(DvrVSyncClient** client_out);
 
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 5d12020..2426a49 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -25,8 +25,9 @@
 class DvrBufferQueueTest : public ::testing::Test {
  protected:
   void SetUp() override {
+    auto config = ProducerQueueConfigBuilder().SetMetadata<TestMeta>().Build();
     write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
-        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
+        ProducerQueue::Create(config, UsagePolicy{}));
     ASSERT_NE(nullptr, write_queue_);
   }
 
@@ -197,11 +198,13 @@
   ASSERT_EQ(nullptr, window);
 
   // A write queue with DvrNativeBufferMetadata should work fine.
+  auto config = ProducerQueueConfigBuilder()
+                    .SetMetadata<DvrNativeBufferMetadata>()
+                    .Build();
   std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
-      write_queue(
-          CreateDvrWriteBufferQueueFromProducerQueue(
-              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
-          dvrWriteBufferQueueDestroy);
+      write_queue(CreateDvrWriteBufferQueueFromProducerQueue(
+                      ProducerQueue::Create(config, UsagePolicy{})),
+                  dvrWriteBufferQueueDestroy);
   ASSERT_NE(nullptr, write_queue.get());
 
   ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index cf04588..419083f 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,8 +1,9 @@
 #include <android/hardware_buffer.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/dvr_surface.h>
-#include <dvr/dvr_vrflinger_config_buffer.h>
+#include <dvr/dvr_vrflinger_config.h>
 #include <system/graphics.h>
 
 #include <base/logging.h>
@@ -275,7 +276,8 @@
 }
 
 TEST_F(DvrGlobalBufferTest, TestVrflingerConfigBuffer) {
-  const DvrGlobalBufferKey buffer_name = kVrFlingerConfigBufferKey;
+  const DvrGlobalBufferKey buffer_name =
+      DvrGlobalBuffers::kVrFlingerConfigBufferKey;
 
   // First delete any existing buffer so we can test the failure case.
   dvrDisplayManagerDeleteGlobalBuffer(client_, buffer_name);
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index 527cdbd..62aeb79 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -28,7 +28,7 @@
     "libhardware",
 ]
 
-staticLibraries = ["libpdx_default_transport"]
+staticLibraries = ["libpdx_default_transport", "libbroadcastring"]
 
 headerLibraries = [
     "libeigen",
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 080479a..0fb2d84 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -34,6 +34,7 @@
     "libdvrcommon",
     "libperformance",
     "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
     "libvr_manager",
     "libbroadcastring",
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index fb2751b..babdc0e 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -207,7 +207,9 @@
            surface_id(), meta_size_bytes);
 
   std::lock_guard<std::mutex> autolock(lock_);
-  auto producer = ProducerQueue::Create(meta_size_bytes);
+  auto config =
+      ProducerQueueConfigBuilder().SetMetadataSize(meta_size_bytes).Build();
+  auto producer = ProducerQueue::Create(config, UsagePolicy{});
   if (!producer) {
     ALOGE(
         "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
@@ -268,7 +270,12 @@
 
   std::lock_guard<std::mutex> autolock(lock_);
   if (!direct_queue_) {
-    auto producer = ProducerQueue::Create(meta_size_bytes);
+    // Inject the hw composer usage flag to enable the display to read the
+    // buffers.
+    auto config =
+        ProducerQueueConfigBuilder().SetMetadataSize(meta_size_bytes).Build();
+    auto producer = ProducerQueue::Create(
+        config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0});
     if (!producer) {
       ALOGE(
           "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 88173ca..7a78d1f 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -25,7 +25,6 @@
 #include <dvr/performance_client_api.h>
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/ion_buffer.h>
-#include <private/dvr/pose_client_internal.h>
 
 using android::pdx::LocalHandle;
 using android::pdx::rpc::EmptyVariant;
@@ -211,10 +210,6 @@
 void HardwareComposer::OnPostThreadResumed() {
   hwc2_hidl_->resetCommands();
 
-  // Connect to pose service.
-  pose_client_ = dvrPoseCreate();
-  ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
-
   // HIDL HWC seems to have an internal race condition. If we submit a frame too
   // soon after turning on VSync we don't get any VSync signals. Give poor HWC
   // implementations a chance to enable VSync before we continue.
@@ -243,11 +238,6 @@
   }
   active_layer_count_ = 0;
 
-  if (pose_client_) {
-    dvrPoseDestroy(pose_client_);
-    pose_client_ = nullptr;
-  }
-
   EnableVsync(false);
 
   hwc2_hidl_->resetCommands();
@@ -467,7 +457,16 @@
 
 int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
                                         IonBuffer& ion_buffer) {
-  if (key == kVrFlingerConfigBufferKey) {
+  if (key == DvrGlobalBuffers::kVsyncBuffer) {
+    vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
+        &ion_buffer, CPUUsageMode::WRITE_OFTEN);
+
+    if (vsync_ring_->IsMapped() == false) {
+      return -EPERM;
+    }
+  }
+
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
     return MapConfigBuffer(ion_buffer);
   }
 
@@ -475,7 +474,7 @@
 }
 
 void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
-  if (key == kVrFlingerConfigBufferKey) {
+  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
     ConfigBufferDeleted();
   }
 }
@@ -515,7 +514,7 @@
   if (!shared_config_ring_.is_valid())
     return;
   // Copy from latest record in shared_config_ring_ to local copy.
-  DvrVrFlingerConfigBuffer record;
+  DvrVrFlingerConfig record;
   if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
     post_thread_config_ = record;
   }
@@ -850,16 +849,20 @@
 
     ++vsync_count_;
 
-    if (pose_client_) {
-      // Signal the pose service with vsync info.
-      // Display timestamp is in the middle of scanout.
-      privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
-                                vsync_timestamp + photon_offset_ns,
-                                ns_per_frame, right_eye_photon_offset_ns);
-    }
-
     const bool layer_config_changed = UpdateLayerConfig();
 
+    // Publish the vsync event.
+    if (vsync_ring_) {
+      DvrVsync vsync;
+      vsync.vsync_count = vsync_count_;
+      vsync.vsync_timestamp_ns = vsync_timestamp;
+      vsync.vsync_left_eye_offset_ns = photon_offset_ns;
+      vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
+      vsync.vsync_period_ns = ns_per_frame;
+
+      vsync_ring_->Publish(vsync);
+    }
+
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index c182bf9..de6f9ff 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -5,6 +5,7 @@
 #include "DisplayHardware/ComposerHal.h"
 #include "hwc_types.h"
 
+#include <dvr/dvr_shared_buffers.h>
 #include <hardware/gralloc.h>
 #include <log/log.h>
 
@@ -16,11 +17,12 @@
 #include <tuple>
 #include <vector>
 
-#include <dvr/dvr_vrflinger_config_buffer.h>
-#include <dvr/pose_client.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
 #include <pdx/file_handle.h>
 #include <pdx/rpc/variant.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
 #include "acquired_buffer.h"
 #include "display_surface.h"
@@ -446,15 +448,14 @@
   // us to detect when the display driver begins queuing frames.
   std::vector<pdx::LocalHandle> retire_fence_fds_;
 
-  // Pose client for frame count notifications. Pose client predicts poses
-  // out to display frame boundaries, so we need to tell it about vsyncs.
-  DvrPose* pose_client_ = nullptr;
+  // If we are publishing vsync data, we will put it here.
+  std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
 
   // Broadcast ring for receiving config data from the DisplayManager.
   DvrVrFlingerConfigRing shared_config_ring_;
   uint32_t shared_config_ring_sequence_{0};
   // Config buffer for reading from the post thread.
-  DvrVrFlingerConfigBuffer post_thread_config_;
+  DvrVrFlingerConfig post_thread_config_;
   std::mutex shared_config_mutex_;
 
   static constexpr int kPostThreadInterrupted = 1;
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index abad78b..d022adf 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -23,9 +23,11 @@
 ]
 
 staticLibraries = [
+    "libdisplay",
     "libbufferhub",
     "libbufferhubqueue",
     "libdvrcommon",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
@@ -43,6 +45,7 @@
     export_include_dirs: includeFiles,
     static_libs: staticLibraries,
     shared_libs: sharedLibraries,
+    header_libs: ["libdvr_headers"],
     name: "libvrsensor",
 }
 
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index 6802fa9..d684ddc 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -14,63 +14,13 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#include <dvr/dvr_pose.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct DvrPose DvrPose;
-
-// Represents the current state provided by the pose service, containing a
-// rotation and translation.
-typedef struct __attribute__((packed, aligned(8))) DvrPoseState {
-  // A quaternion representing the rotation of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z, w;
-  } head_from_start_rotation;
-  // The position of the HMD in Start Space.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } head_from_start_translation;
-  // Time in nanoseconds for the current pose.
-  uint64_t timestamp_ns;
-  // The rotational velocity of the HMD.
-  struct __attribute__((packed)) {
-    float x, y, z;
-  } sensor_from_start_rotation_velocity;
-} DvrPoseState;
-
-enum {
-  DVR_POSE_FLAG_VALID = (1UL << 0),       // This pose is valid.
-  DVR_POSE_FLAG_HEAD = (1UL << 1),        // This pose is the head.
-  DVR_POSE_FLAG_CONTROLLER = (1UL << 2),  // This pose is a controller.
-};
-
-// Represents an estimated pose, accessed asynchronously through a shared ring
-// buffer. No assumptions should be made about the data in padding space.
-// The size of this struct is 128 bytes.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
-  // Left eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t orientation;
-  // Left eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t translation;
-  // Right eye head-from-start orientation quaternion x,y,z,w.
-  float32x4_t right_orientation;
-  // Right eye head-from-start translation x,y,z,pad in meters.
-  float32x4_t right_translation;
-  // Start-space angular velocity x,y,z,pad in radians per second.
-  float32x4_t angular_velocity;
-  // Start-space positional velocity x,y,z,pad in meters per second.
-  float32x4_t velocity;
-  // Timestamp of when this pose is predicted for, typically halfway through
-  // scanout.
-  int64_t timestamp_ns;
-  // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
-  //
-  // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
-  uint64_t flags;
-  // Reserved padding to 128 bytes.
-  uint8_t pad[16];
-} DvrPoseAsync;
+typedef struct DvrPoseClient DvrPoseClient;
 
 // Returned by the async pose ring buffer access API.
 typedef struct DvrPoseRingBufferInfo {
@@ -120,12 +70,12 @@
 // Creates a new pose client.
 //
 // @return Pointer to the created pose client, nullptr on failure.
-DvrPose* dvrPoseCreate();
+DvrPoseClient* dvrPoseClientCreate();
 
 // Destroys a pose client.
 //
 // @param client Pointer to the pose client to be destroyed.
-void dvrPoseDestroy(DvrPose* client);
+void dvrPoseClientDestroy(DvrPoseClient* client);
 
 // Gets the pose for the given vsync count.
 //
@@ -134,10 +84,11 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose);
 
 // Gets the current vsync count.
-uint32_t dvrPoseGetVsyncCount(DvrPose* client);
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client);
 
 // Gets the pose for the given controller at the given vsync count.
 //
@@ -147,15 +98,15 @@
 //     Typically this is the count returned by dvrGetNextVsyncCount.
 // @param out_pose Struct to store pose state.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose);
 
 // Enables/disables logging for the controller fusion.
 //
 // @param client Pointer to the pose client.
 // @param enable True starts logging, False stops.
 // @return Zero on success, negative error code on failure.
-int dvrPoseLogController(DvrPose* client, bool enable);
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable);
 
 // DEPRECATED
 // Polls current pose state.
@@ -163,30 +114,30 @@
 // @param client Pointer to the pose client.
 // @param state Struct to store polled state.
 // @return Zero on success, negative error code on failure.
-int dvrPosePoll(DvrPose* client, DvrPoseState* state);
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state);
 
 // Freezes the pose to the provided state.
 //
 // Future poll operations will return this state until a different state is
-// frozen or dvrPoseSetMode() is called with a different mode. The timestamp is
+// frozen or dvrPoseClientModeSet() is called with a different mode. The timestamp is
 // not frozen.
 //
 // @param client Pointer to the pose client.
 // @param frozen_state State pose to be frozen to.
 // @return Zero on success, negative error code on failure.
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state);
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state);
 
 // Sets the pose service mode.
 //
 // @param mode The requested pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode);
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode);
 
 // Gets the pose service mode.
 //
 // @param mode Return value for the current pose mode.
 // @return Zero on success, negative error code on failure.
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode);
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode);
 
 // Get access to the shared memory pose ring buffer.
 // A future pose at vsync <current> + <offset> is accessed at index:
@@ -197,8 +148,14 @@
 // |out_fd| will be set to the gralloc buffer file descriptor, which is
 //   required for binding this buffer for GPU use.
 // Returns 0 on success.
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info);
+int dvrPoseClientGetRingBuffer(DvrPoseClient* client,
+                               DvrPoseRingBufferInfo* out_info);
 
+// Sets enabled state for sensors pose processing.
+//
+// @param enabled Whether sensors are enabled or disabled.
+// @return Zero on success
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
index 0616d46..e4455f1 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
@@ -11,14 +11,12 @@
 #define DVR_POSE_SERVICE_CLIENT (DVR_POSE_SERVICE_BASE "/client")
 
 enum {
-  DVR_POSE_POLL = 0,
-  DVR_POSE_FREEZE,
+  DVR_POSE_FREEZE = 0,
   DVR_POSE_SET_MODE,
-  DVR_POSE_GET_RING_BUFFER,
-  DVR_POSE_NOTIFY_VSYNC,
   DVR_POSE_GET_MODE,
   DVR_POSE_GET_CONTROLLER_RING_BUFFER,
   DVR_POSE_LOG_CONTROLLER,
+  DVR_POSE_SENSORS_ENABLE,
 };
 
 #ifdef __cplusplus
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
deleted file mode 100644
index 66c4c7c..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-#define ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-
-#include <stdint.h>
-
-#include <dvr/pose_client.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/sensor_constants.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Sensord head pose ring buffer.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseRingBuffer {
-  // Ring buffer always at the beginning of the structure, as consumers may
-  // not have access to this parent structure definition.
-  DvrPoseAsync ring[kPoseAsyncBufferTotalCount];
-  // Current vsync_count (where sensord is writing poses from).
-  uint32_t vsync_count;
-} DvrPoseMetadata;
-
-// Called by displayd to give vsync count info to the pose service.
-// |display_timestamp| Display timestamp is in the middle of scanout.
-// |display_period_ns| Nanos between vsyncs.
-// |right_eye_photon_offset_ns| Nanos to shift the prediction timestamp for
-//    the right eye head pose (relative to the left eye prediction).
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns);
-
-// Get file descriptor for access to the shared memory pose buffer. This can be
-// used with GL extensions that support shared memory buffer objects. The caller
-// takes ownership of the returned fd and must close it or pass on ownership.
-int privateDvrPoseGetRingBufferFd(DvrPose* client,
-                                  android::pdx::LocalHandle* fd);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h b/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
deleted file mode 100644
index 8fa87b3..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CONSTANTS_H_
-#define ANDROID_DVR_SENSOR_CONSTANTS_H_
-
-namespace android {
-namespace dvr {
-
-// Number of elements in the async pose buffer.
-// Must be power of two.
-// Macro so that shader code can easily include this value.
-#define kPoseAsyncBufferTotalCount 8
-
-// Mask for accessing the current ring buffer array element:
-// index = vsync_count & kPoseAsyncBufferIndexMask
-constexpr uint32_t kPoseAsyncBufferIndexMask = kPoseAsyncBufferTotalCount - 1;
-
-// Number of pose frames including the current frame that are kept updated with
-// pose forecast data. The other poses are left their last known estimates.
-constexpr uint32_t kPoseAsyncBufferMinFutureCount = 4;
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SENSOR_CONSTANTS_H_
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 9eae3aa..b21c7cf 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -1,4 +1,5 @@
 #define LOG_TAG "PoseClient"
+#include <dvr/dvr_shared_buffers.h>
 #include <dvr/pose_client.h>
 
 #include <stdint.h>
@@ -8,9 +9,9 @@
 #include <pdx/default_transport/client_channel_factory.h>
 #include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/display_client.h>
 #include <private/dvr/pose-ipc.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sensor_constants.h>
+#include <private/dvr/shared_buffer_helpers.h>
 
 using android::pdx::LocalHandle;
 using android::pdx::LocalChannelHandle;
@@ -28,39 +29,44 @@
   ~PoseClient() override {}
 
   // Casts C handle into an instance of this class.
-  static PoseClient* FromC(DvrPose* client) {
+  static PoseClient* FromC(DvrPoseClient* client) {
     return reinterpret_cast<PoseClient*>(client);
   }
 
   // Polls the pose service for the current state and stores it in *state.
   // Returns zero on success, a negative error code otherwise.
-  int Poll(DvrPoseState* state) {
-    Transaction trans{*this};
-    Status<int> status =
-        trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
-    ALOGE_IF(!status, "Pose poll() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
+  int Poll(DvrPose* state) {
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      if (state) {
+        // Fill the state
+        *state = vsync_buffer->current_pose;
+      }
+      return -EINVAL;
+    }
+
+    return -EAGAIN;
   }
 
   int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return ret;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      *out_pose =
+          vsync_buffer
+              ->vsync_poses[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
+      return 0;
+    } else {
+      return -EAGAIN;
     }
-    *out_pose =
-        mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
-    return 0;
   }
 
   uint32_t GetVsyncCount() {
-    if (!mapped_pose_buffer_) {
-      int ret = GetRingBuffer(nullptr);
-      if (ret < 0)
-        return 0;
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      return vsync_buffer->vsync_count;
     }
-    return mapped_pose_buffer_->vsync_count;
+
+    return 0;
   }
 
   int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
@@ -75,7 +81,7 @@
     }
     *out_pose =
         controllers_[controller_id]
-            .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
+            .mapped_pose_buffer[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
     return 0;
   }
 
@@ -92,7 +98,7 @@
   // this state until a different state is frozen or SetMode() is called with a
   // different mode.
   // Returns zero on success, a negative error code otherwise.
-  int Freeze(const DvrPoseState& frozen_state) {
+  int Freeze(const DvrPose& frozen_state) {
     Transaction trans{*this};
     Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
                                          sizeof(frozen_state), nullptr, 0);
@@ -124,48 +130,29 @@
     return ReturnStatusOrError(status);
   }
 
-  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
-    if (pose_buffer_.get()) {
-      if (out_info) {
-        GetPoseRingBufferInfo(out_info);
-      }
-      return 0;
-    }
-
+  // Enables or disables all pose processing from sensors
+  int EnableSensors(bool enabled) {
     Transaction trans{*this};
-    Status<LocalChannelHandle> status =
-        trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
-    if (!status) {
-      ALOGE("Pose GetRingBuffer() failed because: %s",
-            status.GetErrorMessage().c_str());
-      return -status.error();
+    Status<int> status = trans.Send<int>(DVR_POSE_SENSORS_ENABLE, &enabled,
+                                         sizeof(enabled), nullptr, 0);
+    ALOGE_IF(!status, "Pose EnableSensors() failed because: %s\n",
+             status.GetErrorMessage().c_str());
+    return ReturnStatusOrError(status);
+  }
+
+  int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
+    // First time mapping the buffer?
+    const auto vsync_buffer = GetVsyncBuffer();
+    if (vsync_buffer) {
+      if (out_info) {
+        out_info->min_future_count = DvrVsyncPoseBuffer::kMinFutureCount;
+        out_info->total_count = DvrVsyncPoseBuffer::kSize;
+        out_info->buffer = vsync_buffer->vsync_poses;
+      }
+      return -EINVAL;
     }
 
-    auto buffer = BufferConsumer::Import(status.take());
-    if (!buffer) {
-      ALOGE("Pose failed to import ring buffer");
-      return -EIO;
-    }
-    void* addr = nullptr;
-    int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
-    if (ret < 0 || !addr) {
-      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
-      return -EIO;
-    }
-    pose_buffer_.swap(buffer);
-    mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
-    ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
-          mapped_pose_buffer_->ring[0].translation[0],
-          mapped_pose_buffer_->ring[0].translation[1],
-          mapped_pose_buffer_->ring[0].translation[2],
-          mapped_pose_buffer_->ring[0].orientation[0],
-          mapped_pose_buffer_->ring[0].orientation[1],
-          mapped_pose_buffer_->ring[0].orientation[2],
-          mapped_pose_buffer_->ring[0].orientation[3]);
-    if (out_info) {
-      GetPoseRingBufferInfo(out_info);
-    }
-    return 0;
+    return -EAGAIN;
   }
 
   int GetControllerRingBuffer(int32_t controller_id) {
@@ -190,7 +177,7 @@
       ALOGE("Pose failed to import ring buffer");
       return -EIO;
     }
-    constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
+    constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
     void* addr = nullptr;
     int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
     if (ret < 0 || !addr) {
@@ -201,9 +188,9 @@
     client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
     ALOGI(
         "Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
-        controller_id, client_state.mapped_pose_buffer[0].translation[0],
-        client_state.mapped_pose_buffer[0].translation[1],
-        client_state.mapped_pose_buffer[0].translation[2],
+        controller_id, client_state.mapped_pose_buffer[0].position[0],
+        client_state.mapped_pose_buffer[0].position[1],
+        client_state.mapped_pose_buffer[0].position[2],
         client_state.mapped_pose_buffer[0].orientation[0],
         client_state.mapped_pose_buffer[0].orientation[1],
         client_state.mapped_pose_buffer[0].orientation[2],
@@ -211,32 +198,6 @@
     return 0;
   }
 
-  int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
-                  int64_t display_period_ns,
-                  int64_t right_eye_photon_offset_ns) {
-    const struct iovec data[] = {
-        {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
-        {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
-        {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
-        {.iov_base = &right_eye_photon_offset_ns,
-         .iov_len = sizeof(right_eye_photon_offset_ns)},
-    };
-    Transaction trans{*this};
-    Status<int> status =
-        trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
-    ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
-             status.GetErrorMessage().c_str());
-    return ReturnStatusOrError(status);
-  }
-
-  int GetRingBufferFd(LocalHandle* fd) {
-    int ret = GetRingBuffer(nullptr);
-    if (ret < 0)
-      return ret;
-    *fd = pose_buffer_->GetBlobFd();
-    return 0;
-  }
-
  private:
   friend BASE;
 
@@ -252,14 +213,29 @@
   PoseClient(const PoseClient&) = delete;
   PoseClient& operator=(const PoseClient&) = delete;
 
-  void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
-    out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
-    out_info->total_count = kPoseAsyncBufferTotalCount;
-    out_info->buffer = mapped_pose_buffer_->ring;
+  const DvrVsyncPoseBuffer* GetVsyncBuffer() {
+    if (mapped_vsync_pose_buffer_ == nullptr) {
+      if (vsync_pose_buffer_ == nullptr) {
+        // The constructor tries mapping it so we do not need TryMapping after.
+        vsync_pose_buffer_ = std::make_unique<CPUMappedBuffer>(
+            DvrGlobalBuffers::kVsyncPoseBuffer, CPUUsageMode::READ_OFTEN);
+      } else if (vsync_pose_buffer_->IsMapped() == false) {
+        vsync_pose_buffer_->TryMapping();
+      }
+
+      if (vsync_pose_buffer_->IsMapped()) {
+        mapped_vsync_pose_buffer_ =
+            static_cast<DvrVsyncPoseBuffer*>(vsync_pose_buffer_->Address());
+      }
+    }
+
+    return mapped_vsync_pose_buffer_;
   }
 
-  std::unique_ptr<BufferConsumer> pose_buffer_;
-  const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
+  // The vsync pose buffer if already mapped.
+  std::unique_ptr<CPUMappedBuffer> vsync_pose_buffer_;
+
+  const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
 
   struct ControllerClientState {
     std::unique_ptr<BufferConsumer> pose_buffer;
@@ -273,66 +249,55 @@
 
 using android::dvr::PoseClient;
 
-struct DvrPose {};
-
 extern "C" {
 
-DvrPose* dvrPoseCreate() {
-  PoseClient* client = PoseClient::Create().release();
-  return reinterpret_cast<DvrPose*>(client);
+DvrPoseClient* dvrPoseClientCreate() {
+  auto* client = PoseClient::Create().release();
+  return reinterpret_cast<DvrPoseClient*>(client);
 }
 
-void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
+void dvrPoseClientDestroy(DvrPoseClient* client) {
+  delete PoseClient::FromC(client);
+}
 
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+                     DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
 }
 
-uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client) {
   return PoseClient::FromC(client)->GetVsyncCount();
 }
 
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
-                         uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+                               uint32_t vsync_count, DvrPoseAsync* out_pose) {
   return PoseClient::FromC(client)->GetControllerPose(controller_id,
                                                       vsync_count, out_pose);
 }
 
-int dvrPoseLogController(DvrPose* client, bool enable) {
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable) {
   return PoseClient::FromC(client)->LogController(enable);
 }
 
-int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state) {
   return PoseClient::FromC(client)->Poll(state);
 }
 
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state) {
   return PoseClient::FromC(client)->Freeze(*frozen_state);
 }
 
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
+int dvrPoseClientModeSet(DvrPoseClient* client, DvrPoseMode mode) {
   return PoseClient::FromC(client)->SetMode(mode);
 }
 
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
+int dvrPoseClientModeGet(DvrPoseClient* client, DvrPoseMode* mode) {
   return PoseClient::FromC(client)->GetMode(mode);
 }
 
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
-  return PoseClient::FromC(client)->GetRingBuffer(out_info);
-}
 
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
-                              int64_t display_timestamp,
-                              int64_t display_period_ns,
-                              int64_t right_eye_photon_offset_ns) {
-  return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
-                                                display_period_ns,
-                                                right_eye_photon_offset_ns);
-}
-
-int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
-  return PoseClient::FromC(client)->GetRingBufferFd(fd);
+int dvrPoseClientSensorsEnable(DvrPoseClient* client, bool enabled) {
+  return PoseClient::FromC(client)->EnableSensors(enabled);
 }
 
 }  // extern "C"
diff --git a/services/displayservice/DisplayEventReceiver.cpp b/services/displayservice/DisplayEventReceiver.cpp
index a7fd3c5..5993e44 100644
--- a/services/displayservice/DisplayEventReceiver.cpp
+++ b/services/displayservice/DisplayEventReceiver.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #define LOG_TAG "libdisplayservicehidl"
 
 #include <displayservice/DisplayEventReceiver.h>
@@ -43,12 +44,14 @@
     return looper;
 }
 
-DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback) : mCallback(callback) {
+DisplayEventReceiver::AttachedEvent::AttachedEvent(const sp<IEventCallback> &callback)
+    : mCallback(callback)
+{
     mLooperAttached = getLooper()->addFd(mFwkReceiver.getFd(),
-                                         Looper::POLL_CALLBACK,
-                                         Looper::EVENT_INPUT,
-                                         this,
-                                         nullptr);
+            Looper::POLL_CALLBACK,
+            Looper::EVENT_INPUT,
+            this,
+            nullptr);
 }
 
 DisplayEventReceiver::AttachedEvent::~AttachedEvent() {
@@ -86,7 +89,7 @@
         return 1; // keep the callback
     }
 
-    const static size_t SIZE = 1;
+    constexpr size_t SIZE = 1;
 
     ssize_t n;
     FwkReceiver::Event buf[SIZE];
@@ -149,11 +152,11 @@
 }
 
 Return<Status> DisplayEventReceiver::close() {
+    std::unique_lock<std::mutex> lock(mMutex);
     if (mAttached == nullptr) {
         return Status::BAD_VALUE;
     }
 
-    std::unique_lock<std::mutex> lock(mMutex);
     bool success = mAttached->detach();
     mAttached = nullptr;
 
diff --git a/services/displayservice/DisplayService.cpp b/services/displayservice/DisplayService.cpp
index 1699673..18418fd 100644
--- a/services/displayservice/DisplayService.cpp
+++ b/services/displayservice/DisplayService.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include <displayservice/DisplayService.h>
 #include <displayservice/DisplayEventReceiver.h>
 
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
index 83c0931..5d569b6 100644
--- a/services/displayservice/include/displayservice/DisplayEventReceiver.h
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
 #define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYEVENTRECEIVER_H
 
diff --git a/services/displayservice/include/displayservice/DisplayService.h b/services/displayservice/include/displayservice/DisplayService.h
index d92cb62..9722e71 100644
--- a/services/displayservice/include/displayservice/DisplayService.h
+++ b/services/displayservice/include/displayservice/DisplayService.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
 #define ANDROID_FRAMEWORKS_DISPLAYSERVICE_V1_0_DISPLAYSERVICE_H
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0f93cd7..245e0ed 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -298,6 +298,11 @@
     }
 
     mSurfaceFlingerConsumer->abandon();
+
+#ifdef USE_HWC2
+    clearHwcLayers();
+#endif
+
     for (const auto& child : mCurrentChildren) {
         child->onRemoved();
     }
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index d27f274..26843c9 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -382,7 +382,7 @@
 }
 
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
-    pdx::Message& message, size_t meta_size_bytes,
+    pdx::Message& message, const ProducerQueueConfig& producer_config,
     const UsagePolicy& usage_policy) {
   // Use the producer channel id as the global queue id.
   const int queue_id = message.GetChannelId();
@@ -396,11 +396,11 @@
     return ErrorStatus(EALREADY);
   }
 
-  auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+  auto status = ProducerQueueChannel::Create(this, queue_id, producer_config,
                                              usage_policy);
   if (status) {
     message.SetChannel(status.take());
-    return {{meta_size_bytes, queue_id}};
+    return {{producer_config, queue_id}};
   } else {
     ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
     return status.error_status();
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 3bc2635..b0df11f 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -166,9 +166,9 @@
                                              size_t meta_size_bytes);
   pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
                                           const std::string& name);
-  pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
-                                               size_t meta_size_bytes,
-                                               const UsagePolicy& usage_policy);
+  pdx::Status<QueueInfo> OnCreateProducerQueue(
+      pdx::Message& message, const ProducerQueueConfig& producer_config,
+      const UsagePolicy& usage_policy);
 
   BufferHubService(const BufferHubService&) = delete;
   void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 886e621..605b8fb 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -16,11 +16,11 @@
 
 ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
                                            int channel_id,
-                                           size_t meta_size_bytes,
+                                           const ProducerQueueConfig& config,
                                            const UsagePolicy& usage_policy,
                                            int* error)
     : BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
-      meta_size_bytes_(meta_size_bytes),
+      config_(config),
       usage_policy_(usage_policy),
       capacity_(0) {
   *error = 0;
@@ -35,8 +35,8 @@
 
 /* static */
 Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
-    BufferHubService* service, int channel_id, size_t meta_size_bytes,
-    const UsagePolicy& usage_policy) {
+    BufferHubService* service, int channel_id,
+    const ProducerQueueConfig& config, const UsagePolicy& usage_policy) {
   // Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
   // should be mutually exclusive.
   if ((usage_policy.usage_deny_set_mask & usage_policy.usage_deny_clear_mask)) {
@@ -50,7 +50,7 @@
 
   int error = 0;
   std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
-      service, channel_id, meta_size_bytes, usage_policy, &error));
+      service, channel_id, config, usage_policy, &error));
   if (error < 0)
     return ErrorStatus(-error);
   else
@@ -134,7 +134,7 @@
 }
 
 Status<QueueInfo> ProducerQueueChannel::OnGetQueueInfo(Message&) {
-  return {{meta_size_bytes_, buffer_id()}};
+  return {{config_, buffer_id()}};
 }
 
 Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
@@ -222,7 +222,7 @@
 
   auto producer_channel_status =
       ProducerChannel::Create(service(), buffer_id, width, height, layer_count,
-                              format, usage, meta_size_bytes_);
+                              format, usage, config_.meta_size_bytes);
   if (!producer_channel_status) {
     ALOGE(
         "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 28c74cd..212a90d 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -12,8 +12,8 @@
 class ProducerQueueChannel : public BufferHubChannel {
  public:
   static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
-      BufferHubService* service, int channel_id, size_t meta_size_bytes,
-      const UsagePolicy& usage_policy);
+      BufferHubService* service, int channel_id,
+      const ProducerQueueConfig& config, const UsagePolicy& usage_policy);
   ~ProducerQueueChannel() override;
 
   bool HandleMessage(pdx::Message& message) override;
@@ -48,8 +48,8 @@
 
  private:
   ProducerQueueChannel(BufferHubService* service, int channel_id,
-                       size_t meta_size_bytes, const UsagePolicy& usage_policy,
-                       int* error);
+                       const ProducerQueueConfig& config,
+                       const UsagePolicy& usage_policy, int* error);
 
   // Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
   // Note that the newly created buffer's file handle will be pushed to client
@@ -60,10 +60,9 @@
       pdx::Message& message, uint32_t width, uint32_t height,
       uint32_t layer_count, uint32_t format, uint64_t usage);
 
-  // Size of the meta data associated with all the buffers allocated from the
-  // queue. Now we assume the metadata size is immutable once the queue is
-  // created.
-  size_t meta_size_bytes_;
+  // The producer queue's configuration. Now we assume the configuration is
+  // immutable once the queue is created.
+  ProducerQueueConfig config_;
 
   // A set of variables to control what |usage| bits can this ProducerQueue
   // allocate.
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 5cb201d..9201520 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -7,6 +7,7 @@
   ],
 
   static_libs: [
+    "libbroadcastring",
     "libhwcomposer-client",
     "libdisplay",
     "libbufferhubqueue",
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index a19fcf1..3efc131 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 0
-define VERSION_PATCH 46
+define VERSION_PATCH 49
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -320,7 +320,7 @@
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
 
-// 119
+// 120
 @extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
 @extension("VK_KHR_get_surface_capabilities2") define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
 
@@ -409,7 +409,7 @@
     //@extension("VK_KHR_swapchain") // 2
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR                      = 1000111000,
 }
 
@@ -1005,9 +1005,6 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX  = 1000071002,
     VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX            = 1000071003,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX         = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX          = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX             = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX   = 1000071007,
 
     //@extension("VK_KHX_external_memory") // 73
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX    = 1000072000,
@@ -1086,10 +1083,10 @@
     //@extension("VK_EXT_hdr_metadata") // 106
     VK_STRUCTURE_TYPE_HDR_METADATA_EXT                          = 1000105000,
 
-    //@extension("VK_KHR_shared_presentable_image") // 111
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR   = 1000111000,
 
-    //@extension("VK_KHR_get_surface_capabilities2") // 119
+    //@extension("VK_KHR_get_surface_capabilities2") // 120
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR        = 1000119000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR                = 1000119001,
     VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR                      = 1000119002,
@@ -1179,6 +1176,55 @@
     VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT                  = 1000099000,
 }
 
+enum VkObjectType {
+    VK_OBJECT_TYPE_UNKNOWN                                  = 0,
+    VK_OBJECT_TYPE_INSTANCE                                 = 1,
+    VK_OBJECT_TYPE_PHYSICAL_DEVICE                          = 2,
+    VK_OBJECT_TYPE_DEVICE                                   = 3,
+    VK_OBJECT_TYPE_QUEUE                                    = 4,
+    VK_OBJECT_TYPE_SEMAPHORE                                = 5,
+    VK_OBJECT_TYPE_COMMAND_BUFFER                           = 6,
+    VK_OBJECT_TYPE_FENCE                                    = 7,
+    VK_OBJECT_TYPE_DEVICE_MEMORY                            = 8,
+    VK_OBJECT_TYPE_BUFFER                                   = 9,
+    VK_OBJECT_TYPE_IMAGE                                    = 10,
+    VK_OBJECT_TYPE_EVENT                                    = 11,
+    VK_OBJECT_TYPE_QUERY_POOL                               = 12,
+    VK_OBJECT_TYPE_BUFFER_VIEW                              = 13,
+    VK_OBJECT_TYPE_IMAGE_VIEW                               = 14,
+    VK_OBJECT_TYPE_SHADER_MODULE                            = 15,
+    VK_OBJECT_TYPE_PIPELINE_CACHE                           = 16,
+    VK_OBJECT_TYPE_PIPELINE_LAYOUT                          = 17,
+    VK_OBJECT_TYPE_RENDER_PASS                              = 18,
+    VK_OBJECT_TYPE_PIPELINE                                 = 19,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT                    = 20,
+    VK_OBJECT_TYPE_SAMPLER                                  = 21,
+    VK_OBJECT_TYPE_DESCRIPTOR_POOL                          = 22,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET                           = 23,
+    VK_OBJECT_TYPE_FRAMEBUFFER                              = 24,
+    VK_OBJECT_TYPE_COMMAND_POOL                             = 25,
+
+    //@extension("VK_KHR_surface") // 1
+    VK_OBJECT_TYPE_SURFACE_KHR                              = 1000000000,
+
+    //@extension("VK_KHR_swapchain") // 2
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR                            = 1000001000,
+
+    //@extension("VK_KHR_display") // 3
+    VK_OBJECT_TYPE_DISPLAY_KHR                              = 1000002000,
+    VK_OBJECT_TYPE_DISPLAY_MODE_KHR                         = 1000002001,
+
+    //@extension("VK_KHR_debug_report") // 12
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT                = 1000011000,
+
+    //@extension("VK_KHR_descriptor_update_template") // 86
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR           = 1000085000,
+
+    //@extension("VK_NVX_device_generated_commands") // 87
+    VK_OBJECT_TYPE_OBJECT_TABLE_NVX                         = 1000086000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX             = 1000086001,
+}
+
 @extension("VK_KHR_surface") // 1
 enum VkPresentModeKHR {
     VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
@@ -1186,7 +1232,7 @@
     VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
     VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
 
-    //@extension("VK_KHR_shared_presentable_image")
+    //@extension("VK_KHR_shared_presentable_image") // 112
     VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR               = 1000111000,
     VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR           = 1000111001,
 }
@@ -4261,28 +4307,28 @@
     f32                                             maxFrameAverageLightLevel
 }
 
-@extension("VK_KHR_shared_presentable_image") // 111
+@extension("VK_KHR_shared_presentable_image") // 112
 class VkSharedPresentSurfaceCapabilitiesKHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkImageUsageFlags                               sharedPresentSupportedUsageFlags
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkPhysicalDeviceSurfaceInfo2KHR {
     VkStructureType                                 sType
     const void*                                     pNext
     VkSurfaceKHR                                    surface
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkSurfaceCapabilities2KHR {
     VkStructureType                                 sType
     void*                                           pNext
     VkSurfaceCapabilitiesKHR                        surfaceCapabilities
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 class VkSurfaceFormat2KHR {
     VkStructureType                                 sType
     void*                                           pNext
@@ -7462,7 +7508,7 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR(
         VkPhysicalDevice                            physicalDevice,
         const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
@@ -7470,7 +7516,7 @@
     return ?
 }
 
-@extension("VK_KHR_get_surface_capabilities2") // 119
+@extension("VK_KHR_get_surface_capabilities2") // 120
 cmd VkResult vkGetPhysicalDeviceSurfaceFormats2KHR(
         VkPhysicalDevice                            physicalDevice,
         const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 67eba86..ee30913 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,11 +43,11 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 46
+#define VK_HEADER_VERSION 49
 
 
 #define VK_NULL_HANDLE 0
-
+        
 
 
 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
@@ -60,7 +60,7 @@
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
 #endif
 #endif
-
+        
 
 
 typedef uint32_t VkFlags;
@@ -261,9 +261,6 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX = 1000071002,
     VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX = 1000071003,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX = 1000071004,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX = 1000071005,
-    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX = 1000071006,
-    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX = 1000071007,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX = 1000072000,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX = 1000072001,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX = 1000072002,
@@ -901,6 +898,47 @@
     VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
 } VkSubpassContents;
 
+typedef enum VkObjectType {
+    VK_OBJECT_TYPE_UNKNOWN = 0,
+    VK_OBJECT_TYPE_INSTANCE = 1,
+    VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
+    VK_OBJECT_TYPE_DEVICE = 3,
+    VK_OBJECT_TYPE_QUEUE = 4,
+    VK_OBJECT_TYPE_SEMAPHORE = 5,
+    VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
+    VK_OBJECT_TYPE_FENCE = 7,
+    VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
+    VK_OBJECT_TYPE_BUFFER = 9,
+    VK_OBJECT_TYPE_IMAGE = 10,
+    VK_OBJECT_TYPE_EVENT = 11,
+    VK_OBJECT_TYPE_QUERY_POOL = 12,
+    VK_OBJECT_TYPE_BUFFER_VIEW = 13,
+    VK_OBJECT_TYPE_IMAGE_VIEW = 14,
+    VK_OBJECT_TYPE_SHADER_MODULE = 15,
+    VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
+    VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
+    VK_OBJECT_TYPE_RENDER_PASS = 18,
+    VK_OBJECT_TYPE_PIPELINE = 19,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
+    VK_OBJECT_TYPE_SAMPLER = 21,
+    VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
+    VK_OBJECT_TYPE_FRAMEBUFFER = 24,
+    VK_OBJECT_TYPE_COMMAND_POOL = 25,
+    VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
+    VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
+    VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
+    VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000,
+    VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
+    VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
+    VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
+    VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1),
+    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkObjectType;
+
 typedef VkFlags VkInstanceCreateFlags;
 
 typedef enum VkFormatFeatureFlagBits {
@@ -4107,6 +4145,64 @@
     const void*                                 pData);
 #endif
 
+#define VK_KHR_shared_presentable_image 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+
+typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
+    VkStructureType      sType;
+    void*                pNext;
+    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
+} VkSharedPresentSurfaceCapabilitiesKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain);
+#endif
+
+#define VK_KHR_get_surface_capabilities2 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
+
+typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkSurfaceKHR       surface;
+} VkPhysicalDeviceSurfaceInfo2KHR;
+
+typedef struct VkSurfaceCapabilities2KHR {
+    VkStructureType             sType;
+    void*                       pNext;
+    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
+} VkSurfaceCapabilities2KHR;
+
+typedef struct VkSurfaceFormat2KHR {
+    VkStructureType       sType;
+    void*                 pNext;
+    VkSurfaceFormatKHR    surfaceFormat;
+} VkSurfaceFormat2KHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
+    uint32_t*                                   pSurfaceFormatCount,
+    VkSurfaceFormat2KHR*                        pSurfaceFormats);
+#endif
+
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
@@ -5770,66 +5866,6 @@
     const VkHdrMetadataEXT*                     pMetadata);
 #endif
 
-#define VK_KHR_shared_presentable_image 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-typedef struct VkSharedPresentSurfaceCapabilitiesKHR {
-    VkStructureType      sType;
-    void*                pNext;
-    VkImageUsageFlags    sharedPresentSupportedUsageFlags;
-} VkSharedPresentSurfaceCapabilitiesKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
-    VkDevice                                    device,
-    VkSwapchainKHR                              swapchain);
-#endif
-
-#define VK_KHR_get_surface_capabilities2 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION 1
-#define VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME "VK_KHR_get_surface_capabilities2"
-
-typedef struct VkPhysicalDeviceSurfaceInfo2KHR {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkSurfaceKHR       surface;
-} VkPhysicalDeviceSurfaceInfo2KHR;
-
-typedef struct VkSurfaceCapabilities2KHR {
-    VkStructureType             sType;
-    void*                       pNext;
-    VkSurfaceCapabilitiesKHR    surfaceCapabilities;
-} VkSurfaceCapabilities2KHR;
-
-typedef struct VkSurfaceFormat2KHR {
-    VkStructureType       sType;
-    void*                 pNext;
-    VkSurfaceFormatKHR    surfaceFormat;
-} VkSurfaceFormat2KHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormats2KHR(
-    VkPhysicalDevice                            physicalDevice,
-    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
-    uint32_t*                                   pSurfaceFormatCount,
-    VkSurfaceFormat2KHR*                        pSurfaceFormats);
-#endif
-
-
-
 #ifdef VK_USE_PLATFORM_IOS_MVK
 #define VK_MVK_ios_surface 1
 #define VK_MVK_IOS_SURFACE_SPEC_VERSION   2