Remove the VR compositor from the framework.

Remove the VR compositor framework and enable out-of-process VR composition
in VrCore.

This CL seems large due to the ripple effect of changing the VrFlinger
API and protocol types. There are three major modules that require
concurrent changes:
  1. Protocol definitions and low-level VrFlinger API in libdisplay.
     * Additional changes needed to keep old interfaces working for
       a short time while replacing the dependent code (dvrGraphics*).
  2. VrFlinger service implementation changes to support VrCore compositor
     and the removal of the internal compositor.
  3. Changes to libdvr platform library API due to changes in #1 and #2.

Because of the nature of the interdependence of types and other defs it is
difficult to break this CL into smaller chunks. However, review of the three
major modules (libdisplay, libdvr, and libvrflinger) may be done separately
to ease the mental burden on reviewers.

Change Summary:
- Remove obsolete screenshot service. VR screenshots will be implemented
  by VrCore.
- Update display protocol definitions for changes in VrFlinger service
  requirements. The majority of the changes in libdisplay are a
  consequence of these protocol and service changes.
- Update VrFlinger to support two kinds of surfaces:
    1. Application - use by VR apps.
    2. Direct - used by VrCore (protected by permission check).
- Remove VrFlinger internal compositor and GL context.
- Remove obsolete debug console.
- Update VrFlinger hardware composer interface to handle direct
  surfaces only, removing the concept of GPU (compositor) layers.
- Update display manager to expose access to application surface info
  to VrCore (protected by permission check).
- Update libdvr platform library interfaces for changes to VrFlinger
  API / protocol.
- Clean up libdvr API struct setup using a common include.
- Add C++ header-only helpers for DVR platform library opaque types.

Bug: 36401174
Test: Build; run VrFlinger display test tool.
Change-Id: I15abfde5f72dbb3725a3f58621486afba6b64902
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index aa4513e..2375b5a 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -20,6 +20,7 @@
 
 LOCAL_CFLAGS += \
     -fvisibility=hidden \
+    -DLOG_TAG=\"libdvr\" \
     -D DVR_EXPORT='__attribute__ ((visibility ("default")))'
 
 LOCAL_C_INCLUDES := \
@@ -29,13 +30,13 @@
     $(LOCAL_PATH)/include \
 
 LOCAL_SRC_FILES := \
-    display_manager_client.cpp \
     dvr_api.cpp \
     dvr_buffer.cpp \
     dvr_buffer_queue.cpp \
+    dvr_display_manager.cpp \
     dvr_hardware_composer_client.cpp \
     dvr_surface.cpp \
-    vsync_client_api.cpp \
+    dvr_vsync.cpp \
 
 LOCAL_STATIC_LIBRARIES := \
     libbufferhub \
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
deleted file mode 100644
index 5bed815..0000000
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-#include "include/dvr/display_manager_client.h"
-
-#include <dvr/dvr_buffer.h>
-#include <grallocusage/GrallocUsageConversion.h>
-#include <private/android/AHardwareBufferHelpers.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_manager_client.h>
-
-using android::dvr::DisplaySurfaceAttributeEnum;
-
-extern "C" {
-
-struct DvrDisplayManagerClient {
-  DvrDisplayManagerClient()
-      : client(android::dvr::DisplayManagerClient::Create()) {}
-  ~DvrDisplayManagerClient() {}
-
-  std::unique_ptr<android::dvr::DisplayManagerClient> client;
-};
-
-struct DvrDisplayManagerClientSurfaceList {
-  DvrDisplayManagerClientSurfaceList(
-      std::vector<android::dvr::DisplaySurfaceInfo> surface_list)
-      : list(std::move(surface_list)) {}
-  ~DvrDisplayManagerClientSurfaceList() {}
-
-  std::vector<android::dvr::DisplaySurfaceInfo> list;
-};
-
-struct DvrDisplayManagerClientSurfaceBuffers {
-  DvrDisplayManagerClientSurfaceBuffers(
-      std::vector<std::unique_ptr<android::dvr::BufferConsumer>> buffer_list)
-      : list(std::move(buffer_list)) {}
-  ~DvrDisplayManagerClientSurfaceBuffers() {}
-
-  std::vector<std::unique_ptr<android::dvr::BufferConsumer>> list;
-};
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate() {
-  return new DvrDisplayManagerClient();
-}
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client) {
-  delete client;
-}
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
-                                             const char* name, size_t size,
-                                             uint64_t hardware_buffer_usage,
-                                             uint64_t unused) {
-  uint64_t producer_usage = 0;
-  uint64_t consumer_usage = 0;
-
-  // Note: AHardwareBuffer no longer uses usage0/usage1
-  uint64_t gralloc_usage =
-      android::AHardwareBuffer_convertToGrallocUsageBits(hardware_buffer_usage);
-
-  // Note: split producer/consumer usage is deprecated, grallocV2 uses single
-  // 64-bits usage
-  // And, currently, 64-bits gralloc usage flags can safely be truncated to
-  // 32-bits
-  android_convertGralloc0To1Usage((uint32_t)gralloc_usage, &producer_usage,
-                                  &consumer_usage);
-
-  auto ion_buffer = client->client->SetupNamedBuffer(
-      name, size, (producer_usage | consumer_usage));
-  if (ion_buffer) {
-    return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
-  }
-  return nullptr;
-}
-
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client) {
-  return client->client->event_fd();
-}
-
-int dvrDisplayManagerClientTranslateEpollEventMask(
-    DvrDisplayManagerClient* client, int in_events, int* out_events) {
-  auto result = client->client->GetChannel()->GetEventMask(in_events);
-
-  if (!result) {
-    return -EIO;
-  }
-
-  *out_events = result.get();
-
-  return 0;
-}
-
-int dvrDisplayManagerClientGetSurfaceList(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list) {
-  std::vector<android::dvr::DisplaySurfaceInfo> list;
-  int ret = client->client->GetSurfaceList(&list);
-  if (ret < 0)
-    return ret;
-
-  *surface_list = new DvrDisplayManagerClientSurfaceList(std::move(list));
-  return ret;
-}
-
-void dvrDisplayManagerClientSurfaceListDestroy(
-    DvrDisplayManagerClientSurfaceList* surface_list) {
-  delete surface_list;
-}
-
-size_t dvrDisplayManagerClientSurfaceListGetSize(
-    DvrDisplayManagerClientSurfaceList* surface_list) {
-  return surface_list->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].surface_id;
-}
-
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].ClientZOrder();
-}
-
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
-  return surface_list->list[index].IsClientVisible();
-}
-
-int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* /* client */, int /* surface_id */,
-    DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
-  // TODO(jwcai, hendrikw) Remove this after we replacing
-  // dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
-  return -1;
-}
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
-  delete surface_buffers;
-}
-
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
-  return surface_buffers->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index) {
-  return surface_buffers->list[index]->event_fd();
-}
-
-}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index c4634b1..4d7e1a6 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -1,13 +1,14 @@
 #include "include/dvr/dvr_api.h"
 
 #include <errno.h>
+#include <utils/Log.h>
 
 // Headers from libdvr
-#include <dvr/display_manager_client.h>
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
-#include <dvr/vsync_client_api.h>
+#include <dvr/dvr_vsync.h>
 
 // Headers not yet moved into libdvr.
 // TODO(jwcai) Move these once their callers are moved into Google3.
@@ -18,134 +19,28 @@
 extern "C" {
 
 DVR_EXPORT int dvrGetApi(void* api, size_t struct_size, int version) {
+  ALOGI("dvrGetApi: api=%p struct_size=%zu version=%d", api, struct_size,
+        version);
   if (version == 1) {
     if (struct_size != sizeof(DvrApi_v1)) {
+      ALOGE("dvrGetApi: Size mismatch: expected %zu; actual %zu",
+            sizeof(DvrApi_v1), struct_size);
       return -EINVAL;
     }
     DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
 
-    // display_manager_client.h
-    dvr_api->display_manager_client_create = dvrDisplayManagerClientCreate;
-    dvr_api->display_manager_client_destroy = dvrDisplayManagerClientDestroy;
-    dvr_api->display_manager_client_get_surface_list =
-        dvrDisplayManagerClientGetSurfaceList;
-    dvr_api->display_manager_client_surface_list_destroy =
-        dvrDisplayManagerClientSurfaceListDestroy;
-    dvr_api->display_manager_setup_named_buffer =
-        dvrDisplayManagerSetupNamedBuffer;
-    dvr_api->display_manager_client_surface_list_get_size =
-        dvrDisplayManagerClientSurfaceListGetSize;
-    dvr_api->display_manager_client_surface_list_get_surface_id =
-        dvrDisplayManagerClientSurfaceListGetSurfaceId;
-    dvr_api->display_manager_client_get_surface_buffer_list =
-        dvrDisplayManagerClientGetSurfaceBuffers;
-    dvr_api->display_manager_client_surface_buffer_list_destroy =
-        dvrDisplayManagerClientSurfaceBuffersDestroy;
-    dvr_api->display_manager_client_surface_buffer_list_get_size =
-        dvrDisplayManagerClientSurfaceBuffersGetSize;
-    dvr_api->display_manager_client_surface_buffer_list_get_fd =
-        dvrDisplayManagerClientSurfaceBuffersGetFd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) dvr_api->name = dvr##name
 
-    // dvr_buffer.h
-    dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
-    dvr_api->write_buffer_get_ahardwarebuffer =
-        dvrWriteBufferGetAHardwareBuffer;
-    dvr_api->write_buffer_post = dvrWriteBufferPost;
-    dvr_api->write_buffer_gain = dvrWriteBufferGain;
-    dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
-    dvr_api->write_buffer_get_native_handle = dvrWriteBufferGetNativeHandle;
+#include "include/dvr/dvr_api_entries.h"
 
-    dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
-    dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
-    dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
-    dvr_api->read_buffer_release = dvrReadBufferRelease;
-    dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
-    dvr_api->read_buffer_get_native_handle = dvrReadBufferGetNativeHandle;
-
-    dvr_api->buffer_destroy = dvrBufferDestroy;
-    dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
-    dvr_api->buffer_get_native_handle = dvrBufferGetNativeHandle;
-
-    // dvr_buffer_queue.h
-    dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
-    dvr_api->write_buffer_queue_get_capacity = dvrWriteBufferQueueGetCapacity;
-    dvr_api->write_buffer_queue_get_external_surface =
-        dvrWriteBufferQueueGetExternalSurface;
-    dvr_api->write_buffer_queue_create_read_queue =
-        dvrWriteBufferQueueCreateReadQueue;
-    dvr_api->write_buffer_queue_dequeue = dvrWriteBufferQueueDequeue;
-    dvr_api->read_buffer_queue_destroy = dvrReadBufferQueueDestroy;
-    dvr_api->read_buffer_queue_get_capacity = dvrReadBufferQueueGetCapacity;
-    dvr_api->read_buffer_queue_create_read_queue =
-        dvrReadBufferQueueCreateReadQueue;
-    dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
-
-    // dvr_surface.h
-    dvr_api->get_named_buffer = dvrGetNamedBuffer;
-    dvr_api->surface_create = dvrSurfaceCreate;
-    dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
-
-    // vsync_client_api.h
-    dvr_api->vsync_client_create = dvr_vsync_client_create;
-    dvr_api->vsync_client_destroy = dvr_vsync_client_destroy;
-    dvr_api->vsync_client_get_sched_info = dvr_vsync_client_get_sched_info;
-
-    // pose_client.h
-    dvr_api->pose_client_create = dvrPoseCreate;
-    dvr_api->pose_client_destroy = dvrPoseDestroy;
-    dvr_api->pose_get = dvrPoseGet;
-    dvr_api->pose_get_vsync_count = dvrPoseGetVsyncCount;
-    dvr_api->pose_get_controller = dvrPoseGetController;
-
-    // virtual_touchpad_client.h
-    dvr_api->virtual_touchpad_create = dvrVirtualTouchpadCreate;
-    dvr_api->virtual_touchpad_destroy = dvrVirtualTouchpadDestroy;
-    dvr_api->virtual_touchpad_attach = dvrVirtualTouchpadAttach;
-    dvr_api->virtual_touchpad_detach = dvrVirtualTouchpadDetach;
-    dvr_api->virtual_touchpad_touch = dvrVirtualTouchpadTouch;
-    dvr_api->virtual_touchpad_button_state = dvrVirtualTouchpadButtonState;
-
-    // dvr_hardware_composer_client.h
-    dvr_api->hwc_client_create = dvrHwcClientCreate;
-    dvr_api->hwc_client_destroy = dvrHwcClientDestroy;
-    dvr_api->hwc_frame_destroy = dvrHwcFrameDestroy;
-    dvr_api->hwc_frame_get_display_id = dvrHwcFrameGetDisplayId;
-    dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
-    dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
-    dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
-    dvr_api->hwc_frame_get_active_config = dvrHwcFrameGetActiveConfig;
-    dvr_api->hwc_frame_get_color_mode = dvrHwcFrameGetColorMode;
-    dvr_api->hwc_frame_get_color_transform = dvrHwcFrameGetColorTransform;
-    dvr_api->hwc_frame_get_power_mode = dvrHwcFrameGetPowerMode;
-    dvr_api->hwc_frame_get_vsync_enabled = dvrHwcFrameGetVsyncEnabled;
-    dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
-    dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
-    dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
-    dvr_api->hwc_frame_get_layer_fence = dvrHwcFrameGetLayerFence;
-    dvr_api->hwc_frame_get_layer_display_frame =
-        dvrHwcFrameGetLayerDisplayFrame;
-    dvr_api->hwc_frame_get_layer_crop = dvrHwcFrameGetLayerCrop;
-    dvr_api->hwc_frame_get_layer_blend_mode = dvrHwcFrameGetLayerBlendMode;
-    dvr_api->hwc_frame_get_layer_alpha = dvrHwcFrameGetLayerAlpha;
-    dvr_api->hwc_frame_get_layer_type = dvrHwcFrameGetLayerType;
-    dvr_api->hwc_frame_get_layer_application_id =
-        dvrHwcFrameGetLayerApplicationId;
-    dvr_api->hwc_frame_get_layer_z_order = dvrHwcFrameGetLayerZOrder;
-    dvr_api->hwc_frame_get_layer_cursor = dvrHwcFrameGetLayerCursor;
-    dvr_api->hwc_frame_get_layer_transform = dvrHwcFrameGetLayerTransform;
-    dvr_api->hwc_frame_get_layer_dataspace = dvrHwcFrameGetLayerDataspace;
-    dvr_api->hwc_frame_get_layer_color = dvrHwcFrameGetLayerColor;
-    dvr_api->hwc_frame_get_layer_num_visible_regions =
-        dvrHwcFrameGetLayerNumVisibleRegions;
-    dvr_api->hwc_frame_get_layer_visible_region =
-        dvrHwcFrameGetLayerVisibleRegion;
-    dvr_api->hwc_frame_get_layer_num_damaged_regions =
-        dvrHwcFrameGetLayerNumDamagedRegions;
-    dvr_api->hwc_frame_get_layer_damaged_region =
-        dvrHwcFrameGetLayerDamagedRegion;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
 
     return 0;
   }
+
+  ALOGE("dvrGetApi: Unknown API version=%d", version);
   return -EINVAL;
 }
 
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 28820e7..82469b8 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -4,37 +4,13 @@
 #include <private/dvr/buffer_hub_client.h>
 #include <ui/GraphicBuffer.h>
 
+#include "dvr_internal.h"
+
 using namespace android;
 
-struct DvrWriteBuffer {
-  std::shared_ptr<dvr::BufferProducer> write_buffer;
-};
-
-struct DvrReadBuffer {
-  std::shared_ptr<dvr::BufferConsumer> read_buffer;
-};
-
-struct DvrBuffer {
-  std::shared_ptr<dvr::IonBuffer> buffer;
-};
-
 namespace android {
 namespace dvr {
 
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
-  if (!buffer_producer)
-    return nullptr;
-  return new DvrWriteBuffer{std::move(buffer_producer)};
-}
-
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
-  if (!buffer_consumer)
-    return nullptr;
-  return new DvrReadBuffer{std::move(buffer_consumer)};
-}
-
 DvrBuffer* CreateDvrBufferFromIonBuffer(
     const std::shared_ptr<IonBuffer>& ion_buffer) {
   if (!ion_buffer)
@@ -47,14 +23,6 @@
 
 namespace {
 
-void InitializeGraphicBuffer(const dvr::BufferHubBuffer* buffer,
-                             sp<GraphicBuffer>* graphic_buffer) {
-  *graphic_buffer = sp<GraphicBuffer>(new GraphicBuffer(
-      buffer->width(), buffer->height(), buffer->format(), 1, /* layer count */
-      buffer->usage(), buffer->stride(), buffer->native_handle(),
-      false /* keep ownership */));
-}
-
 int ConvertToAHardwareBuffer(GraphicBuffer* graphic_buffer,
                              AHardwareBuffer** hardware_buffer) {
   if (!hardware_buffer || !graphic_buffer) {
@@ -69,28 +37,57 @@
 
 extern "C" {
 
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) {
+  if (write_buffer)
+    *write_buffer = new DvrWriteBuffer;
+}
+
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
   delete write_buffer;
 }
 
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
+  return write_buffer && write_buffer->write_buffer;
+}
+
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer)
+    return -EINVAL;
+
+  write_buffer->write_buffer = nullptr;
+  return 0;
+}
+
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return write_buffer->write_buffer->id();
 }
 
 int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return ConvertToAHardwareBuffer(
       write_buffer->write_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
 int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle fence(ready_fence_fd);
   int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
   return result;
 }
 
 int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
+  if (!write_buffer || !write_buffer->write_buffer || !release_fence_fd)
+    return -EINVAL;
+
   pdx::LocalHandle release_fence;
   int result = write_buffer->write_buffer->Gain(&release_fence);
   *release_fence_fd = release_fence.Release();
@@ -98,23 +95,52 @@
 }
 
 int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return -EINVAL;
+
   return write_buffer->write_buffer->GainAsync();
 }
 
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) {
+  if (read_buffer)
+    *read_buffer = new DvrReadBuffer;
+}
+
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
 
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
+  return read_buffer && read_buffer->read_buffer;
+}
+
+int dvrReadBufferClear(DvrReadBuffer* read_buffer) {
+  if (!read_buffer)
+    return -EINVAL;
+
+  read_buffer->read_buffer = nullptr;
+  return 0;
+}
+
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return read_buffer->read_buffer->id();
 }
 
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return ConvertToAHardwareBuffer(
       read_buffer->read_buffer->buffer()->buffer().get(), hardware_buffer);
 }
 
 int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
                          void* meta, size_t meta_size_bytes) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle ready_fence;
   int result =
       read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
@@ -123,12 +149,18 @@
 }
 
 int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   pdx::LocalHandle fence(release_fence_fd);
   int result = read_buffer->read_buffer->Release(fence);
   return result;
 }
 
 int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return -EINVAL;
+
   return read_buffer->read_buffer->ReleaseAsync();
 }
 
@@ -136,21 +168,34 @@
 
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer) {
+  if (!buffer || !buffer->buffer || !hardware_buffer) {
+    return -EINVAL;
+  }
+
   return ConvertToAHardwareBuffer(buffer->buffer->buffer().get(),
                                   hardware_buffer);
 }
 
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer) {
+  if (!write_buffer || !write_buffer->write_buffer)
+    return nullptr;
+
   return write_buffer->write_buffer->native_handle();
 }
 
 const struct native_handle* dvrReadBufferGetNativeHandle(
     DvrReadBuffer* read_buffer) {
+  if (!read_buffer || !read_buffer->read_buffer)
+    return nullptr;
+
   return read_buffer->read_buffer->native_handle();
 }
 
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer) {
+  if (!buffer || !buffer->buffer)
+    return nullptr;
+
   return buffer->buffer->handle();
 }
 
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 50c94cb..95c0e26 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -6,45 +6,77 @@
 #include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/buffer_hub_queue_producer.h>
 
+#include "dvr_internal.h"
+
 #define CHECK_PARAM(param)                                               \
   LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
                       __FUNCTION__)
 
 using namespace android;
 
+namespace android {
+namespace dvr {
+
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+    const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
+  return new DvrWriteBufferQueue{std::move(producer_queue)};
+}
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+    const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
+  return new DvrReadBufferQueue{std::move(consumer_queue)};
+}
+
+dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+    DvrWriteBufferQueue* write_queue) {
+  return write_queue->producer_queue.get();
+}
+
+}  // namespace dvr
+}  // namespace android
+
 extern "C" {
 
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
-  if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
-    ANativeWindow_release(write_queue->native_window_);
-  }
+  if (write_queue != nullptr && write_queue->native_window != nullptr)
+    ANativeWindow_release(write_queue->native_window);
+
   delete write_queue;
 }
 
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
-  CHECK_PARAM(write_queue);
-  return write_queue->producer_queue_->capacity();
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
+  if (!write_queue || !write_queue->producer_queue)
+    return -EINVAL;
+
+  return write_queue->producer_queue->capacity();
+}
+
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
+  if (!write_queue)
+    return -EINVAL;
+
+  return write_queue->producer_queue->id();
 }
 
 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
                                           ANativeWindow** out_window) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(out_window);
+  if (!write_queue || !out_window)
+    return -EINVAL;
 
-  if (write_queue->producer_queue_->metadata_size() !=
+  if (write_queue->producer_queue->metadata_size() !=
       sizeof(DvrNativeBufferMetadata)) {
     ALOGE(
-        "The size of buffer metadata (%u) of the write queue does not match of "
-        "size of DvrNativeBufferMetadata (%u).",
-        write_queue->producer_queue_->metadata_size(),
+        "The size of buffer metadata (%zu) of the write queue does not match "
+        "of size of DvrNativeBufferMetadata (%zu).",
+        write_queue->producer_queue->metadata_size(),
         sizeof(DvrNativeBufferMetadata));
     return -EINVAL;
   }
 
-  // Lazy creation of |native_window_|.
-  if (write_queue->native_window_ == nullptr) {
+  // Lazy creation of |native_window|.
+  if (write_queue->native_window == nullptr) {
     std::shared_ptr<dvr::BufferHubQueueCore> core =
-        dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+        dvr::BufferHubQueueCore::Create(write_queue->producer_queue);
     if (core == nullptr) {
       ALOGE(
           "dvrWriteBufferQueueGetExternalSurface: Failed to create native "
@@ -54,24 +86,23 @@
 
     sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
     sp<Surface> surface = new Surface(gbp, true);
-    write_queue->native_window_ = static_cast<ANativeWindow*>(surface.get());
-    ANativeWindow_acquire(write_queue->native_window_);
+    write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow_acquire(write_queue->native_window);
   }
 
-  *out_window = write_queue->native_window_;
+  *out_window = write_queue->native_window;
   return 0;
 }
 
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(write_queue->producer_queue_);
-  CHECK_PARAM(out_read_queue);
+  if (!write_queue || !write_queue->producer_queue || !out_read_queue)
+    return -EINVAL;
 
   auto read_queue = std::make_unique<DvrReadBufferQueue>();
-  read_queue->consumer_queue_ =
-      write_queue->producer_queue_->CreateConsumerQueue();
-  if (read_queue->consumer_queue_ == nullptr) {
+  read_queue->consumer_queue =
+      write_queue->producer_queue->CreateConsumerQueue();
+  if (read_queue->consumer_queue == nullptr) {
     ALOGE(
         "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
         "from DvrWriteBufferQueue[%p].",
@@ -84,23 +115,25 @@
 }
 
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                                  DvrWriteBuffer** out_buffer,
-                                  int* out_fence_fd) {
-  CHECK_PARAM(write_queue);
-  CHECK_PARAM(write_queue->producer_queue_);
-  CHECK_PARAM(out_buffer);
-  CHECK_PARAM(out_fence_fd);
+                               DvrWriteBuffer* write_buffer,
+                               int* out_fence_fd) {
+  if (!write_queue || !write_queue->producer_queue || !write_buffer ||
+      !out_fence_fd) {
+    return -EINVAL;
+  }
 
   size_t slot;
   pdx::LocalHandle release_fence;
-  std::shared_ptr<dvr::BufferProducer> buffer =
-      write_queue->producer_queue_->Dequeue(timeout, &slot, &release_fence);
-  if (buffer == nullptr) {
-    ALOGE("dvrWriteBufferQueueDequeue: Failed to dequeue buffer.");
-    return -ENOMEM;
+  auto buffer_status =
+      write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence);
+  if (!buffer_status) {
+    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+             "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s",
+             buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
   }
 
-  *out_buffer = CreateDvrWriteBufferFromBufferProducer(buffer);
+  write_buffer->write_buffer = buffer_status.take();
   *out_fence_fd = release_fence.Release();
   return 0;
 }
@@ -110,22 +143,29 @@
   delete read_queue;
 }
 
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
-  CHECK_PARAM(read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
 
-  return read_queue->consumer_queue_->capacity();
+  return read_queue->consumer_queue->capacity();
+}
+
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
+  if (!read_queue)
+    return -EINVAL;
+
+  return read_queue->consumer_queue->id();
 }
 
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue) {
-  CHECK_PARAM(read_queue);
-  CHECK_PARAM(read_queue->consumer_queue_);
-  CHECK_PARAM(out_read_queue);
+  if (!read_queue || !read_queue->consumer_queue || !out_read_queue)
+    return -EINVAL;
 
   auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
-  new_read_queue->consumer_queue_ =
-      read_queue->consumer_queue_->CreateConsumerQueue();
-  if (new_read_queue->consumer_queue_ == nullptr) {
+  new_read_queue->consumer_queue =
+      read_queue->consumer_queue->CreateConsumerQueue();
+  if (new_read_queue->consumer_queue == nullptr) {
     ALOGE(
         "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
         "from DvrReadBufferQueue[%p].",
@@ -138,34 +178,33 @@
 }
 
 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              DvrReadBuffer* read_buffer, int* out_fence_fd,
                               void* out_meta, size_t meta_size_bytes) {
-  CHECK_PARAM(read_queue);
-  CHECK_PARAM(read_queue->consumer_queue_);
-  CHECK_PARAM(out_buffer);
-  CHECK_PARAM(out_fence_fd);
-  CHECK_PARAM(out_meta);
+  if (!read_queue || !read_queue->consumer_queue || !read_buffer ||
+      !out_fence_fd || !out_meta) {
+    return -EINVAL;
+  }
 
-  if (meta_size_bytes != read_queue->consumer_queue_->metadata_size()) {
+  if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) {
     ALOGE(
         "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
         "but actual (%zu).",
-        read_queue->consumer_queue_->metadata_size(), meta_size_bytes);
+        read_queue->consumer_queue->metadata_size(), meta_size_bytes);
     return -EINVAL;
   }
 
   size_t slot;
   pdx::LocalHandle acquire_fence;
-  std::shared_ptr<dvr::BufferConsumer> buffer =
-      read_queue->consumer_queue_->Dequeue(timeout, &slot, out_meta,
-                                           meta_size_bytes, &acquire_fence);
-
-  if (buffer == nullptr) {
-    ALOGE("dvrReadBufferQueueGainBuffer: Failed to dequeue buffer.");
-    return -ENOMEM;
+  auto buffer_status = read_queue->consumer_queue->Dequeue(
+      timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
+  if (!buffer_status) {
+    ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+             "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
+             buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
   }
 
-  *out_buffer = CreateDvrReadBufferFromBufferConsumer(buffer);
+  read_buffer->read_buffer = buffer_status.take();
   *out_fence_fd = acquire_fence.Release();
   return 0;
 }
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
new file mode 100644
index 0000000..87636ec
--- /dev/null
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -0,0 +1,304 @@
+#include "include/dvr/dvr_display_manager.h"
+
+#include <dvr/dvr_buffer.h>
+#include <pdx/rpc/variant.h>
+#include <private/android/AHardwareBufferHelpers.h>
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_manager_client.h>
+
+#include "dvr_internal.h"
+
+using android::AHardwareBuffer_convertToGrallocUsageBits;
+using android::dvr::BufferConsumer;
+using android::dvr::display::DisplayManagerClient;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceState;
+using android::dvr::CreateDvrReadBufferQueueFromConsumerQueue;
+using android::pdx::rpc::EmptyVariant;
+
+namespace {
+
+// Extracts type and value from the attribute Variant and writes them into the
+// respective fields of DvrSurfaceAttribute.
+struct AttributeVisitor {
+  DvrSurfaceAttribute* attribute;
+
+  void operator()(int32_t value) {
+    attribute->value.int32_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+  }
+  void operator()(int64_t value) {
+    attribute->value.int64_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
+  }
+  void operator()(bool value) {
+    attribute->value.bool_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+  }
+  void operator()(float value) {
+    attribute->value.float_value = value;
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
+  }
+  void operator()(const std::array<float, 2>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float2_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
+  }
+  void operator()(const std::array<float, 3>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float3_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
+  }
+  void operator()(const std::array<float, 4>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float4_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
+  }
+  void operator()(const std::array<float, 8>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float8_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
+  }
+  void operator()(const std::array<float, 16>& value) {
+    std::copy(value.cbegin(), value.cend(), attribute->value.float16_value);
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
+  }
+  void operator()(EmptyVariant) {
+    attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
+  }
+};
+
+size_t ConvertSurfaceAttributes(const SurfaceAttributes& surface_attributes,
+                                DvrSurfaceAttribute* attributes,
+                                size_t max_count) {
+  size_t count = 0;
+  for (const auto& attribute : surface_attributes) {
+    if (count >= max_count)
+      break;
+
+    // Copy the key and extract the Variant value using a visitor.
+    attributes[count].key = attribute.first;
+    attribute.second.Visit(AttributeVisitor{&attributes[count]});
+    count++;
+  }
+
+  return count;
+}
+
+}  // anonymous namespace
+
+extern "C" {
+
+struct DvrDisplayManager {
+  std::unique_ptr<DisplayManagerClient> client;
+};
+
+struct DvrSurfaceState {
+  std::vector<SurfaceState> state;
+};
+
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out) {
+  if (!client_out)
+    return -EINVAL;
+
+  auto client = DisplayManagerClient::Create();
+  if (!client) {
+    ALOGE("dvrDisplayManagerCreate: Failed to create display manager client!");
+    return -EIO;
+  }
+
+  *client_out = new DvrDisplayManager{std::move(client)};
+  return 0;
+}
+
+void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
+
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+                                      const char* name, size_t size,
+                                      uint64_t usage, DvrBuffer** buffer_out) {
+  if (!client || !name || !buffer_out)
+    return -EINVAL;
+
+  uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
+
+  auto buffer_status =
+      client->client->SetupNamedBuffer(name, size, gralloc_usage);
+  if (!buffer_status) {
+    ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
+          buffer_status.GetErrorMessage().c_str());
+    return -buffer_status.error();
+  }
+
+  *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
+  return 0;
+}
+
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
+  if (!client)
+    return -EINVAL;
+
+  return client->client->event_fd();
+}
+
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+                                             int in_events, int* out_events) {
+  if (!client || !out_events)
+    return -EINVAL;
+
+  auto status = client->client->GetEventMask(in_events);
+  if (!status)
+    return -status.error();
+
+  *out_events = status.get();
+  return 0;
+}
+
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+                                     DvrSurfaceState* state) {
+  if (!client || !state)
+    return -EINVAL;
+
+  auto status = client->client->GetSurfaceState();
+  if (!status)
+    return -status.error();
+
+  state->state = status.take();
+  return 0;
+}
+
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+                                        int surface_id, int queue_id,
+                                        DvrReadBufferQueue** queue_out) {
+  if (!client || !queue_out)
+    return -EINVAL;
+
+  auto status = client->client->GetSurfaceQueue(surface_id, queue_id);
+  if (!status) {
+    ALOGE("dvrDisplayManagerGetReadBufferQueue: Failed to get queue: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
+
+  *queue_out = CreateDvrReadBufferQueueFromConsumerQueue(status.take());
+  return 0;
+}
+
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state_out) {
+  if (!surface_state_out)
+    return -EINVAL;
+
+  *surface_state_out = new DvrSurfaceState{};
+  return 0;
+}
+
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state) {
+  delete surface_state;
+}
+
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+                                   size_t* count_out) {
+  if (!surface_state)
+    return -EINVAL;
+
+  *count_out = surface_state->state.size();
+  return 0;
+}
+
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+                                  size_t surface_index,
+                                  DvrSurfaceUpdateFlags* flags_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *flags_out = surface_state->state[surface_index].update_flags;
+  return 0;
+}
+
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* surface_id_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *surface_id_out = surface_state->state[surface_index].surface_id;
+  return 0;
+}
+
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* process_id_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *process_id_out = surface_state->state[surface_index].process_id;
+  return 0;
+}
+
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+                                 size_t surface_index, size_t* count_out) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  *count_out = surface_state->state[surface_index].queue_ids.size();
+  return 0;
+}
+
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+                                   size_t surface_index, int* queue_ids,
+                                   size_t max_count) {
+  if (!surface_state || surface_index >= surface_state->state.size())
+    return -EINVAL;
+
+  size_t i;
+  const auto& state = surface_state->state[surface_index];
+  for (i = 0; i < std::min(max_count, state.queue_ids.size()); i++) {
+    queue_ids[i] = state.queue_ids[i];
+  }
+
+  return i;
+}
+
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+                             size_t surface_index, int* z_order_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !z_order_out) {
+    return -EINVAL;
+  }
+
+  *z_order_out = surface_state->state[surface_index].GetZOrder();
+  return 0;
+}
+
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+                              size_t surface_index, bool* visible_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !visible_out) {
+    return -EINVAL;
+  }
+
+  *visible_out = surface_state->state[surface_index].GetVisible();
+  return 0;
+}
+
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+                                     size_t surface_index, size_t* count_out) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !count_out) {
+    return -EINVAL;
+  }
+
+  *count_out = surface_state->state[surface_index].surface_attributes.size();
+  return 0;
+}
+
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+                                     size_t surface_index,
+                                     DvrSurfaceAttribute* attributes,
+                                     size_t max_count) {
+  if (!surface_state || surface_index >= surface_state->state.size() ||
+      !attributes) {
+    return -EINVAL;
+  }
+
+  return ConvertSurfaceAttributes(
+      surface_state->state[surface_index].surface_attributes, attributes,
+      max_count);
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
new file mode 100644
index 0000000..89bef09
--- /dev/null
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -0,0 +1,70 @@
+#ifndef ANDROID_DVR_INTERNAL_H_
+#define ANDROID_DVR_INTERNAL_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+extern "C" {
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+}  // extern "C"
+
+namespace android {
+namespace dvr {
+
+class BufferProducer;
+class BufferConsumer;
+class ConsumerQueue;
+class IonBuffer;
+class ProducerQueue;
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+    const std::shared_ptr<IonBuffer>& ion_buffer);
+
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+    const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+    const std::shared_ptr<BufferProducer>& buffer_producer);
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue);
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+    const std::shared_ptr<ProducerQueue>& producer_queue);
+ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+    DvrWriteBufferQueue* write_queue);
+
+}  // namespace dvr
+}  // namespace android
+
+extern "C" {
+
+struct DvrWriteBuffer {
+  std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+};
+
+struct DvrReadBuffer {
+  std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+  std::shared_ptr<android::dvr::IonBuffer> buffer;
+};
+
+struct DvrWriteBufferQueue {
+  std::shared_ptr<android::dvr::ProducerQueue> producer_queue;
+  ANativeWindow* native_window{nullptr};
+};
+
+struct DvrReadBufferQueue {
+  std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue;
+};
+
+}  // extern "C"
+
+#endif  // ANDROID_DVR_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a04ed50..b70f726 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -1,65 +1,162 @@
 #include "include/dvr/dvr_surface.h"
 
+#include <inttypes.h>
+
 #include <private/dvr/display_client.h>
 
-using namespace android;
+#include "dvr_internal.h"
 
-struct DvrSurface {
-  std::unique_ptr<dvr::DisplaySurfaceClient> display_surface_;
-};
+using android::dvr::display::DisplayClient;
+using android::dvr::display::Surface;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttributeValue;
+using android::dvr::CreateDvrReadBufferFromBufferConsumer;
+using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue;
+
+namespace {
+
+bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
+                              size_t attribute_count,
+                              SurfaceAttributes* surface_attributes,
+                              size_t* error_index) {
+  for (size_t i = 0; i < attribute_count; i++) {
+    SurfaceAttributeValue value;
+    switch (attributes[i].value.type) {
+      case DVR_SURFACE_ATTRIBUTE_TYPE_INT32:
+        value = attributes[i].value.int32_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_INT64:
+        value = attributes[i].value.int64_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
+        value = attributes[i].value.bool_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
+        value = attributes[i].value.float_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
+        value = attributes[i].value.float2_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
+        value = attributes[i].value.float3_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
+        value = attributes[i].value.float4_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
+        value = attributes[i].value.float8_value;
+        break;
+      case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
+        value = attributes[i].value.float16_value;
+        break;
+      default:
+        *error_index = i;
+        return false;
+    }
+
+    surface_attributes->emplace(attributes[i].key, value);
+  }
+
+  return true;
+}
+
+}  // anonymous namespace
 
 extern "C" {
 
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
-                     uint64_t usage1, int flags, DvrSurface** out_surface) {
+struct DvrSurface {
+  std::unique_ptr<Surface> surface;
+};
+
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+                     size_t attribute_count, DvrSurface** out_surface) {
   if (out_surface == nullptr) {
-    ALOGE("dvrSurfaceCreate: invalid inputs: out_surface=%p.", out_surface);
+    ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
     return -EINVAL;
   }
 
-  int error;
-  auto client = dvr::DisplayClient::Create(&error);
-  if (!client) {
-    ALOGE("Failed to create display client!");
-    return error;
+  size_t error_index;
+  SurfaceAttributes surface_attributes;
+  if (!ConvertSurfaceAttributes(attributes, attribute_count,
+                                &surface_attributes, &error_index)) {
+    ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64,
+          attributes[error_index].value.type);
+    return -EINVAL;
   }
 
-  // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
-  std::unique_ptr<dvr::DisplaySurfaceClient> surface =
-      client->CreateDisplaySurface(
-          width, height, static_cast<int>(usage0 | usage1), format, flags);
+  auto status = Surface::CreateSurface(surface_attributes);
+  if (!status) {
+    ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
 
-  DvrSurface* dvr_surface = new DvrSurface;
-  dvr_surface->display_surface_ = std::move(surface);
-  *out_surface = dvr_surface;
+  *out_surface = new DvrSurface{status.take()};
   return 0;
 }
 
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
-                                  DvrWriteBufferQueue** out_writer) {
+void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
+
+int dvrSurfaceGetId(DvrSurface* surface) {
+  return surface->surface->surface_id();
+}
+
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+                            const DvrSurfaceAttribute* attributes,
+                            size_t attribute_count) {
+  if (surface == nullptr || attributes == nullptr) {
+    ALOGE(
+        "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p "
+        "attribute_count=%zu",
+        surface, attributes, attribute_count);
+    return -EINVAL;
+  }
+
+  size_t error_index;
+  SurfaceAttributes surface_attributes;
+  if (!ConvertSurfaceAttributes(attributes, attribute_count,
+                                &surface_attributes, &error_index)) {
+    ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64,
+          attributes[error_index].value.type);
+    return -EINVAL;
+  }
+
+  auto status = surface->surface->SetAttributes(surface_attributes);
+  if (!status) {
+    ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
+  }
+
+  return 0;
+}
+
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint64_t usage, size_t capacity,
+                                     DvrWriteBufferQueue** out_writer) {
   if (surface == nullptr || out_writer == nullptr) {
     ALOGE(
-        "dvrSurfaceGetWriteBufferQueue: Invalid inputs: surface=%p, "
+        "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
         "out_writer=%p.",
         surface, out_writer);
     return -EINVAL;
   }
-  DvrWriteBufferQueue* buffer_writer = new DvrWriteBufferQueue;
-  buffer_writer->producer_queue_ =
-      surface->display_surface_->GetProducerQueue();
-  if (buffer_writer->producer_queue_ == nullptr) {
-    ALOGE(
-        "dvrSurfaceGetWriteBufferQueue: Failed to get producer queue from "
-        "display surface.");
-    return -ENOMEM;
+
+  auto status =
+      surface->surface->CreateQueue(width, height, format, usage, capacity);
+  if (!status) {
+    ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
+          status.GetErrorMessage().c_str());
+    return -status.error();
   }
 
-  *out_writer = buffer_writer;
+  *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take());
   return 0;
 }
 
 int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
-  auto client = android::dvr::DisplayClient::Create();
+  auto client = DisplayClient::Create();
   if (!client) {
     ALOGE("dvrGetNamedBuffer: Failed to create display client!");
     return -ECOMM;
@@ -71,12 +168,13 @@
     return -EINVAL;
   }
 
-  auto named_buffer = client->GetNamedBuffer(name);
-  if (!named_buffer) {
-    ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
-    return -EINVAL;
+  auto status = client->GetNamedBuffer(name);
+  if (!status) {
+    ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
+          status.GetErrorMessage().c_str());
+    return -status.error();
   }
-  *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
+  *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
   return 0;
 }
 
diff --git a/libs/vr/libdvr/dvr_vsync.cpp b/libs/vr/libdvr/dvr_vsync.cpp
new file mode 100644
index 0000000..099240e
--- /dev/null
+++ b/libs/vr/libdvr/dvr_vsync.cpp
@@ -0,0 +1,33 @@
+#include "include/dvr/dvr_vsync.h"
+
+#include <utils/Log.h>
+
+#include <private/dvr/vsync_client.h>
+
+extern "C" {
+
+struct DvrVSyncClient {
+  std::unique_ptr<android::dvr::VSyncClient> client;
+};
+
+int dvrVSyncClientCreate(DvrVSyncClient** client_out) {
+  auto client = android::dvr::VSyncClient::Create();
+  if (!client) {
+    ALOGE("dvrVSyncClientCreate: Failed to create vsync client!");
+    return -EIO;
+  }
+
+  *client_out = new DvrVSyncClient{std::move(client)};
+  return 0;
+}
+
+void dvrVSyncClientDestroy(DvrVSyncClient* client) { delete client; }
+
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+                               int64_t* next_timestamp_ns,
+                               uint32_t* next_vsync_count) {
+  return client->client->GetSchedInfo(vsync_period_ns, next_timestamp_ns,
+                                      next_vsync_count);
+}
+
+}  // extern "C"
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
deleted file mode 100644
index 8cd948c..0000000
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
-#define DVR_DISPLAY_MANAGER_CLIENT_H_
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
-    DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
-    DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrBuffer DvrBuffer;
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
-                                             const char* name, size_t size,
-                                             uint64_t usage0, uint64_t usage1);
-
-// Return an event fd for checking if there was an event on the server
-// Note that the only event which will be flagged is POLLIN. You must use
-// dvrDisplayManagerClientTranslateEpollEventMask in order to get the real
-// event flags.
-// @return the fd
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client);
-
-// Once you have received an epoll event, you must translate it to its true
-// flags. This is a workaround for working with UDS.
-// @param in_events pass in the epoll revents that were initially returned
-// @param on success, this value will be overwritten with the true epoll values
-// @return 0 on success, non-zero otherwise
-int dvrDisplayManagerClientTranslateEpollEventMask(
-    DvrDisplayManagerClient* client, int in_events, int* out_events);
-
-// If successful, populates |surface_list| with a list of application
-// surfaces the display is currently using.
-//
-// @return 0 on success. Otherwise it returns a negative error value.
-int dvrDisplayManagerClientGetSurfaceList(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list);
-
-void dvrDisplayManagerClientSurfaceListDestroy(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Returns the number of surfaces in the list.
-size_t dvrDisplayManagerClientSurfaceListGetSize(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Return a unique identifier for a client surface. The identifier can
-// be used to query for other surface properties.
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns the stacking order of the client surface at |index|.
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns true if the client surface is visible, false otherwise.
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// TODO(jwcai, hendrikw) Remove this after we replacing
-// dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
-int dvrDisplayManagerClientGetSurfaceBuffers(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the number of buffers.
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the file descriptor for the buffer consumer at |index|.
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 3cd401d..7124bee 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -4,137 +4,177 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
 
 #include <dvr/dvr_hardware_composer_defs.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct ANativeWindow ANativeWindow;
 
 typedef struct DvrPoseAsync DvrPoseAsync;
 
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
-    DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
-    DvrDisplayManagerClientSurfaceBuffers;
+typedef uint64_t DvrSurfaceUpdateFlags;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
 typedef struct DvrPose DvrPose;
-typedef struct dvr_vsync_client dvr_vsync_client;
+typedef struct DvrVSyncClient DvrVSyncClient;
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
-typedef DvrDisplayManagerClient* (*DvrDisplayManagerClientCreatePtr)(void);
-typedef void (*DvrDisplayManagerClientDestroyPtr)(
-    DvrDisplayManagerClient* client);
-
+typedef struct DvrBuffer DvrBuffer;
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
-typedef struct DvrBuffer DvrBuffer;
 typedef struct AHardwareBuffer AHardwareBuffer;
 
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 
 typedef struct DvrSurface DvrSurface;
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
+typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
 
 struct native_handle;
 
-// display_manager_client.h
-typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
-    DvrDisplayManagerClient* client,
-    DvrDisplayManagerClientSurfaceList** surface_list);
-typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
-    DvrDisplayManagerClient* client, const char* name, size_t size,
-    uint64_t usage0, uint64_t usage1);
-typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list);
-typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
-    DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-typedef int (*DvrDisplayManagerClientGetSurfaceBufferListPtr)(
-    DvrDisplayManagerClient* client, int surface_id,
-    DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-typedef void (*DvrDisplayManagerClientSurfaceBufferListDestroyPtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef size_t (*DvrDisplayManagerClientSurfaceBufferListGetSizePtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef int (*DvrDisplayManagerClientSurfaceBufferListGetFdPtr)(
-    DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
+// dvr_display_manager.h
+typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
+typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
+                                                    const char* name,
+                                                    size_t size, uint64_t usage,
+                                                    DvrBuffer** buffer_out);
+typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
+    DvrDisplayManager* client, int in_events, int* out_events);
+typedef int (*DvrDisplayManagerGetSurfaceStatePtr)(
+    DvrDisplayManager* client, DvrSurfaceState* surface_state);
+typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
+    DvrDisplayManager* client, int surface_id, int queue_id,
+    DvrReadBufferQueue** queue_out);
+typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
+typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
+typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
+                                                 size_t* count_out);
+typedef int (*DvrSurfaceStateGetUpdateFlagsPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index,
+    DvrSurfaceUpdateFlags* flags_out);
+typedef int (*DvrSurfaceStateGetSurfaceIdPtr)(DvrSurfaceState* surface_state,
+                                              size_t surface_index,
+                                              int* surface_id_out);
+typedef int (*DvrSurfaceStateGetProcessIdPtr)(DvrSurfaceState* surface_state,
+                                              size_t surface_index,
+                                              int* process_id_out);
+typedef int (*DvrSurfaceStateGetQueueCountPtr)(DvrSurfaceState* surface_state,
+                                               size_t surface_index,
+                                               size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetQueueIdsPtr)(DvrSurfaceState* surface_state,
+                                                 size_t surface_index,
+                                                 int* queue_ids,
+                                                 size_t max_count);
+typedef int (*DvrSurfaceStateGetZOrderPtr)(DvrSurfaceState* surface_state,
+                                           size_t surface_index,
+                                           int* z_order_out);
+typedef int (*DvrSurfaceStateGetVisiblePtr)(DvrSurfaceState* surface_state,
+                                            size_t surface_index,
+                                            bool* visible_out);
+typedef int (*DvrSurfaceStateGetAttributeCountPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index, size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetAttributesPtr)(
+    DvrSurfaceState* surface_state, size_t surface_index,
+    DvrSurfaceAttribute* attributes, size_t max_attribute_count);
 
 // dvr_buffer.h
-typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
+typedef void (*DvrWriteBufferCreateEmptyPtr)(DvrWriteBuffer** write_buffer_out);
+typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferIsValidPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferClearPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferGetIdPtr)(DvrWriteBuffer* write_buffer);
 typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
-    DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
-                                     const void* meta, size_t meta_size_bytes);
-typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* client,
+    DvrWriteBuffer* write_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* write_buffer,
+                                     int ready_fence_fd, const void* meta,
+                                     size_t meta_size_bytes);
+typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* write_buffer,
                                      int* release_fence_fd);
-typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
-typedef const struct native_handle* (*DvrWriteBufferGetNativeHandle)(
+typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* write_buffer);
+typedef const struct native_handle* (*DvrWriteBufferGetNativeHandlePtr)(
     DvrWriteBuffer* write_buffer);
 
-typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
+typedef void (*DvrReadBufferCreateEmptyPtr)(DvrReadBuffer** read_buffer_out);
+typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferIsValidPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferClearPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferGetIdPtr)(DvrReadBuffer* read_buffer);
 typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
-    DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
+    DvrReadBuffer* read_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* read_buffer,
                                        int* ready_fence_fd, void* meta,
                                        size_t meta_size_bytes);
-typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
+typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* read_buffer,
                                        int release_fence_fd);
-typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
-typedef const struct native_handle* (*DvrReadBufferGetNativeHandle)(
+typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* read_buffer);
+typedef const struct native_handle* (*DvrReadBufferGetNativeHandlePtr)(
     DvrReadBuffer* read_buffer);
 
-typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
-typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
-                                           AHardwareBuffer** hardware_buffer);
-typedef const struct native_handle* (*DvrBufferGetNativeHandle)(
+typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBufferPtr)(
+    DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
     DvrBuffer* buffer);
 
 // dvr_buffer_queue.h
 typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
-typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)(
     DvrWriteBufferQueue* write_queue);
+typedef int (*DvrWriteBufferQueueGetIdPtr)(DvrWriteBufferQueue* write_queue);
 typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
     DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
 typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
     DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
                                              int timeout,
-                                             DvrWriteBuffer** out_buffer,
+                                             DvrWriteBuffer* out_buffer,
                                              int* out_fence_fd);
 typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
-typedef size_t (*DvrReadBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrReadBufferQueueGetCapacityPtr)(
     DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueGetIdPtr)(DvrReadBufferQueue* read_queue);
 typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
     DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
 typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
                                             int timeout,
-                                            DvrReadBuffer** out_buffer,
+                                            DvrReadBuffer* out_buffer,
                                             int* out_fence_fd, void* out_meta,
                                             size_t meta_size_bytes);
 
 // dvr_surface.h
 typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
-typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
-                                   uint64_t usage0, uint64_t usage1, int flags,
-                                   DvrSurface** out_surface);
-typedef int (*DvrSurfaceGetWriteBufferQueuePtr)(
-    DvrSurface* surface, DvrWriteBufferQueue** out_writer);
+typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
+                                   size_t attribute_count,
+                                   DvrSurface** surface_out);
+typedef void (*DvrSurfaceDestroyPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceGetIdPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceSetAttributesPtr)(DvrSurface* surface,
+                                          const DvrSurfaceAttribute* attributes,
+                                          size_t attribute_count);
+typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
+    DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
+    uint64_t usage, size_t capacity, DvrWriteBufferQueue** queue_out);
 
 // vsync_client_api.h
-typedef dvr_vsync_client* (*DvrVSyncClientCreatePtr)();
-typedef void (*DvrVSyncClientDestroyPtr)(dvr_vsync_client* client);
-typedef int (*DvrVSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
+typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
+typedef void (*DvrVSyncClientDestroyPtr)(DvrVSyncClient* client);
+typedef int (*DvrVSyncClientGetSchedInfoPtr)(DvrVSyncClient* client,
                                              int64_t* vsync_period_ns,
                                              int64_t* next_timestamp_ns,
                                              uint32_t* next_vsync_count);
 
 // pose_client.h
-typedef DvrPose* (*DvrPoseClientCreatePtr)(void);
-typedef void (*DvrPoseClientDestroyPtr)(DvrPose* client);
+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);
@@ -226,8 +266,8 @@
 // reorder existing data members. If new fields need to be added, please take
 // extra care to make sure that new data field is padded properly the size of
 // the struct stays same.
-// TODO(b/37578558) Move |dvr_api.h| into a header library so that this structure
-// won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
+// TODO(b/37578558) Move |dvr_api.h| into a header library so that this
+// structure won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
 struct DvrNativeBufferMetadata {
   // Timestamp of the frame.
   int64_t timestamp;
@@ -257,127 +297,18 @@
 };
 
 struct DvrApi_v1 {
-  // Display manager client
-  DvrDisplayManagerClientCreatePtr display_manager_client_create;
-  DvrDisplayManagerClientDestroyPtr display_manager_client_destroy;
-  DvrDisplayManagerClientGetSurfaceListPtr
-      display_manager_client_get_surface_list;
-  DvrDisplayManagerClientSurfaceListDestroyPtr
-      display_manager_client_surface_list_destroy;
-  DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
-  DvrDisplayManagerClientSurfaceListGetSizePtr
-      display_manager_client_surface_list_get_size;
-  DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
-      display_manager_client_surface_list_get_surface_id;
-  DvrDisplayManagerClientGetSurfaceBufferListPtr
-      display_manager_client_get_surface_buffer_list;
-  DvrDisplayManagerClientSurfaceBufferListDestroyPtr
-      display_manager_client_surface_buffer_list_destroy;
-  DvrDisplayManagerClientSurfaceBufferListGetSizePtr
-      display_manager_client_surface_buffer_list_get_size;
-  DvrDisplayManagerClientSurfaceBufferListGetFdPtr
-      display_manager_client_surface_buffer_list_get_fd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
 
-  // Write buffer
-  DvrWriteBufferDestroyPtr write_buffer_destroy;
-  DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
-  DvrWriteBufferPostPtr write_buffer_post;
-  DvrWriteBufferGainPtr write_buffer_gain;
-  DvrWriteBufferGainAsyncPtr write_buffer_gain_async;
-  DvrWriteBufferGetNativeHandle write_buffer_get_native_handle;
+// Include file with API entries.
+#include "dvr_api_entries.h"
 
-  // Read buffer
-  DvrReadBufferDestroyPtr read_buffer_destroy;
-  DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
-  DvrReadBufferAcquirePtr read_buffer_acquire;
-  DvrReadBufferReleasePtr read_buffer_release;
-  DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
-  DvrReadBufferGetNativeHandle read_buffer_get_native_handle;
-
-  // Buffer
-  DvrBufferDestroy buffer_destroy;
-  DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
-  DvrBufferGetNativeHandle buffer_get_native_handle;
-
-  // Write buffer queue
-  DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
-  DvrWriteBufferQueueGetCapacityPtr write_buffer_queue_get_capacity;
-  DvrWriteBufferQueueGetExternalSurfacePtr
-      write_buffer_queue_get_external_surface;
-  DvrWriteBufferQueueCreateReadQueuePtr write_buffer_queue_create_read_queue;
-  DvrWriteBufferQueueDequeuePtr write_buffer_queue_dequeue;
-
-  // Read buffer queue
-  DvrReadBufferQueueDestroyPtr read_buffer_queue_destroy;
-  DvrReadBufferQueueGetCapacityPtr read_buffer_queue_get_capacity;
-  DvrReadBufferQueueCreateReadQueuePtr read_buffer_queue_create_read_queue;
-  DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
-
-  // V-Sync client
-  DvrVSyncClientCreatePtr vsync_client_create;
-  DvrVSyncClientDestroyPtr vsync_client_destroy;
-  DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
-
-  // Display surface
-  DvrGetNamedBufferPtr get_named_buffer;
-  DvrSurfaceCreatePtr surface_create;
-  DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
-
-  // Pose client
-  DvrPoseClientCreatePtr pose_client_create;
-  DvrPoseClientDestroyPtr pose_client_destroy;
-  DvrPoseGetPtr pose_get;
-  DvrPoseGetVsyncCountPtr pose_get_vsync_count;
-  DvrPoseGetControllerPtr pose_get_controller;
-
-  // Virtual touchpad client
-  DvrVirtualTouchpadCreatePtr virtual_touchpad_create;
-  DvrVirtualTouchpadDestroyPtr virtual_touchpad_destroy;
-  DvrVirtualTouchpadAttachPtr virtual_touchpad_attach;
-  DvrVirtualTouchpadDetachPtr virtual_touchpad_detach;
-  DvrVirtualTouchpadTouchPtr virtual_touchpad_touch;
-  DvrVirtualTouchpadButtonStatePtr virtual_touchpad_button_state;
-
-  // VR HWComposer client
-  DvrHwcClientCreatePtr hwc_client_create;
-  DvrHwcClientDestroyPtr hwc_client_destroy;
-  DvrHwcFrameDestroyPtr hwc_frame_destroy;
-  DvrHwcFrameGetDisplayIdPtr hwc_frame_get_display_id;
-  DvrHwcFrameGetDisplayWidthPtr hwc_frame_get_display_width;
-  DvrHwcFrameGetDisplayHeightPtr hwc_frame_get_display_height;
-  DvrHwcFrameGetDisplayRemovedPtr hwc_frame_get_display_removed;
-  DvrHwcFrameGetActiveConfigPtr hwc_frame_get_active_config;
-  DvrHwcFrameGetColorModePtr hwc_frame_get_color_mode;
-  DvrHwcFrameGetColorTransformPtr hwc_frame_get_color_transform;
-  DvrHwcFrameGetPowerModePtr hwc_frame_get_power_mode;
-  DvrHwcFrameGetVsyncEnabledPtr hwc_frame_get_vsync_enabled;
-  DvrHwcFrameGetLayerCountPtr hwc_frame_get_layer_count;
-  DvrHwcFrameGetLayerIdPtr hwc_frame_get_layer_id;
-  DvrHwcFrameGetLayerBufferPtr hwc_frame_get_layer_buffer;
-  DvrHwcFrameGetLayerFencePtr hwc_frame_get_layer_fence;
-  DvrHwcFrameGetLayerDisplayFramePtr hwc_frame_get_layer_display_frame;
-  DvrHwcFrameGetLayerCropPtr hwc_frame_get_layer_crop;
-  DvrHwcFrameGetLayerBlendModePtr hwc_frame_get_layer_blend_mode;
-  DvrHwcFrameGetLayerAlphaPtr hwc_frame_get_layer_alpha;
-  DvrHwcFrameGetLayerTypePtr hwc_frame_get_layer_type;
-  DvrHwcFrameGetLayerApplicationIdPtr hwc_frame_get_layer_application_id;
-  DvrHwcFrameGetLayerZOrderPtr hwc_frame_get_layer_z_order;
-  DvrHwcFrameGetLayerCursorPtr hwc_frame_get_layer_cursor;
-  DvrHwcFrameGetLayerTransformPtr hwc_frame_get_layer_transform;
-  DvrHwcFrameGetLayerDataspacePtr hwc_frame_get_layer_dataspace;
-  DvrHwcFrameGetLayerColorPtr hwc_frame_get_layer_color;
-  DvrHwcFrameGetLayerNumVisibleRegionsPtr
-      hwc_frame_get_layer_num_visible_regions;
-  DvrHwcFrameGetLayerVisibleRegionPtr hwc_frame_get_layer_visible_region;
-  DvrHwcFrameGetLayerNumDamagedRegionsPtr
-      hwc_frame_get_layer_num_damaged_regions;
-  DvrHwcFrameGetLayerDamagedRegionPtr hwc_frame_get_layer_damaged_region;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
 };
 
 int dvrGetApi(void* api, size_t struct_size, int version);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_API_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
new file mode 100644
index 0000000..09568fd
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -0,0 +1,135 @@
+// dvr_api_entries.h
+//
+// Defines the DVR platform library API entries.
+//
+// Do not include this header directly.
+
+#ifndef DVR_V1_API_ENTRY
+#error Do not include this header directly.
+#endif
+
+// Display manager client
+DVR_V1_API_ENTRY(DisplayManagerCreate);
+DVR_V1_API_ENTRY(DisplayManagerDestroy);
+DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
+DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
+DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
+DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
+DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(SurfaceStateCreate);
+DVR_V1_API_ENTRY(SurfaceStateDestroy);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
+DVR_V1_API_ENTRY(SurfaceStateGetUpdateFlags);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceId);
+DVR_V1_API_ENTRY(SurfaceStateGetProcessId);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueCount);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueIds);
+DVR_V1_API_ENTRY(SurfaceStateGetZOrder);
+DVR_V1_API_ENTRY(SurfaceStateGetVisible);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributeCount);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributes);
+
+// Write buffer
+DVR_V1_API_ENTRY(WriteBufferCreateEmpty);
+DVR_V1_API_ENTRY(WriteBufferDestroy);
+DVR_V1_API_ENTRY(WriteBufferIsValid);
+DVR_V1_API_ENTRY(WriteBufferClear);
+DVR_V1_API_ENTRY(WriteBufferGetId);
+DVR_V1_API_ENTRY(WriteBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(WriteBufferPost);
+DVR_V1_API_ENTRY(WriteBufferGain);
+DVR_V1_API_ENTRY(WriteBufferGainAsync);
+DVR_V1_API_ENTRY(WriteBufferGetNativeHandle);
+
+// Read buffer
+DVR_V1_API_ENTRY(ReadBufferCreateEmpty);
+DVR_V1_API_ENTRY(ReadBufferDestroy);
+DVR_V1_API_ENTRY(ReadBufferIsValid);
+DVR_V1_API_ENTRY(ReadBufferClear);
+DVR_V1_API_ENTRY(ReadBufferGetId);
+DVR_V1_API_ENTRY(ReadBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(ReadBufferAcquire);
+DVR_V1_API_ENTRY(ReadBufferRelease);
+DVR_V1_API_ENTRY(ReadBufferReleaseAsync);
+DVR_V1_API_ENTRY(ReadBufferGetNativeHandle);
+
+// Buffer
+DVR_V1_API_ENTRY(BufferDestroy);
+DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(BufferGetNativeHandle);
+
+// Write buffer queue
+DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
+DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(WriteBufferQueueGetId);
+DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);
+DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(WriteBufferQueueDequeue);
+
+// Read buffer queue
+DVR_V1_API_ENTRY(ReadBufferQueueDestroy);
+DVR_V1_API_ENTRY(ReadBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(ReadBufferQueueGetId);
+DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(ReadBufferQueueDequeue);
+
+// V-Sync client
+DVR_V1_API_ENTRY(VSyncClientCreate);
+DVR_V1_API_ENTRY(VSyncClientDestroy);
+DVR_V1_API_ENTRY(VSyncClientGetSchedInfo);
+
+// Display surface
+DVR_V1_API_ENTRY(SurfaceCreate);
+DVR_V1_API_ENTRY(SurfaceDestroy);
+DVR_V1_API_ENTRY(SurfaceGetId);
+DVR_V1_API_ENTRY(SurfaceSetAttributes);
+DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
+DVR_V1_API_ENTRY(GetNamedBuffer);
+
+// 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);
+
+// Virtual touchpad client
+DVR_V1_API_ENTRY(VirtualTouchpadCreate);
+DVR_V1_API_ENTRY(VirtualTouchpadDestroy);
+DVR_V1_API_ENTRY(VirtualTouchpadAttach);
+DVR_V1_API_ENTRY(VirtualTouchpadDetach);
+DVR_V1_API_ENTRY(VirtualTouchpadTouch);
+DVR_V1_API_ENTRY(VirtualTouchpadButtonState);
+
+// VR HWComposer client
+DVR_V1_API_ENTRY(HwcClientCreate);
+DVR_V1_API_ENTRY(HwcClientDestroy);
+DVR_V1_API_ENTRY(HwcFrameDestroy);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayId);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayWidth);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayHeight);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayRemoved);
+DVR_V1_API_ENTRY(HwcFrameGetActiveConfig);
+DVR_V1_API_ENTRY(HwcFrameGetColorMode);
+DVR_V1_API_ENTRY(HwcFrameGetColorTransform);
+DVR_V1_API_ENTRY(HwcFrameGetPowerMode);
+DVR_V1_API_ENTRY(HwcFrameGetVsyncEnabled);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCount);
+DVR_V1_API_ENTRY(HwcFrameGetLayerId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBuffer);
+DVR_V1_API_ENTRY(HwcFrameGetLayerFence);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDisplayFrame);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCrop);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBlendMode);
+DVR_V1_API_ENTRY(HwcFrameGetLayerAlpha);
+DVR_V1_API_ENTRY(HwcFrameGetLayerType);
+DVR_V1_API_ENTRY(HwcFrameGetLayerApplicationId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerZOrder);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCursor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerTransform);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDataspace);
+DVR_V1_API_ENTRY(HwcFrameGetLayerColor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumVisibleRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index 3e8357c..af55698 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -3,11 +3,10 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <sys/cdefs.h>
 #include <memory>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct DvrWriteBuffer DvrWriteBuffer;
 typedef struct DvrReadBuffer DvrReadBuffer;
@@ -15,58 +14,91 @@
 typedef struct AHardwareBuffer AHardwareBuffer;
 struct native_handle;
 
-// Write buffer
+// Creates an empty write buffer that may be filled with an acutal buffer by
+// other functions.
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer);
+
+// Destroys the write buffer.
 void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrWriteBufferIsValid on the same buffer object returns 0.
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer);
+
+// Returns the global BufferHub id of this buffer.
 int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
                                      AHardwareBuffer** hardware_buffer);
+
+// Posts the buffer, notifying any connected read buffers. Takes ownership of
+// |ready_fence_fd|.
 int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
                        const void* meta, size_t meta_size_bytes);
+
+// Gains a buffer that has been released by all connected read buffers.
 int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
 int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer);
 
-// Read buffer
+// Creates an empty read buffer that may be filled with and actual buffer by
+// other functions.
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer);
+
+// Destroys the read buffer.
 void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrReadBufferIsValid on the same buffer object returns 0.
+int dvrReadBufferClear(DvrReadBuffer* read_buffer);
+
+// Returns the global BufferHub id of this buffer.
 int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
                                     AHardwareBuffer** hardware_buffer);
+
+// Acquires the read buffer after it has been posted by the write buffer it is
+// connected to.
 int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
                          void* meta, size_t meta_size_bytes);
+
+// Releases the read buffer, notifying the write buffer it is connected to.
+// Takes ownership of |release_fence_fd|.
 int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
 int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrReadBufferGetNativeHandle(
     DvrReadBuffer* read_buffer);
 
-// Buffer
+// Destroys the buffer.
 void dvrBufferDestroy(DvrBuffer* buffer);
+
+// Gets an AHardwareBuffer from the buffer.
 // Caller must call AHardwareBuffer_release on hardware_buffer.
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-namespace android {
-namespace dvr {
-
-class BufferProducer;
-class BufferConsumer;
-class IonBuffer;
-
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<BufferProducer>& buffer_producer);
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrBuffer* CreateDvrBufferFromIonBuffer(
-    const std::shared_ptr<IonBuffer>& ion_buffer);
-
-}  // namespace dvr
-}  // namespace android
+__END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index ba39513..dd669dc 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -1,11 +1,11 @@
 #ifndef ANDROID_DVR_BUFFER_QUEUE_H_
 #define ANDROID_DVR_BUFFER_QUEUE_H_
 
+#include <sys/cdefs.h>
+
 #include <dvr/dvr_buffer.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 typedef struct ANativeWindow ANativeWindow;
 
@@ -14,7 +14,8 @@
 
 // WriteBufferQueue
 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue);
 
 // Returns ANativeWindow. Can be casted to a Java Surface using
 // ANativeWindow_toSurface NDK API. Note that this method does not acquire an
@@ -26,19 +27,18 @@
 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
                                        DvrReadBufferQueue** out_read_queue);
 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
-                               DvrWriteBuffer** out_buffer, int* out_fence_fd);
+                               DvrWriteBuffer* out_buffer, int* out_fence_fd);
 
 // ReadeBufferQueue
 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue);
 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
                                       DvrReadBufferQueue** out_read_queue);
 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
-                              DvrReadBuffer** out_buffer, int* out_fence_fd,
+                              DvrReadBuffer* out_buffer, int* out_fence_fd,
                               void* out_meta, size_t meta_size_bytes);
 
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_deleter.h b/libs/vr/libdvr/include/dvr/dvr_deleter.h
new file mode 100644
index 0000000..943384f
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_deleter.h
@@ -0,0 +1,86 @@
+#ifndef ANDROID_DVR_DELETER_H_
+#define ANDROID_DVR_DELETER_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+// Header-only C++ helper to delete opaque DVR objects.
+
+__BEGIN_DECLS
+
+// Use forward declarations to avoid dependency on other headers.
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrSurface DvrSurface;
+typedef struct DvrHwcClient DvrHwcClient;
+typedef struct DvrHwcFrame DvrHwcFrame;
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+void dvrBufferDestroy(DvrBuffer* buffer);
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+void dvrSurfaceDestroy(DvrSurface* surface);
+void dvrHwcClientDestroy(DvrHwcClient* client);
+void dvrHwcFrameDestroy(DvrHwcFrame* frame);
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+__END_DECLS
+
+// Avoid errors if this header is included in C code.
+#if defined(__cplusplus)
+
+namespace android {
+namespace dvr {
+
+// Universal DVR object deleter. May be passed to smart pointer types to handle
+// deletion of DVR API objects.
+struct DvrObjectDeleter {
+  void operator()(DvrBuffer* p) { dvrBufferDestroy(p); }
+  void operator()(DvrReadBuffer* p) { dvrReadBufferDestroy(p); }
+  void operator()(DvrWriteBuffer* p) { dvrWriteBufferDestroy(p); }
+  void operator()(DvrReadBufferQueue* p) { dvrReadBufferQueueDestroy(p); }
+  void operator()(DvrWriteBufferQueue* p) { dvrWriteBufferQueueDestroy(p); }
+  void operator()(DvrDisplayManager* p) { dvrDisplayManagerDestroy(p); }
+  void operator()(DvrSurfaceState* p) { dvrSurfaceStateDestroy(p); }
+  void operator()(DvrSurface* p) { dvrSurfaceDestroy(p); }
+  void operator()(DvrHwcClient* p) { dvrHwcClientDestroy(p); }
+  void operator()(DvrHwcFrame* p) { dvrHwcFrameDestroy(p); }
+  void operator()(DvrVSyncClient* p) { dvrVSyncClientDestroy(p); }
+};
+
+// Helper to define unique pointers for DVR object types.
+template <typename T>
+using MakeUniqueDvrPointer = std::unique_ptr<T, DvrObjectDeleter>;
+
+// Unique pointer types for DVR objects.
+using UniqueDvrBuffer = MakeUniqueDvrPointer<DvrBuffer>;
+using UniqueDvrReadBuffer = MakeUniqueDvrPointer<DvrReadBuffer>;
+using UniqueDvrWriteBuffer = MakeUniqueDvrPointer<DvrWriteBuffer>;
+using UniqueDvrReadBufferQueue = MakeUniqueDvrPointer<DvrReadBufferQueue>;
+using UniqueDvrWriteBufferQueue = MakeUniqueDvrPointer<DvrWriteBufferQueue>;
+using UniqueDvrDisplayManager = MakeUniqueDvrPointer<DvrDisplayManager>;
+using UniqueDvrSurfaceState = MakeUniqueDvrPointer<DvrSurfaceState>;
+using UniqueDvrSurface = MakeUniqueDvrPointer<DvrSurface>;
+using UniqueDvrHwcClient = MakeUniqueDvrPointer<DvrHwcClient>;
+using UniqueDvrHwcFrame = MakeUniqueDvrPointer<DvrHwcFrame>;
+using UniqueDvrVSyncClient = MakeUniqueDvrPointer<DvrVSyncClient>;
+
+// TODO(eieio): Add an adapter for std::shared_ptr that injects the deleter into
+// the relevant constructors.
+
+}  // namespace dvr
+}  // namespace android
+
+#endif // defined(__cplusplus)
+
+#endif  // ANDROID_DVR_DELETER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
new file mode 100644
index 0000000..d5aef8b
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -0,0 +1,140 @@
+#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
+#define DVR_DISPLAY_MANAGER_CLIENT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_surface.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+typedef uint64_t DvrSurfaceUpdateFlags;
+
+// Attempts to connect to the display manager service.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out);
+
+// Destroys the display manager client object.
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+
+// Sets up a named buffer for shared memory data transfer between display
+// clients and the display manager.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+                                      const char* name, size_t size,
+                                      uint64_t usage, DvrBuffer** buffer_out);
+
+// Returns an fd used to signal when surface updates occur. Note that depending
+// on the underlying transport, only a subset of the real event bits may be
+// supported. Use dvrDisplayManagerClientTranslateEpollEventMask to get the real
+// event flags.
+// @return the fd on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client);
+
+// @param in_events pass in the epoll revents that were initially returned by
+// poll/epoll.
+// @param on success, this value will be overwritten with the true poll/epoll
+// values.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+                                             int in_events, int* out_events);
+
+// Queries the display manager service for the current state of the display
+// surfaces and stores the results in the given surface state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+                                     DvrSurfaceState* surface_state);
+
+// Gets a read buffer queue from the surface |surface_id| named |queue_id|. Each
+// call returns a different read buffer queue connected to the same write buffer
+// queue. Callers should cache these instead of requesting new ones when
+// possible.
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+                                        int surface_id, int queue_id,
+                                        DvrReadBufferQueue** queue_out);
+
+// Creates a new surface state object. This object may be used to receive the
+// results of a surface state query. More than one state object may be created
+// to keep multiple snapshots, if desired.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state);
+
+// Destorys the surface state object.
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+
+// Writes the number of surfaces described in the state object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+                                   size_t* count_out);
+
+// Returns the update flags for the surface at |surface_index| in the state
+// object. The flags may be used to determine what changes, if any, occured to
+// the surface since the last state update.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+                                  size_t surface_index,
+                                  DvrSurfaceUpdateFlags* flags_out);
+
+// Returns the unique identifier of surface at |surface_index| in the state
+// object. The identifier may be used to distinguish between surfaces.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* surface_id_out);
+
+// Returns the process id of surface at |surface_index| in the state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+                                size_t surface_index, int* process_id_out);
+
+// Writes the number of queues in the surface at |surface_index| in the state
+// object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+                                 size_t surface_index, size_t* count_out);
+
+// Returns up to |max_count| queue ids for the queues belonging to the surface
+// at |surface_index| in the state object.
+// @return The number of queue ids written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+                                   size_t surface_index, int* queue_ids,
+                                   size_t max_count);
+
+// Writes the z-order of the surface at |surface_index| in surface state object
+// into |z_order_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+                             size_t surface_index, int* z_order_out);
+
+// Writes the visible state of the surface at |surface_index| in the surface
+// state object into |visible_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+                              size_t surface_index, bool* visible_out);
+
+// Writes the number of attributes on the surface at |surface_index| in the
+// state object into |count_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+                                     size_t surface_index, size_t* count_out);
+
+// Writes the list of attribute key/value pairs for the surface at
+// |surface_index| in the surface state object into |attributes|.
+// @return The number of attributes written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+                                     size_t surface_index,
+                                     DvrSurfaceAttribute* attributes,
+                                     size_t max_count);
+
+__END_DECLS
+
+#endif  // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index e5228d6..58f2a10 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -1,28 +1,90 @@
 #ifndef ANDROID_DVR_SURFACE_H_
 #define ANDROID_DVR_SURFACE_H_
 
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
 #include <dvr/dvr_buffer.h>
 #include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_types.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
+typedef struct DvrBuffer DvrBuffer;
 typedef struct DvrSurface DvrSurface;
-typedef struct DvrSurfaceParameter DvrSurfaceParameter;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
 
-// Get a pointer to the global pose buffer.
+// Attribute types. The values are one-hot encoded to support singluar types or
+// masks of supported types.
+enum {
+  DVR_SURFACE_ATTRIBUTE_TYPE_NONE = 0,
+  DVR_SURFACE_ATTRIBUTE_TYPE_INT32 = (1 << 0),
+  DVR_SURFACE_ATTRIBUTE_TYPE_INT64 = (1 << 1),
+  DVR_SURFACE_ATTRIBUTE_TYPE_BOOL = (1 << 2),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT = (1 << 3),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2 = (1 << 4),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3 = (1 << 5),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4 = (1 << 6),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8 = (1 << 7),
+  DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16 = (1 << 8),
+};
+
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue {
+  DvrSurfaceAttributeType type;
+  union {
+    int32_t int32_value;
+    int64_t int64_value;
+    bool bool_value;
+    float float_value;
+    float float2_value[2];
+    float float3_value[3];
+    float float4_value[4];
+    float float8_value[8];
+    float float16_value[16];
+  };
+} DvrSurfaceAttributeValue;
+
+typedef struct DvrSurfaceAttribute {
+  DvrSurfaceAttributeKey key;
+  DvrSurfaceAttributeValue value;
+} DvrSurfaceAttribute;
+
+// Creates a new display surface with the given attributes.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+                     size_t attribute_count, DvrSurface** surface_out);
+
+// Destroys the display surface.
+void dvrSurfaceDestroy(DvrSurface* surface);
+
+// Gets the DisplayService global id for this surface.
+int dvrSurfaceGetId(DvrSurface* surface);
+
+// Sets attributes on the given display surface.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+                            const DvrSurfaceAttribute* attributes,
+                            size_t attribute_count);
+
+// Creates a new write-side buffer queue on the given surface. Direct surfaces
+// may only have one queue, the latest call replacing any prior queue. Replaced
+// queues are still referenced and should be destryoed using the queue destroy
+// API.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+                                     uint32_t height, uint32_t format,
+                                     uint64_t usage, size_t capacity,
+                                     DvrWriteBufferQueue** queue_out);
+
+// Get a named buffer from the display service.
+// @return 0 on success. Otherwise returns a negative error value.
 int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
 
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
-                     uint64_t usage1, int flags, DvrSurface** out_surface);
-
-// TODO(eieio, jwcai) Change this once we have multiple buffer queue support.
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
-                                  DvrWriteBufferQueue** out_writer);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
+__END_DECLS
 
 #endif  // ANDROID_DVR_SURFACE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
new file mode 100644
index 0000000..1eea3d9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -0,0 +1,26 @@
+#ifndef ANDROID_DVR_VSYNC_H_
+#define ANDROID_DVR_VSYNC_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+// Creates a new client to the system vsync service.
+int dvrVSyncClientCreate(DvrVSyncClient** client_out);
+
+// Destroys the vsync client.
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+// Get the estimated timestamp of the next GPU lens warp preemption event in/
+// ns. Also returns the corresponding vsync count that the next lens warp
+// operation will target.
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+                               int64_t* next_timestamp_ns,
+                               uint32_t* next_vsync_count);
+
+__END_DECLS
+
+#endif  // ANDROID_DVR_VSYNC_H_
diff --git a/libs/vr/libdvr/include/dvr/vsync_client_api.h b/libs/vr/libdvr/include/dvr/vsync_client_api.h
deleted file mode 100644
index 0ae5cd5..0000000
--- a/libs/vr/libdvr/include/dvr/vsync_client_api.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ANDROID_DVR_VSYNC_CLIENT_API_H_
-#define ANDROID_DVR_VSYNC_CLIENT_API_H_
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// A client of the vsync service.
-//
-// The "dvr_vsync_client" structure wraps a client connection to the
-// system vsync service. It is used to synchronize application drawing
-// with the scanout of the display.
-typedef struct dvr_vsync_client dvr_vsync_client;
-
-// Creates a new client to the system vsync service.
-dvr_vsync_client* dvr_vsync_client_create();
-
-// Destroys the vsync client.
-void dvr_vsync_client_destroy(dvr_vsync_client* client);
-
-// Get the estimated timestamp of the next GPU lens warp preemption event in
-// ns. Also returns the corresponding vsync count that the next lens warp
-// operation will target. This call has the same side effect on events as
-// Acknowledge, which saves an IPC message.
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
-                                    int64_t* vsync_period_ns,
-                                    int64_t* next_timestamp_ns,
-                                    uint32_t* next_vsync_count);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // ANDROID_DVR_VSYNC_CLIENT_API_H_
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 29cdc13..d6ce99b 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -23,6 +23,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := \
     dvr_buffer_queue-test.cpp \
+    dvr_display_manager-test.cpp \
     dvr_named_buffer-test.cpp \
 
 LOCAL_STATIC_LIBRARIES := $(static_libraries)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index ea1273e..5f7f1bf 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -6,6 +6,8 @@
 #include <base/logging.h>
 #include <gtest/gtest.h>
 
+#include "../dvr_internal.h"
+
 namespace android {
 namespace dvr {
 
@@ -23,9 +25,9 @@
 class DvrBufferQueueTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    write_queue_ = new DvrWriteBufferQueue;
-    write_queue_->producer_queue_ = ProducerQueue::Create<TestMeta>(0, 0, 0, 0);
-    ASSERT_NE(nullptr, write_queue_->producer_queue_);
+    write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
+        ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
+    ASSERT_NE(nullptr, write_queue_);
   }
 
   void TearDown() override {
@@ -38,9 +40,10 @@
   void AllocateBuffers(size_t buffer_count) {
     size_t out_slot;
     for (size_t i = 0; i < buffer_count; i++) {
-      int ret = write_queue_->producer_queue_->AllocateBuffer(
-          kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage,
-          kBufferSliceCount, &out_slot);
+      int ret =
+          GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+              ->AllocateBuffer(kBufferWidth, kBufferHeight, kBufferFormat,
+                               kBufferUsage, kBufferSliceCount, &out_slot);
       ASSERT_EQ(0, ret);
     }
   }
@@ -88,6 +91,39 @@
   dvrReadBufferQueueDestroy(read_queue2);
 }
 
+TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
+  AllocateBuffers(3);
+
+  DvrReadBuffer* read_buffer = nullptr;
+  DvrWriteBuffer* write_buffer = nullptr;
+
+  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+  dvrReadBufferCreateEmpty(&read_buffer);
+  ASSERT_NE(nullptr, read_buffer);
+
+  dvrWriteBufferCreateEmpty(&write_buffer);
+  ASSERT_NE(nullptr, write_buffer);
+
+  EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+  DvrReadBufferQueue* read_queue = nullptr;
+
+  ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
+
+  const int kTimeoutMs = 0;
+  int fence_fd = -1;
+  ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
+                                          write_buffer, &fence_fd));
+  EXPECT_EQ(-1, fence_fd);
+  EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
+
+  ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
+  EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+}
+
 TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
   static constexpr int kTimeout = 0;
   DvrReadBufferQueue* read_queue = nullptr;
@@ -100,12 +136,18 @@
   ASSERT_EQ(0, ret);
   ASSERT_NE(nullptr, read_queue);
 
+  dvrWriteBufferCreateEmpty(&wb);
+  ASSERT_NE(nullptr, wb);
+
+  dvrReadBufferCreateEmpty(&rb);
+  ASSERT_NE(nullptr, rb);
+
   AllocateBuffers(kQueueCapacity);
 
   // Gain buffer for writing.
-  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, &wb, &fence_fd);
+  ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
   ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, wb);
+  ASSERT_TRUE(dvrWriteBufferIsValid(wb));
   ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
            wb, fence_fd);
   pdx::LocalHandle release_fence(fence_fd);
@@ -119,10 +161,10 @@
 
   // Acquire buffer for reading.
   TestMeta acquired_seq = 0U;
-  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, &rb, &fence_fd,
+  ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
                                   &acquired_seq, sizeof(acquired_seq));
   ASSERT_EQ(0, ret);
-  ASSERT_NE(nullptr, rb);
+  ASSERT_TRUE(dvrReadBufferIsValid(rb));
   ASSERT_EQ(seq, acquired_seq);
   ALOGD_IF(TRACE,
            "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
@@ -156,10 +198,11 @@
 
   // A write queue with DvrNativeBufferMetadata should work fine.
   std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
-      write_queue(new DvrWriteBufferQueue, dvrWriteBufferQueueDestroy);
-  write_queue->producer_queue_ =
-      ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0);
-  ASSERT_NE(nullptr, write_queue->producer_queue_);
+      write_queue(
+          CreateDvrWriteBufferQueueFromProducerQueue(
+              ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
+          dvrWriteBufferQueueDestroy);
+  ASSERT_NE(nullptr, write_queue.get());
 
   ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
   ASSERT_EQ(0, ret);
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
new file mode 100644
index 0000000..0150984
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -0,0 +1,539 @@
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <poll.h>
+
+#include <android/hardware_buffer.h>
+
+#include <algorithm>
+#include <set>
+#include <thread>
+#include <vector>
+
+#include <dvr/dvr_deleter.h>
+#include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_surface.h>
+
+#include <pdx/status.h>
+
+using android::pdx::ErrorStatus;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, bool value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+  attribute.value.bool_value = value;
+  return attribute;
+}
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, int32_t value) {
+  DvrSurfaceAttribute attribute;
+  attribute.key = key;
+  attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+  attribute.value.bool_value = value;
+  return attribute;
+}
+
+Status<UniqueDvrSurface> CreateApplicationSurface(bool visible = false,
+                                                  int32_t z_order = 0) {
+  DvrSurface* surface = nullptr;
+  DvrSurfaceAttribute attributes[] = {
+      GetAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
+      GetAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
+
+  const int ret = dvrSurfaceCreate(
+      attributes, std::extent<decltype(attributes)>::value, &surface);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {UniqueDvrSurface(surface)};
+}
+
+Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
+    const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
+    uint32_t format, uint64_t usage, size_t capacity) {
+  DvrWriteBufferQueue* queue;
+  const int ret = dvrSurfaceCreateWriteBufferQueue(
+      surface.get(), width, height, format, usage, capacity, &queue);
+  if (ret < 0)
+    return ErrorStatus(-ret);
+  else
+    return {UniqueDvrWriteBufferQueue(queue)};
+}
+
+class TestDisplayManager {
+ public:
+  TestDisplayManager(UniqueDvrDisplayManager display_manager,
+                     UniqueDvrSurfaceState surface_state)
+      : display_manager_(std::move(display_manager)),
+        surface_state_(std::move(surface_state)) {
+    const int fd = dvrDisplayManagerGetEventFd(display_manager_.get());
+    LOG_IF(INFO, fd < 0) << "Failed to get event fd: " << strerror(-fd);
+    display_manager_event_fd_ = fd;
+  }
+
+  Status<UniqueDvrReadBufferQueue> GetReadBufferQueue(int surface_id,
+                                                      int queue_id) {
+    DvrReadBufferQueue* queue;
+    const int ret = dvrDisplayManagerGetReadBufferQueue(
+        display_manager_.get(), surface_id, queue_id, &queue);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {UniqueDvrReadBufferQueue(queue)};
+  }
+
+  Status<void> UpdateSurfaceState() {
+    const int ret = dvrDisplayManagerGetSurfaceState(display_manager_.get(),
+                                                     surface_state_.get());
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {};
+  }
+
+  Status<void> WaitForUpdate() {
+    if (display_manager_event_fd_ < 0)
+      return ErrorStatus(-display_manager_event_fd_);
+
+    const int kTimeoutMs = 10000;  // 10s
+    pollfd pfd = {display_manager_event_fd_, POLLIN, 0};
+    const int count = poll(&pfd, 1, kTimeoutMs);
+    if (count < 0)
+      return ErrorStatus(errno);
+    else if (count == 0)
+      return ErrorStatus(ETIMEDOUT);
+
+    int events;
+    const int ret = dvrDisplayManagerTranslateEpollEventMask(
+        display_manager_.get(), pfd.revents, &events);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else if (events & POLLIN)
+      return UpdateSurfaceState();
+    else
+      return ErrorStatus(EPROTO);
+  }
+
+  Status<size_t> GetSurfaceCount() {
+    size_t count = 0;
+    const int ret =
+        dvrSurfaceStateGetSurfaceCount(surface_state_.get(), &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {count};
+  }
+
+  Status<DvrSurfaceUpdateFlags> GetUpdateFlags(size_t surface_index) {
+    DvrSurfaceUpdateFlags update_flags;
+    const int ret = dvrSurfaceStateGetUpdateFlags(surface_state_.get(),
+                                                  surface_index, &update_flags);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {update_flags};
+  }
+
+  Status<int> GetSurfaceId(size_t surface_index) {
+    int surface_id;
+    const int ret = dvrSurfaceStateGetSurfaceId(surface_state_.get(),
+                                                surface_index, &surface_id);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {surface_id};
+  }
+
+  Status<int> GetProcessId(size_t surface_index) {
+    int process_id;
+    const int ret = dvrSurfaceStateGetProcessId(surface_state_.get(),
+                                                surface_index, &process_id);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+    else
+      return {process_id};
+  }
+
+  Status<std::vector<DvrSurfaceAttribute>> GetAttributes(size_t surface_index) {
+    std::vector<DvrSurfaceAttribute> attributes;
+    size_t count = 0;
+    const int ret = dvrSurfaceStateGetAttributeCount(surface_state_.get(),
+                                                     surface_index, &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+
+    attributes.resize(count);
+    const ssize_t return_count = dvrSurfaceStateGetAttributes(
+        surface_state_.get(), surface_index, attributes.data(), count);
+    if (return_count < 0)
+      return ErrorStatus(-return_count);
+
+    attributes.resize(return_count);
+    return {std::move(attributes)};
+  }
+
+  Status<std::vector<int>> GetQueueIds(size_t surface_index) {
+    std::vector<int> queue_ids;
+    size_t count = 0;
+    const int ret = dvrSurfaceStateGetQueueCount(surface_state_.get(),
+                                                 surface_index, &count);
+    if (ret < 0)
+      return ErrorStatus(-ret);
+
+    if (count > 0) {
+      queue_ids.resize(count);
+      const ssize_t return_count = dvrSurfaceStateGetQueueIds(
+          surface_state_.get(), surface_index, queue_ids.data(), count);
+      if (return_count < 0)
+        return ErrorStatus(-return_count);
+
+      queue_ids.resize(return_count);
+    }
+
+    return {std::move(queue_ids)};
+  }
+
+ private:
+  UniqueDvrDisplayManager display_manager_;
+  UniqueDvrSurfaceState surface_state_;
+
+  // Owned by object in display_manager_, do not explicitly close.
+  int display_manager_event_fd_;
+
+  TestDisplayManager(const TestDisplayManager&) = delete;
+  void operator=(const TestDisplayManager&) = delete;
+};
+
+class DvrDisplayManagerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    int ret;
+    DvrDisplayManager* display_manager;
+    DvrSurfaceState* surface_state;
+
+    ret = dvrDisplayManagerCreate(&display_manager);
+    ASSERT_EQ(0, ret) << "Failed to create display manager client";
+    ASSERT_NE(nullptr, display_manager);
+
+    ret = dvrSurfaceStateCreate(&surface_state);
+    ASSERT_EQ(0, ret) << "Failed to create surface state object";
+    ASSERT_NE(nullptr, surface_state);
+
+    manager_.reset(
+        new TestDisplayManager(UniqueDvrDisplayManager(display_manager),
+                               UniqueDvrSurfaceState(surface_state)));
+  }
+  void TearDown() override {}
+
+  std::unique_ptr<TestDisplayManager> manager_;
+};
+
+// TODO(eieio): Consider moving these somewhere more central because they are
+// broadly useful.
+
+template <typename T>
+testing::AssertionResult StatusOk(const char* status_expression,
+                                  const Status<T>& status) {
+  if (!status.ok()) {
+    return testing::AssertionFailure()
+           << "(" << status_expression
+           << ") expected to indicate success but actually contains error ("
+           << status.error() << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T>
+testing::AssertionResult StatusError(const char* status_expression,
+                                     const Status<T>& status) {
+  if (status.ok()) {
+    return testing::AssertionFailure()
+           << "(" << status_expression
+           << ") expected to indicate error but instead indicates success.";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T>
+testing::AssertionResult StatusHasError(const char* status_expression,
+                                        const char* /*error_code_expression*/,
+                                        const Status<T>& status,
+                                        int error_code) {
+  if (status.ok()) {
+    return StatusError(status_expression, status);
+  } else if (status.error() != error_code) {
+    return testing::AssertionFailure()
+           << "(" << status_expression << ") expected to indicate error ("
+           << error_code << ") but actually indicates error (" << status.error()
+           << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T, typename U>
+testing::AssertionResult StatusHasValue(const char* status_expression,
+                                        const char* /*value_expression*/,
+                                        const Status<T>& status,
+                                        const U& value) {
+  if (!status.ok()) {
+    return StatusOk(status_expression, status);
+  } else if (status.get() != value) {
+    return testing::AssertionFailure()
+           << "(" << status_expression << ") expected to contain value ("
+           << testing::PrintToString(value) << ") but actually contains value ("
+           << testing::PrintToString(status.get()) << ")";
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+template <typename T, typename Op>
+testing::AssertionResult StatusPred(const char* status_expression,
+                                    const char* pred_expression,
+                                    const Status<T>& status, Op pred) {
+  if (!status.ok()) {
+    return StatusOk(status_expression, status);
+  } else if (!pred(status.get())) {
+    return testing::AssertionFailure()
+           << status_expression << " value ("
+           << testing::PrintToString(status.get())
+           << ") failed to pass predicate " << pred_expression;
+  } else {
+    return testing::AssertionSuccess();
+  }
+}
+
+#define ASSERT_STATUS_OK(status) ASSERT_PRED_FORMAT1(StatusOk, status)
+#define ASSERT_STATUS_ERROR(status) ASSERT_PRED_FORMAT1(StatusError, status)
+
+#define ASSERT_STATUS_ERROR_VALUE(value, status) \
+  ASSERT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define ASSERT_STATUS_EQ(value, status) \
+  ASSERT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_OK(status) EXPECT_PRED_FORMAT1(StatusOk, status)
+#define EXPECT_STATUS_ERROR(status) EXPECT_PRED_FORMAT1(StatusError, status)
+
+#define EXPECT_STATUS_ERROR_VALUE(value, status) \
+  EXPECT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define EXPECT_STATUS_EQ(value, status) \
+  EXPECT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_PRED(pred, status) \
+  EXPECT_PRED_FORMAT2(StatusPred, status, pred)
+
+#if 0
+// Verify utility predicate/macro functionality. This section is commented out
+// because it is designed to fail in some cases to validate the helpers.
+TEST_F(DvrDisplayManagerTest, ExpectVoid) {
+  Status<void> status_error{ErrorStatus{EINVAL}};
+  Status<void> status_ok{};
+
+  EXPECT_STATUS_ERROR(status_error);
+  EXPECT_STATUS_ERROR(status_ok);
+  EXPECT_STATUS_OK(status_error);
+  EXPECT_STATUS_OK(status_ok);
+
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+}
+
+TEST_F(DvrDisplayManagerTest, ExpectInt) {
+  Status<int> status_error{ErrorStatus{EINVAL}};
+  Status<int> status_ok{10};
+
+  EXPECT_STATUS_ERROR(status_error);
+  EXPECT_STATUS_ERROR(status_ok);
+  EXPECT_STATUS_OK(status_error);
+  EXPECT_STATUS_OK(status_ok);
+
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+  EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+
+  EXPECT_STATUS_EQ(10, status_error);
+  EXPECT_STATUS_EQ(20, status_error);
+  EXPECT_STATUS_EQ(10, status_ok);
+  EXPECT_STATUS_EQ(20, status_ok);
+
+  auto pred1 = [](const auto& value) { return value < 15; };
+  auto pred2 = [](const auto& value) { return value > 5; };
+  auto pred3 = [](const auto& value) { return value > 15; };
+  auto pred4 = [](const auto& value) { return value < 5; };
+
+  EXPECT_STATUS_PRED(pred1, status_error);
+  EXPECT_STATUS_PRED(pred2, status_error);
+  EXPECT_STATUS_PRED(pred3, status_error);
+  EXPECT_STATUS_PRED(pred4, status_error);
+  EXPECT_STATUS_PRED(pred1, status_ok);
+  EXPECT_STATUS_PRED(pred2, status_ok);
+  EXPECT_STATUS_PRED(pred3, status_ok);
+  EXPECT_STATUS_PRED(pred4, status_ok);
+}
+#endif
+
+TEST_F(DvrDisplayManagerTest, SurfaceCreateEvent) {
+  // Get surface state and verify there are no surfaces.
+  ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+  ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+  // Get flags for invalid surface index.
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetUpdateFlags(0));
+
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  const int surface_id = dvrSurfaceGetId(surface.get());
+  ASSERT_GE(surface_id, 0);
+
+  // Now there should be one new surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify the new surface flag is set.
+  auto check_flags = [](const auto& value) {
+    return value & DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE;
+  };
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  // Verify the surface id matches.
+  EXPECT_STATUS_EQ(surface_id, manager_->GetSurfaceId(0));
+
+  // Verify the owning process of the surface.
+  EXPECT_STATUS_EQ(getpid(), manager_->GetProcessId(0));
+
+  surface.reset();
+
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  EXPECT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceAttributeEvent) {
+  // Get surface state and verify there are no surfaces.
+  ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+  ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+  // Get attributes for an invalid surface index.
+  EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetAttributes(0));
+
+  const bool kInitialVisibility = true;
+  const int32_t kInitialZOrder = 10;
+  auto surface_status =
+      CreateApplicationSurface(kInitialVisibility, kInitialZOrder);
+  ASSERT_STATUS_OK(surface_status);
+  auto surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Check the initial attribute values.
+  auto attribute_status = manager_->GetAttributes(0);
+  ASSERT_STATUS_OK(attribute_status);
+  auto attributes = attribute_status.take();
+  EXPECT_GE(attributes.size(), 2u);
+
+  const std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+                                           DVR_SURFACE_ATTRIBUTE_VISIBLE};
+
+  // Collect all the keys in attributes that match the expected keys.
+  std::set<int32_t> actual_keys;
+  std::for_each(attributes.begin(), attributes.end(),
+                [&expected_keys, &actual_keys](const auto& attribute) {
+                  if (expected_keys.find(attribute.key) != expected_keys.end())
+                    actual_keys.emplace(attribute.key);
+                });
+
+  // If the sets match then attributes contained at least the expected keys,
+  // even if other keys were also present.
+  EXPECT_EQ(expected_keys, actual_keys);
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceQueueEvent) {
+  // Create an application surface.
+  auto surface_status = CreateApplicationSurface();
+  ASSERT_STATUS_OK(surface_status);
+  UniqueDvrSurface surface = surface_status.take();
+  ASSERT_NE(nullptr, surface.get());
+
+  const int surface_id = dvrSurfaceGetId(surface.get());
+  ASSERT_GE(surface_id, 0);
+  // Get surface state and verify there is one surface.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify there are no queues for the surface recorded in the state snapshot.
+  EXPECT_STATUS_EQ(std::vector<int>{}, manager_->GetQueueIds(0));
+
+  // Create a new queue in the surface.
+  auto write_queue_status = CreateSurfaceQueue(
+      surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+      AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+  ASSERT_STATUS_OK(write_queue_status);
+  UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
+  ASSERT_NE(nullptr, write_queue.get());
+
+  const int queue_id = dvrWriteBufferQueueGetId(write_queue.get());
+  ASSERT_GE(queue_id, 0);
+
+  // Update surface state.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify the buffers changed flag is set.
+  auto check_flags = [](const auto& value) {
+    return value & DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED;
+  };
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  auto queue_ids_status = manager_->GetQueueIds(0);
+  ASSERT_STATUS_OK(queue_ids_status);
+
+  auto queue_ids = queue_ids_status.take();
+  ASSERT_EQ(1u, queue_ids.size());
+  EXPECT_EQ(queue_id, queue_ids[0]);
+
+  auto read_queue_status = manager_->GetReadBufferQueue(surface_id, queue_id);
+  ASSERT_STATUS_OK(read_queue_status);
+  UniqueDvrReadBufferQueue read_queue = read_queue_status.take();
+  ASSERT_NE(nullptr, read_queue.get());
+  EXPECT_EQ(queue_id, dvrReadBufferQueueGetId(read_queue.get()));
+
+  write_queue.reset();
+
+  // Verify that destroying the queue generates a surface update event.
+  ASSERT_STATUS_OK(manager_->WaitForUpdate());
+  ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+  // Verify that the buffers changed flag is set.
+  EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+  // Verify that the queue ids reflect the change.
+  queue_ids_status = manager_->GetQueueIds(0);
+  ASSERT_STATUS_OK(queue_ids_status);
+
+  queue_ids = queue_ids_status.take();
+  ASSERT_EQ(0u, queue_ids.size());
+}
+
+}  // namespace
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index 6a02342..e65f6d5 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,6 +1,6 @@
 #include <android/hardware_buffer.h>
-#include <dvr/display_manager_client.h>
 #include <dvr/dvr_buffer.h>
+#include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_surface.h>
 #include <system/graphics.h>
 
@@ -15,28 +15,31 @@
 class DvrNamedBufferTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    client_ = dvrDisplayManagerClientCreate();
+    const int ret = dvrDisplayManagerCreate(&client_);
+    ASSERT_EQ(0, ret);
     ASSERT_NE(nullptr, client_);
   }
 
   void TearDown() override {
-    if (client_ != nullptr) {
-      dvrDisplayManagerClientDestroy(client_);
-      client_ = nullptr;
-    }
+    dvrDisplayManagerDestroy(client_);
+    client_ = nullptr;
   }
 
-  DvrDisplayManagerClient* client_ = nullptr;
+  DvrDisplayManager* client_ = nullptr;
 };
 
 TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
   const char* buffer_name = "same_name";
-  DvrBuffer* buffer1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  DvrBuffer* buffer1 = nullptr;
+  int ret1 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer1);
 
-  DvrBuffer* buffer2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+  DvrBuffer* buffer2 = nullptr;
+  int ret2 =
+      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, buffer2);
 
   AHardwareBuffer* hardware_buffer1 = nullptr;
@@ -95,13 +98,17 @@
 TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
   const char* buffer_name1 = "test1";
   const char* buffer_name2 = "test2";
-  DvrBuffer* setup_buffer1 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+  DvrBuffer* setup_buffer1 = nullptr;
+  int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
+                                               &setup_buffer1);
+  ASSERT_EQ(0, ret1);
   ASSERT_NE(nullptr, setup_buffer1);
   dvrBufferDestroy(setup_buffer1);
 
-  DvrBuffer* setup_buffer2 =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+  DvrBuffer* setup_buffer2 = nullptr;
+  int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
+                                               &setup_buffer2);
+  ASSERT_EQ(0, ret2);
   ASSERT_NE(nullptr, setup_buffer2);
   dvrBufferDestroy(setup_buffer2);
 
@@ -126,11 +133,13 @@
   // GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, and these two values are different.
   // If all is good, when we get the AHardwareBuffer, it should be converted
   // back to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE.
-  const int64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
+  const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
 
-  DvrBuffer* setup_buffer =
-      dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage, 0);
+  DvrBuffer* setup_buffer = nullptr;
+  int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
+                                             &setup_buffer);
   ASSERT_NE(nullptr, setup_buffer);
+  ASSERT_EQ(0, e1);
 
   AHardwareBuffer* hardware_buffer = nullptr;
   int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
@@ -139,14 +148,12 @@
 
   AHardwareBuffer_Desc desc = {};
   AHardwareBuffer_describe(hardware_buffer, &desc);
-
-  ASSERT_EQ(desc.usage, AHARDWAREBUFFER_USAGE_VIDEO_ENCODE);
+  ASSERT_EQ(usage, desc.usage);
 
   dvrBufferDestroy(setup_buffer);
   AHardwareBuffer_release(hardware_buffer);
 }
 
-
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libdvr/vsync_client_api.cpp b/libs/vr/libdvr/vsync_client_api.cpp
deleted file mode 100644
index dbddd3d..0000000
--- a/libs/vr/libdvr/vsync_client_api.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "include/dvr/vsync_client_api.h"
-
-#include <private/dvr/vsync_client.h>
-
-extern "C" {
-
-dvr_vsync_client* dvr_vsync_client_create() {
-  auto client = android::dvr::VSyncClient::Create();
-  return static_cast<dvr_vsync_client*>(client.release());
-}
-
-void dvr_vsync_client_destroy(dvr_vsync_client* client) {
-  delete static_cast<android::dvr::VSyncClient*>(client);
-}
-
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
-                                    int64_t* vsync_period_ns,
-                                    int64_t* next_timestamp_ns,
-                                    uint32_t* next_vsync_count) {
-  return static_cast<android::dvr::VSyncClient*>(client)->GetSchedInfo(
-      vsync_period_ns, next_timestamp_ns, next_vsync_count);
-}
-
-}  // extern "C"