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/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 632978b..dc81c60 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -14,17 +14,11 @@
 
 sourceFiles = [
     "acquired_buffer.cpp",
-    "compositor.cpp",
-    "debug_hud_data.cpp",
-    "debug_hud_view.cpp",
+    "epoll_event_dispatcher.cpp",
     "display_manager_service.cpp",
     "display_service.cpp",
     "display_surface.cpp",
     "hardware_composer.cpp",
-    "screenshot_service.cpp",
-    "surface_channel.cpp",
-    "video_compositor.cpp",
-    "video_mesh_surface.cpp",
     "vr_flinger.cpp",
     "vsync_service.cpp",
 ]
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5a3aa7f..7932a9c 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -9,7 +9,7 @@
 namespace dvr {
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                               LocalHandle acquire_fence, uint64_t /*sequence*/)
+                               LocalHandle acquire_fence)
     : buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
 
 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 1d14a38..dd4fcc5 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -21,7 +21,7 @@
   // this constructor; the constructor does not attempt to ACQUIRE the buffer
   // itself.
   AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
-                 pdx::LocalHandle acquire_fence, uint64_t sequence);
+                 pdx::LocalHandle acquire_fence);
 
   // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
   // be in the POSTED state prior to calling this constructor, as this
diff --git a/libs/vr/libvrflinger/compositor.cpp b/libs/vr/libvrflinger/compositor.cpp
deleted file mode 100644
index d1d4f45..0000000
--- a/libs/vr/libvrflinger/compositor.cpp
+++ /dev/null
@@ -1,878 +0,0 @@
-#include "compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-
-#include <memory>
-
-#include <cutils/properties.h>
-
-#include <dvr/graphics.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/device_metrics.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/dummy_native_window.h>
-#include <private/dvr/gl_fenced_flush.h>
-#include <private/dvr/graphics/blur.h>
-#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/native_buffer.h>
-#include <private/dvr/platform_defines.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include "debug_hud_data.h"
-#include "debug_hud_view.h"
-#include "display_surface.h"
-
-#define BINNING_CONTROL_HINT_QCOM 0x8FB0
-
-// Accepted by the <hint> parameter of glHint:
-#define BINNING_QCOM 0x8FB1
-#define VISIBILITY_OPTIMIZED_BINNING_QCOM 0x8FB2
-#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
-
-#ifndef EGL_CONTEXT_MAJOR_VERSION
-#define EGL_CONTEXT_MAJOR_VERSION 0x3098
-#define EGL_CONTEXT_MINOR_VERSION 0x30FB
-#endif
-
-using android::pdx::LocalHandle;
-
-static const int kDistortionMeshResolution = 40;
-
-static std::shared_ptr<int64_t> eds_gpu_duration_ns =
-    std::make_shared<int64_t>(0);
-
-static constexpr char kDisableLensDistortionProp[] =
-    "persist.dvr.disable_distort";
-
-static constexpr char kEnableEdsPoseSaveProp[] =
-    "persist.dvr.save_eds_pose";
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// An implementation of ANativeWindowBuffer backed by a temporary IonBuffer.
-// Do not hold on to this kind of object, because the IonBuffer may become
-// invalid in other scopes.
-class TemporaryNativeBuffer
-    : public ANativeObjectBase<ANativeWindowBuffer, TemporaryNativeBuffer,
-                               LightRefBase<TemporaryNativeBuffer>> {
- public:
-  explicit TemporaryNativeBuffer(const IonBuffer* buffer) : BASE() {
-    ANativeWindowBuffer::width = buffer->width();
-    ANativeWindowBuffer::height = buffer->height();
-    ANativeWindowBuffer::stride = buffer->stride();
-    ANativeWindowBuffer::format = buffer->format();
-    ANativeWindowBuffer::usage = buffer->usage();
-    // TODO(eieio): Update NYC to support layer_count.
-    // ANativeWindowBuffer::layer_count = 1;
-    handle = buffer->handle();
-  }
-
- private:
-  friend class android::LightRefBase<TemporaryNativeBuffer>;
-
-  TemporaryNativeBuffer(const TemporaryNativeBuffer&) = delete;
-  void operator=(TemporaryNativeBuffer&) = delete;
-};
-
-std::vector<uint8_t> ReadTextureRGBA(GLuint texture_id, int width, int height) {
-  std::vector<uint8_t> data(width * height * 4);
-  GLuint fbo;
-  glGenFramebuffers(1, &fbo);
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         texture_id, 0);
-  // Using default GL_PACK_ALIGNMENT of 4 for the 4 byte source data.
-  glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-  glDeleteFramebuffers(1, &fbo);
-  CHECK_GL();
-  return data;
-}
-
-}  // namespace
-
-class Compositor::Texture {
- public:
-  Texture(std::shared_ptr<BufferConsumer> consumer, EGLDisplay display,
-          int index);
-  ~Texture();
-
-  std::shared_ptr<BufferConsumer> consumer() const { return consumer_; }
-  GLuint texture_id() const { return texture_id_; }
-  vec2i size() const {
-    return vec2i(native_buffer_.get()->width, native_buffer_.get()->height);
-  }
-  int index() const { return index_; }
-
-  bool Initialize();
-
- private:
-  Texture(const Texture&) = delete;
-  void operator=(const Texture&) = delete;
-
-  std::shared_ptr<BufferConsumer> consumer_;
-
-  android::sp<NativeBufferConsumer> native_buffer_;
-
-  EGLDisplay display_;
-  EGLImageKHR image_;
-  GLuint texture_id_;
-  int index_;
-};
-
-Compositor::Texture::Texture(std::shared_ptr<BufferConsumer> consumer,
-                             EGLDisplay display, int index)
-    : consumer_(consumer),
-      display_(display),
-      image_(nullptr),
-      texture_id_(0),
-      index_(index) {}
-
-Compositor::Texture::~Texture() {
-  glDeleteTextures(1, &texture_id_);
-  eglDestroyImageKHR(display_, image_);
-}
-
-bool Compositor::Texture::Initialize() {
-  native_buffer_ = new NativeBufferConsumer(consumer_, index_);
-
-  CHECK_GL();
-  image_ = eglCreateImageKHR(
-      display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-  if (!image_) {
-    ALOGE("Failed to create EGLImage\n");
-    return false;
-  }
-
-  glGenTextures(1, &texture_id_);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, texture_id_);
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  CHECK_GL();
-  return true;
-}
-
-Compositor::RenderTarget::RenderTarget()
-    : buffer_texture_id_(0),
-      buffer_framebuffer_id_(0),
-      buffer_image_(nullptr) {}
-
-Compositor::RenderTarget::~RenderTarget() { Destroy(); }
-
-void Compositor::RenderTarget::Destroy() {
-  glDeleteFramebuffers(1, &buffer_framebuffer_id_);
-  glDeleteTextures(1, &buffer_texture_id_);
-  eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer_image_);
-  buffer_texture_id_ = 0;
-  buffer_framebuffer_id_ = 0;
-  buffer_image_ = nullptr;
-}
-
-void Compositor::RenderTarget::Initialize(int width, int height) {
-  LOG_ALWAYS_FATAL_IF(buffer_texture_id_ || buffer_framebuffer_id_ ||
-                      buffer_image_);
-  constexpr int usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
-                        GRALLOC_USAGE_HW_RENDER |
-                        GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
-  buffer_ = std::make_shared<IonBuffer>(width, height,
-                                        HAL_PIXEL_FORMAT_RGBA_8888, usage);
-
-  native_buffer_ = new NativeBuffer(buffer_);
-
-  buffer_image_ = eglCreateImageKHR(
-      eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
-      EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-
-  glGenTextures(1, &buffer_texture_id_);
-  glBindTexture(GL_TEXTURE_2D, buffer_texture_id_);
-  CHECK_GL();
-
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer_image_);
-  CHECK_GL();
-
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glBindTexture(GL_TEXTURE_2D, 0);
-
-  // Generate a framebuffer.
-  glGenFramebuffers(1, &buffer_framebuffer_id_);
-  glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
-  CHECK_GL();
-
-  // Attach the color buffer
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         buffer_texture_id_, 0);
-  CHECK_GL();
-  GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-  CHECK_GL();
-  if (result != GL_FRAMEBUFFER_COMPLETE) {
-    ALOGE("Framebuffer incomplete: %d", result);
-  }
-
-  // Clear the render target to black once. In direct render mode we never draw
-  // the corner pixels.
-  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-  glClear(GL_COLOR_BUFFER_BIT);
-  glFlush();
-
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-  CHECK_GL();
-}
-
-void Compositor::RenderTarget::BindFramebuffer() {
-  glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
-}
-
-void Compositor::RenderTarget::DiscardColorAttachment() {
-  GLenum attachment = GL_COLOR_ATTACHMENT0;
-  glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
-  CHECK_GL();
-}
-
-class Compositor::RenderPoseBufferObject {
- public:
-  RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) :
-      fd_(std::move(render_pose_buffer_fd)) {
-    // Create new pose tracking buffer for this surface.
-    glGenBuffers(1, &render_pose_buffer_object_);
-    glBindBuffer(GL_UNIFORM_BUFFER, render_pose_buffer_object_);
-    if (fd_) {
-      LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
-      if (glBindSharedBufferQCOM)
-        glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
-                               sizeof(DisplaySurfaceMetadata),
-                               fd_.Get());
-      else
-        ALOGE("Error: Missing gralloc buffer extension");
-      CHECK_GL();
-    }
-    glBindBuffer(GL_UNIFORM_BUFFER, 0);
-  }
-
-  ~RenderPoseBufferObject() { glDeleteBuffers(1, &render_pose_buffer_object_); }
-
-  GLuint object_id() const { return render_pose_buffer_object_; }
-
- private:
-  // Render pose buffer object. This contains an array of poses that corresponds
-  // with the surface buffers.
-  GLuint render_pose_buffer_object_;
-  LocalHandle fd_;
-
-  RenderPoseBufferObject(const RenderPoseBufferObject&) = delete;
-  void operator=(const RenderPoseBufferObject&) = delete;
-};
-
-HeadMountMetrics CreateDefaultHeadMountMetrics() {
-  const bool enable_distortion =
-      property_get_bool(kDisableLensDistortionProp, 0) == 0;
-  return enable_distortion ? CreateHeadMountMetrics()
-                           : CreateUndistortedHeadMountMetrics();
-}
-
-Compositor::Compositor()
-    : head_mount_metrics_(CreateDefaultHeadMountMetrics()),
-      display_(0),
-      config_(0),
-      surface_(0),
-      context_(0),
-      active_render_target_(0),
-      is_render_direct_(false),
-      compute_fbo_(0),
-      compute_fbo_texture_(0),
-      hmd_metrics_requires_update_(false),
-      eds_pose_capture_enabled_(false) {}
-
-Compositor::~Compositor() {}
-
-bool Compositor::Initialize(const DisplayMetrics& display_metrics) {
-  ATRACE_NAME("Compositor::Initialize");
-  if (!InitializeEGL())
-    return false;
-
-  display_metrics_ = display_metrics;
-  const int width = display_metrics_.GetSizePixels().x();
-  const int height = display_metrics_.GetSizePixels().y();
-
-  render_target_[0].Initialize(width, height);
-  render_target_[1].Initialize(width, height);
-
-  // EDS:
-  GpuProfiler::Get()->SetEnableGpuTracing(true);
-
-  eds_pose_capture_enabled_ = property_get_bool(kEnableEdsPoseSaveProp, 0) == 1;
-
-  CheckAndUpdateHeadMountMetrics(true);
-
-  debug_hud_.reset(new DebugHudView(*composite_hmd_.get()));
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  return true;
-}
-
-void Compositor::UpdateHeadMountMetrics(
-    const HeadMountMetrics& head_mount_metrics) {
-  // Recalculating the mesh must be done in the draw loop, defer until then.
-  std::lock_guard<std::mutex> _lock(mutex_);
-  head_mount_metrics_ = head_mount_metrics;
-  hmd_metrics_requires_update_ = true;
-}
-
-void Compositor::CheckAndUpdateHeadMountMetrics(bool force_update) {
-  std::lock_guard<std::mutex> _lock(mutex_);
-  if (hmd_metrics_requires_update_ || force_update) {
-    hmd_metrics_requires_update_ = false;
-    composite_hmd_.reset(
-        new CompositeHmd(head_mount_metrics_, display_metrics_));
-    CHECK_GL();
-    eds_renderer_.reset(new DistortionRenderer(
-        *composite_hmd_.get(), display_metrics_.GetSizePixels(),
-        kDistortionMeshResolution, true, false, false, true, true));
-  }
-}
-
-bool Compositor::InitializeEGL() {
-  ATRACE_NAME("Compositor::InitializeEGL");
-  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  if (!display_) {
-    ALOGE("Failed to get egl display\n");
-    return false;
-  }
-
-  eglInitialize(display_, nullptr, nullptr);
-
-  EGLint attribs[] = {
-      EGL_BUFFER_SIZE,
-      32,
-      EGL_ALPHA_SIZE,
-      0,
-      EGL_BLUE_SIZE,
-      8,
-      EGL_RED_SIZE,
-      8,
-      EGL_GREEN_SIZE,
-      8,
-      EGL_DEPTH_SIZE,
-      0,
-      EGL_SURFACE_TYPE,
-      EGL_WINDOW_BIT,
-      EGL_RENDERABLE_TYPE,
-      EGL_OPENGL_ES2_BIT,
-      EGL_NONE,
-  };
-
-  EGLint num_configs;
-  if (!eglChooseConfig(display_, attribs, &config_, 1, &num_configs)) {
-    ALOGE("Couldn't find config");
-    return false;
-  }
-
-  std::unique_ptr<DummyNativeWindow> window(new DummyNativeWindow());
-
-  surface_ = eglCreateWindowSurface(display_, config_, window.get(), nullptr);
-  if (surface_ == EGL_NO_SURFACE) {
-    ALOGE("Failed to create egl surface");
-    return false;
-  }
-  window.release();
-
-  EGLint context_attribs[] = {EGL_CONTEXT_MAJOR_VERSION,
-                              3,
-                              EGL_CONTEXT_MINOR_VERSION,
-                              1,
-                              EGL_CONTEXT_PRIORITY_LEVEL_IMG,
-                              EGL_CONTEXT_PRIORITY_HIGH_IMG,
-                              EGL_NONE};
-  context_ = eglCreateContext(display_, config_, nullptr, context_attribs);
-  if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
-    ALOGE("Unable to create GLESv2 context");
-    return false;
-  }
-
-  load_gl_extensions();
-  GpuProfiler::Get()->OnGlContextCreated();
-
-  glEnable(BINNING_CONTROL_HINT_QCOM);
-  glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
-  is_render_direct_ = true;
-  CHECK_GL();
-
-  // Initialize the placeholder 1x1 framebuffer that we bind during compute
-  // shader instances to avoid accesses to other framebuffers.
-  glGenFramebuffers(1, &compute_fbo_);
-  glGenTextures(1, &compute_fbo_texture_);
-  glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
-  glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-               nullptr);
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                         compute_fbo_texture_, 0);
-  CHECK_GL();
-  CHECK_GL_FBO();
-  glBindTexture(GL_TEXTURE_2D, 0);
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-  return true;
-}
-
-void Compositor::Shutdown() {
-  glFinish();
-  render_target_[0].Destroy();
-  render_target_[1].Destroy();
-  layers_.clear();
-  glDeleteFramebuffers(1, &compute_fbo_);
-  glDeleteTextures(1, &compute_fbo_texture_);
-
-  debug_hud_.reset();
-  eds_renderer_.reset();
-
-  if (context_) {
-    GpuProfiler::Get()->OnGlContextDestroyed();
-    eglDestroyContext(display_, context_);
-    context_ = 0;
-  }
-
-  if (surface_ != EGL_NO_SURFACE) {
-    eglDestroySurface(display_, surface_);
-    surface_ = EGL_NO_SURFACE;
-  }
-}
-
-void Compositor::RemoveAllBuffers() { layers_.clear(); }
-
-void Compositor::UpdateSurfaces(
-    const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
-  // Delete the removed surfaces.
-  layers_.erase(
-      std::remove_if(layers_.begin(), layers_.end(),
-                     [&surfaces](const AppFrame& layer) {
-                       for (const auto& surface : surfaces)
-                         if (surface->surface_id() == layer.surface_id())
-                           return false;
-                       return true;
-                     }),
-      layers_.end());
-  // New surfaces are added on-demand as buffers are posted.
-}
-
-Compositor::AppFrame::AppFrame()
-    : surface_id_(-1),
-      blur_(0.0f),
-      z_order_(0),
-      vertical_flip_(false),
-      enable_cac_(true),
-      render_buffer_index_(0) {}
-
-Compositor::AppFrame::~AppFrame() {}
-
-const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
-    EGLDisplay display, int index) {
-  auto buffer_consumer = buffer_.buffer();
-  if (!buffer_consumer) {
-    return nullptr;
-  }
-  auto texture_it = std::find_if(
-      textures_.begin(), textures_.end(),
-      [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
-        return t->consumer() == buffer_consumer && t->index() == index;
-      });
-
-  if (texture_it != textures_.end()) {
-    return (*texture_it).get();
-  }
-
-  textures_.push_back(
-      std::make_shared<Texture>(buffer_consumer, display, index));
-  if (!textures_.back()->Initialize()) {
-    textures_.pop_back();
-    return nullptr;
-  }
-  return textures_.back().get();
-}
-
-bool Compositor::AppFrame::UpdateSurface(
-    const std::shared_ptr<DisplaySurface>& surface) {
-  int surface_id = surface->surface_id();
-  float blur = surface->manager_blur();
-  bool need_sort = false;
-  if (z_order_ != surface->layer_order()) {
-    need_sort = true;
-    z_order_ = surface->layer_order();
-  }
-
-  surface_id_ = surface_id;
-  if (!render_pose_buffer_object_) {
-    render_pose_buffer_object_.reset(
-        new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
-  }
-
-  blur_ = blur;
-  vertical_flip_ =
-      !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
-  enable_cac_ =
-      !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
-
-  AcquiredBuffer skipped_buffer;
-  AcquiredBuffer buffer =
-      surface->AcquireNewestAvailableBuffer(&skipped_buffer);
-  if (!skipped_buffer.IsEmpty()) {
-    DebugHudData::data.SkipLayerFrame(z_order_);
-    ATRACE_NAME("DropToCatchUp");
-    ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
-  }
-  if (!buffer.IsEmpty()) {
-    DebugHudData::data.AddLayerFrame(z_order_);
-    // Buffer was already ready, so we don't need to wait on the fence.
-    buffer.ClaimAcquireFence().Close();
-    ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
-
-    render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
-
-#ifdef TRACE
-    const volatile DisplaySurfaceMetadata* data =
-        surface->GetMetadataBufferPtr();
-#endif
-    ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
-             data->orientation[render_buffer_index_][0],
-             data->orientation[render_buffer_index_][1]);
-
-    // Move the new buffer over the old. AcquiredBuffer releases the old one.
-    buffer_ = std::move(buffer);
-  }
-  return need_sort;
-}
-
-void Compositor::AppFrame::UpdateVideoMeshSurface(
-    const std::shared_ptr<DisplaySurface>& surface) {
-  // Update |video_compositors_| with |video_surface|. Note that
-  // |UpdateVideoMeshSurface| should only be called on the PostThread before
-  // |DrawFrame| is called. Thus, no synchronization is required for
-  // |video_compositors_|.
-  if (!surface->video_mesh_surfaces_updated())
-    return;
-
-  // TODO(jwcai) The following loop handles adding new surfaces; video mesh
-  // removal logic shall be handled by listening to |OnChannelClose| event from
-  // DisplayService.
-  for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
-    // Here we assume number of |video_surface|s is relatively small, thus, the
-    // merge should be efficient enough.
-    auto video_compositor_it = std::find_if(
-        video_compositors_.begin(), video_compositors_.end(),
-        [video_surface](const std::shared_ptr<VideoCompositor>& c) {
-          return c->surface_id() == video_surface->surface_id();
-        });
-
-    if (video_compositor_it == video_compositors_.end()) {
-      // This video surface is new, create a new VideoCompositor.
-      video_compositors_.push_back(std::make_shared<VideoCompositor>(
-          video_surface, surface->GetMetadataBufferPtr()));
-    } else {
-      // There is a compositor in |video_compositors_| is already set up for
-      // this |video_surface|.
-      ALOGW("Duplicated video_mesh_surface: surface_id=%d",
-            video_surface->surface_id());
-    }
-  }
-}
-
-void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
-
-void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
-  blurrers_.emplace_back(blurrer);
-}
-
-void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
-  int surface_id = surface->surface_id();
-
-  ALOGD_IF(TRACE, "Post surface %d", surface_id);
-
-  auto layer_it = std::find_if(layers_.begin(), layers_.end(),
-                               [surface_id](const AppFrame& frame) {
-                                 return frame.surface_id() == surface_id;
-                               });
-
-  bool need_sort = false;
-  if (layer_it == layers_.end()) {
-    layers_.push_back(AppFrame());
-    layer_it = layers_.end() - 1;
-    need_sort = true;
-  }
-
-  need_sort |= layer_it->UpdateSurface(surface);
-  layer_it->UpdateVideoMeshSurface(surface);
-
-  if (need_sort) {
-    std::stable_sort(layers_.begin(), layers_.end());
-  }
-}
-
-std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
-                                                 int* height) {
-  if (index >= layers_.size()) {
-    return {};
-  }
-
-  const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
-  if (!texture) {
-    return {};
-  }
-
-  *width = texture->size()[0];
-  *height = texture->size()[1];
-  return ReadTextureRGBA(texture->texture_id(), *width, *height);
-}
-
-std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
-  android::sp<TemporaryNativeBuffer> native_buffer =
-      new TemporaryNativeBuffer(buffer);
-
-  // Finish to make sure the GL driver has completed drawing of prior FBOs.
-  // Since we are creating an EGL image here, the driver will not know that
-  // there is a dependency on earlier GL draws.
-  glFinish();
-
-  EGLImageKHR image = eglCreateImageKHR(
-      display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-      static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
-  if (!image) {
-    ALOGE("Failed to create EGLImage\n");
-    return {};
-  }
-
-  GLuint texture_id;
-  glGenTextures(1, &texture_id);
-  glActiveTexture(GL_TEXTURE0);
-  glBindTexture(GL_TEXTURE_2D, texture_id);
-  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
-
-  int width = buffer->width();
-  int height = buffer->height();
-  std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
-
-  glBindTexture(GL_TEXTURE_2D, 0);
-  glDeleteTextures(1, &texture_id);
-  eglDestroyImageKHR(display_, image);
-  return data;
-}
-
-bool Compositor::DrawFrame(uint32_t target_vsync_count,
-                           LocalHandle* buffer_fence_fd) {
-  CheckAndUpdateHeadMountMetrics(false);
-
-  ATRACE_NAME("Compositor::DrawFrame");
-  GpuProfiler::Get()->PollGlTimerQueries();
-
-  if (buffer_fence_fd)
-    buffer_fence_fd->Close();
-
-  int num_layers = 0;
-  const int kMaxLayers = 4;
-  GLuint texture_id[2][kMaxLayers] = {{0}};
-  GLuint render_pose_buffer_id[kMaxLayers] = {0};
-  uint32_t render_buffer_index[kMaxLayers] = {0};
-  bool vertical_flip[kMaxLayers] = {false};
-  bool separate_eye_textures[kMaxLayers] = {false};
-  bool enable_cac[kMaxLayers] = {};
-  CHECK_GL();
-  for (auto& layer : layers_) {
-    if (!layer.buffer().buffer()) {
-      ATRACE_NAME("no_buffer");
-      continue;
-    }
-
-    // Extract surface parameters.
-    render_buffer_index[num_layers] = layer.render_buffer_index();
-    render_pose_buffer_id[num_layers] =
-        layer.render_pose_buffer_object()->object_id();
-    vertical_flip[num_layers] = layer.vertical_flip();
-    enable_cac[num_layers] =
-        head_mount_metrics_.supports_chromatic_aberration_correction() &&
-        layer.enable_cac();
-
-    // Extract per-eye textures. These may be separate or joined (atlased).
-    vec2i size(0, 0);
-    int view_count = layer.buffer().buffer()->slice_count();
-    ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
-    view_count = std::min(2, view_count);
-    separate_eye_textures[num_layers] = (view_count > 1);
-    bool is_missing_texture = false;
-    for (int eye = 0; eye < 2; ++eye) {
-      // If view_count is 1, each eye texture is the 0th.
-      int view_index = (view_count == 2) ? eye : 0;
-      const Texture* texture = layer.GetGlTextureId(display_, view_index);
-      // Texture will be null if the EGL image creation fails (hopefully never).
-      if (!texture) {
-        is_missing_texture = true;
-        break;
-      }
-      // All views are currently expected to have the same size.
-      size = texture->size();
-      texture_id[eye][num_layers] = texture->texture_id();
-    }
-    if (is_missing_texture) {
-      continue;
-    }
-
-    // Perform blur if requested.
-    if (fabs(layer.blur()) > 0.001f) {
-      // No need for CAC on blurred layers.
-      enable_cac[num_layers] = false;
-      if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
-          layer.blurrer(0)->height() != size[1]) {
-        // Blur is created with the left eye texture, but the same instance
-        // can be used for the right eye as well.
-        layer.ResetBlurrers();
-        layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
-                                  GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
-                                  view_count));
-      }
-      // Reset blur instances to prepare for drawing.
-      layer.blurrer(0)->StartFrame();
-      layer.blurrer(0)->set_scale(layer.blur());
-      // Perform blur and replace source texture with blurred output texture.
-      if (view_count == 1) {
-        // Single wide buffer for both eyes, blur both eyes in one operation.
-        texture_id[0][num_layers] = texture_id[1][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
-      } else {
-        // Split eye buffers in a single frame, blur each framebuffer.
-        texture_id[0][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
-        texture_id[1][num_layers] =
-            layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
-      }
-    }
-
-    ++num_layers;
-    if (num_layers >= kMaxLayers)
-      break;
-  }
-
-  CHECK_GL();
-  // Set appropriate binning mode for the number of layers.
-  if (num_layers > 1 && is_render_direct_) {
-    is_render_direct_ = false;
-    glDisable(BINNING_CONTROL_HINT_QCOM);
-  } else if (num_layers <= 1 && !is_render_direct_) {
-    is_render_direct_ = true;
-    glEnable(BINNING_CONTROL_HINT_QCOM);
-    glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
-  }
-
-  // Workaround for GL driver bug that causes the currently bound FBO to be
-  // accessed during a compute shader pass (DoLateLatch below). Based on an
-  // analysis with systrace, the best pattern here was to run the compute shader
-  // with a *different* FBO than what will be drawn to afterward. So we bind
-  // a dummy 1x1 FBO here and discard it. If instead, the current render target
-  // is bound during the compute shader, the following draw calls will be forced
-  // into direct mode rendering.
-  glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
-  GLenum attachment = GL_COLOR_ATTACHMENT0;
-  glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
-
-  // Double buffer the render target.  Get the render target we're drawing into,
-  // and update the active buffer to the next buffer.
-  RenderTarget& render_target = GetRenderTarget();
-  SetNextRenderTarget();
-
-  if (num_layers > 0) {
-    // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
-    TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
-    CHECK_GL();
-    eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
-                               render_pose_buffer_id, vertical_flip,
-                               separate_eye_textures, num_layers);
-
-    render_target.BindFramebuffer();
-
-    // Discard to avoid unresolving the framebuffer during tiled rendering.
-    render_target.DiscardColorAttachment();
-
-    // For tiled mode rendering, we clear every frame to avoid garbage showing
-    // up in the parts of tiles that are not rendered.
-    if (!is_render_direct_) {
-      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-      glClear(GL_COLOR_BUFFER_BIT);
-    }
-
-    for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
-      eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
-      for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
-        bool blend_with_previous = layer_i > 0;
-        uint32_t current_buffer_index = render_buffer_index[layer_i];
-
-        // Render video mesh in the background of each graphics layer.
-        layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
-                                                 current_buffer_index,
-                                                 &blend_with_previous](
-            const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
-          eds_renderer_->DrawVideoQuad(
-              static_cast<EyeType>(eye), layer_i,
-              video_compositor->GetActiveTextureId(display_),
-              video_compositor->GetTransform(eye, current_buffer_index));
-          blend_with_previous = true;
-        });
-
-        // Apply distortion to frame submitted from the app's GL context.
-        eds_renderer_->SetChromaticAberrationCorrectionEnabled(
-            enable_cac[layer_i]);
-        eds_renderer_->ApplyDistortionCorrectionToTexture(
-            static_cast<EyeType>(eye), &texture_id[eye][layer_i],
-            &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
-            1, blend_with_previous, false);
-      }
-    }
-    eds_renderer_->ResetGlState(1);
-    CHECK_GL();
-  } else {
-    ALOGI("No buffers for compositing, clearing to black.");
-    render_target.BindFramebuffer();
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-  }
-
-  debug_hud_->Update();
-  debug_hud_->Draw();
-
-  LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
-
-  if (buffer_fence_fd)
-    *buffer_fence_fd = std::move(fence_fd);
-
-  if (eds_pose_capture_enabled_) {
-    std::lock_guard<std::mutex> _lock(mutex_);
-    eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
-  }
-
-  return true;
-}
-
-bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
-  if (eds_pose_capture_enabled_) {
-    std::lock_guard<std::mutex> _lock(mutex_);
-    *out_data = eds_pose_capture_;
-    return true;
-  } else {
-    ALOGE("Eds pose capture is not enabled.");
-    return false;
-  }
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/compositor.h b/libs/vr/libvrflinger/compositor.h
deleted file mode 100644
index be26d31..0000000
--- a/libs/vr/libvrflinger/compositor.h
+++ /dev/null
@@ -1,233 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <log/log.h>
-#include <utils/StrongPointer.h>
-
-#include <memory>
-#include <mutex>
-#include <queue>
-#include <vector>
-
-#include <pdx/file_handle.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/display_metrics.h>
-#include <private/dvr/distortion_renderer.h>
-#include <private/dvr/frame_time_history.h>
-#include <private/dvr/ion_buffer.h>
-#include <private/dvr/native_buffer.h>
-
-#include "acquired_buffer.h"
-#include "video_compositor.h"
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class Blur;
-class BufferConsumer;
-class CompositeHmd;
-class DebugHudView;
-class DisplaySurface;
-
-// This is a GPU compositor for software EDS and lens warp on buffers provided
-// by HardwareComposer.
-class Compositor {
- public:
-  Compositor();
-  ~Compositor();
-
-  bool Initialize(const DisplayMetrics& display_metrics);
-  void UpdateHeadMountMetrics(const HeadMountMetrics& head_mount_metrics);
-  void Shutdown();
-
-  // Renders a frame with the latest buffers with EDS and warp applied.
-  // buffer_fence_fd can be used to get a fence for the rendered frame. It can
-  // be set to null if the fence isn't needed.
-  bool DrawFrame(uint32_t target_vsync_count,
-                 pdx::LocalHandle* buffer_fence_fd);
-
-  // Remove all buffers.
-  void RemoveAllBuffers();
-
-  // Synchronize compositor layers with in given surfaces.
-  void UpdateSurfaces(
-      const std::vector<std::shared_ptr<DisplaySurface>>& surfaces);
-
-  // This must be called for each surface before DrawFrame is called.
-  void PostBuffer(const std::shared_ptr<DisplaySurface>& surface);
-
-  std::shared_ptr<IonBuffer> GetBuffer() const {
-    return render_target_[active_render_target_].buffer();
-  }
-
-  // Returns the number of layers being rendered by the compositor.
-  size_t GetLayerCount() const { return layers_.size(); }
-
-  // Returns the source buffer at the given layer index or nullptr if none is
-  // available.
-  std::shared_ptr<BufferConsumer> PeekAtLayer(size_t index) const {
-    if (index >= GetLayerCount())
-      return nullptr;
-    return layers_[index].buffer().buffer();
-  }
-
-  // Expensive operation to transfer the pixels of the given layer index into
-  // unformatted memory and return as a RGBA buffer.
-  // On success, returns non-zero sized vector and sets width and height.
-  // On failure, returns empty vector.
-  std::vector<uint8_t> ReadLayerPixels(size_t index, int* width, int* height);
-
-  // Expensive operation to transfer the pixels of the given buffer into
-  // unformatted memory and return as a RGBA buffer.
-  // On success, returns non-zero sized vector.
-  // On failure, returns empty vector.
-  std::vector<uint8_t> ReadBufferPixels(const IonBuffer* buffer);
-
-  bool GetLastEdsPose(LateLatchOutput* out_data);
-
-  const HeadMountMetrics& head_mount_metrics() const {
-    return head_mount_metrics_;
-  }
-
- private:
-  class Texture;
-  class RenderPoseBufferObject;
-
-  // A rendered frame from an application.
-  class AppFrame {
-   public:
-    AppFrame();
-    ~AppFrame();
-
-    AppFrame(AppFrame&& other) = default;
-    AppFrame& operator=(AppFrame&&) = default;
-
-    // Gets a GL texture object for the current buffer. The resulting texture
-    // object will be cached for future calls. Returns a pointer for temporary
-    // access - not meant to hold on to.
-    const Texture* GetGlTextureId(EGLDisplay display, int index);
-
-    bool operator<(const AppFrame& rhs) const {
-      return z_order_ < rhs.z_order_;
-    }
-    int z_order() const { return z_order_; }
-    // Return true if this surface z order has been changed.
-    bool UpdateSurface(const std::shared_ptr<DisplaySurface>& surface);
-    void UpdateVideoMeshSurface(const std::shared_ptr<DisplaySurface>& surface);
-    void ResetBlurrers();
-    void AddBlurrer(Blur* blurrer);
-
-    const AcquiredBuffer& buffer() const { return buffer_; }
-    int surface_id() const { return surface_id_; }
-    float blur() const { return blur_; }
-    bool vertical_flip() const { return vertical_flip_; }
-    bool enable_cac() const { return enable_cac_; }
-    size_t blurrer_count() const { return blurrers_.size(); }
-    Blur* blurrer(size_t i) {
-      return blurrers_.size() < i ? nullptr : blurrers_[i].get();
-    }
-    uint32_t render_buffer_index() const { return render_buffer_index_; }
-    const RenderPoseBufferObject* render_pose_buffer_object() const {
-      return render_pose_buffer_object_.get();
-    }
-
-    template <class A>
-    void ForEachVideoCompositor(A action) const {
-      for (auto& c : video_compositors_) {
-        action(c);
-      }
-    }
-
-   private:
-    int surface_id_;
-    float blur_;
-    int z_order_;
-    bool vertical_flip_;
-    bool enable_cac_;
-    std::vector<std::unique_ptr<Blur>> blurrers_;
-    AcquiredBuffer buffer_;
-    std::vector<std::shared_ptr<Texture>> textures_;
-    uint32_t render_buffer_index_;
-    std::unique_ptr<RenderPoseBufferObject> render_pose_buffer_object_;
-
-    // Active video mesh compositors
-    std::vector<std::shared_ptr<VideoCompositor>> video_compositors_;
-
-    AppFrame(const AppFrame& other) = delete;
-    AppFrame& operator=(const AppFrame&) = delete;
-  };
-
-  class RenderTarget {
-   public:
-    RenderTarget();
-    ~RenderTarget();
-
-    void Initialize(int width, int height);
-    void Destroy();
-    void BindFramebuffer();
-    void DiscardColorAttachment();
-
-    std::shared_ptr<IonBuffer> buffer() const { return buffer_; }
-
-   private:
-    std::shared_ptr<IonBuffer> buffer_;
-    android::sp<NativeBuffer> native_buffer_;
-
-    GLuint buffer_texture_id_;
-    GLuint buffer_framebuffer_id_;
-    EGLImageKHR buffer_image_;
-  };
-
-  Compositor(const Compositor&) = delete;
-  void operator=(const Compositor&) = delete;
-
-  bool InitializeEGL();
-
-  void UpdateHudToggle();
-  void PrintStatsHud();
-  void CheckAndUpdateHeadMountMetrics(bool force_update);
-
-  RenderTarget& GetRenderTarget() {
-    return render_target_[active_render_target_];
-  }
-
-  void SetNextRenderTarget() {
-    active_render_target_ = (active_render_target_ + 1) & 1;
-  }
-
-  std::vector<AppFrame> layers_;
-
-  DisplayMetrics display_metrics_;
-  HeadMountMetrics head_mount_metrics_;
-
-  EGLDisplay display_;
-  EGLConfig config_;
-  EGLSurface surface_;
-  EGLContext context_;
-  int active_render_target_;
-  RenderTarget render_target_[2];
-  bool is_render_direct_;
-
-  // FBO for compute shader.
-  GLuint compute_fbo_;
-  GLuint compute_fbo_texture_;
-
-  std::unique_ptr<DebugHudView> debug_hud_;
-
-  // EDS:
-  std::unique_ptr<CompositeHmd> composite_hmd_;
-  bool hmd_metrics_requires_update_;
-  std::unique_ptr<DistortionRenderer> eds_renderer_;
-
-  bool eds_pose_capture_enabled_;
-  std::mutex mutex_;
-  LateLatchOutput eds_pose_capture_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/debug_hud_data.cpp b/libs/vr/libvrflinger/debug_hud_data.cpp
deleted file mode 100644
index d387bba..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudData DebugHudData::data;
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_data.h b/libs/vr/libvrflinger/debug_hud_data.h
deleted file mode 100644
index 778169d..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-
-#include <stdint.h>
-
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/frame_time_history.h>
-
-namespace android {
-namespace dvr {
-
-// Tracks debug stats for the displayd debug HUD. Unless otherwise noted,
-// there is no synchronization of data accesses to avoid performance impact.
-// All accesses to this data are on the displayd HWC post thread. Accesses from
-// other threads will need to be duly protected from races.
-// This is a lightweight struct to make it easy to add and remove
-// tracking data.
-struct DebugHudData {
-  // Maximum supported layers for the debug HUD.
-  enum { kMaxLayers = 4 };
-
-  // The global singleton HUD data instance.
-  static DebugHudData data;
-
-  // Tracks framerate and skipped frames.
-  struct FrameStats {
-    void AddFrame() {
-      int64_t now = GetSystemClockNs();
-      frame_time.AddSample(now - last_frame_ts);
-      last_frame_ts = now;
-    }
-
-    void SkipFrame() {
-      AddFrame();
-      ++drops;
-    }
-
-    int drops = 0;
-    int64_t last_frame_ts = 0;
-    FrameTimeHistory frame_time;
-  };
-
-  // Debug data for compositor layers (applications, system UI, etc).
-  struct LayerData {
-    void Reset() {
-      ResetStats();
-      width = 0;
-      height = 0;
-      is_separate = false;
-    }
-
-    void ResetStats() { frame_stats.drops = 0; }
-
-    FrameStats frame_stats;
-    int width = 0;
-    int height = 0;
-    bool is_separate = false;
-  };
-
-  // Resets the stats.
-  void ResetStats() {
-    hwc_frame_stats.drops = 0;
-    hwc_latency = 0;
-    for (auto& l : layer_data)
-      l.ResetStats();
-  }
-
-  // Resets the layer configuration.
-  void ResetLayers() {
-    num_layers = 0;
-    for (auto& l : layer_data)
-      l.Reset();
-  }
-
-  // Tracks a frame arrival for the given layer.
-  void AddLayerFrame(size_t layer) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].frame_stats.AddFrame();
-    }
-  }
-
-  // Tracks a frame skip/drop for the given layer.
-  void SkipLayerFrame(size_t layer) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].frame_stats.SkipFrame();
-    }
-  }
-
-  // Sets the resolution and other details of the layer.
-  void SetLayerInfo(size_t layer, int width, int height, bool is_separate) {
-    if (layer < kMaxLayers) {
-      num_layers = std::max(layer + 1, num_layers);
-      layer_data[layer].width = width;
-      layer_data[layer].height = height;
-      layer_data[layer].is_separate = is_separate;
-    }
-  }
-
-  FrameStats hwc_frame_stats;
-  int64_t hwc_latency = 0;
-  size_t num_layers = 0;
-  LayerData layer_data[kMaxLayers];
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
diff --git a/libs/vr/libvrflinger/debug_hud_view.cpp b/libs/vr/libvrflinger/debug_hud_view.cpp
deleted file mode 100644
index 4936ac6..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "debug_hud_view.h"
-
-#include <dvr/pose_client.h>
-
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudView::DebugHudView(const CompositeHmd& hmd) {
-  pose_client_ = dvrPoseCreate();
-
-  display_size_ = hmd.GetDisplayMetrics().GetSizePixels();
-  vec2 display_size_meters = hmd.GetDisplayMetrics().GetSizeMeters();
-  inter_lens_dist_screen_space_ =
-      2.0f * hmd.GetHeadMountMetrics().GetInterLensDistance() /
-      std::max(display_size_meters[0], display_size_meters[1]);
-}
-
-DebugHudView::~DebugHudView() {
-  if (pose_client_)
-    dvrPoseDestroy(pose_client_);
-  pose_client_ = nullptr;
-}
-
-void DebugHudView::Update() {
-  // Check for gesture that enables the debug stats HUD.
-  if (!pose_client_)
-    return;
-  DvrPoseAsync pose;
-  dvrPoseGet(pose_client_, 0, &pose);
-  float32x4_t q = pose.orientation;
-  quat orientation(q[3], q[0], q[1], q[2]);
-  vec3 up = orientation * vec3(0, 1, 0);
-  if (up[1] < -0.8f) {
-    ++switch_timer_;
-  } else {
-    switch_timer_ = 0;
-  }
-  // A few seconds upside down => toggle stats HUD.
-  if (switch_timer_ > 200) {
-    switch_timer_ = 0;
-    enabled_ = !enabled_;
-    DebugHudData::data.ResetStats();
-    ALOGE("Toggle debug stats HUD: %s", enabled_ ? "ON" : "OFF");
-  }
-}
-
-void DebugHudView::Draw() {
-  if (!enabled_)
-    return;
-  if (!debug_text_)
-    debug_text_.reset(new DebugText(400, display_size_[0], display_size_[1]));
-
-  const DebugHudData& data = DebugHudData::data;
-  const size_t layer_char_count = 50;
-  char layer_data[DebugHudData::kMaxLayers][layer_char_count];
-  for (size_t i = 0; i < data.num_layers; ++i) {
-    float fps = data.layer_data[i].frame_stats.frame_time.GetAverageFps();
-    snprintf(layer_data[i], layer_char_count,
-             "Layer %d %dx%d%s FPS: %.2f Drops: %d\n", static_cast<int>(i),
-             data.layer_data[i].width, data.layer_data[i].height,
-             data.layer_data[i].is_separate ? "x2" : "", fps,
-             data.layer_data[i].frame_stats.drops);
-  }
-
-  float hwc_fps = data.hwc_frame_stats.frame_time.GetAverageFps();
-
-  char text[400];
-  float hwc_latency_ms = static_cast<float>(data.hwc_latency) / 1000000.0f;
-  snprintf(text, sizeof(text), "HWC FPS: %.2f Latency: %.3f ms Skips: %d\n",
-           hwc_fps, hwc_latency_ms, data.hwc_frame_stats.drops);
-
-  for (size_t i = 0; i < data.num_layers; ++i) {
-    strncat(text, layer_data[i], sizeof(text) - strlen(text) - 1);
-  }
-
-  // Ensure text termination.
-  text[sizeof(text) - 1] = '\0';
-
-  glViewport(0, 0, display_size_[0], display_size_[1]);
-  glEnable(GL_BLEND);
-  // No stereo, because you can see the HUD OK in one eye. Stereo actually
-  // makes it more difficult to focus sometimes. To enable stereo:
-  // replace the second to last parameter with inter_lens_dist_screen_space_.
-  debug_text_->Draw(0.0f, -0.7f * inter_lens_dist_screen_space_, text, 0.0f, 1);
-  glDisable(GL_BLEND);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_view.h b/libs/vr/libvrflinger/debug_hud_view.h
deleted file mode 100644
index 50f38a8..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-
-#include <stdint.h>
-
-#include <utils/Log.h>
-
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/graphics/debug_text.h>
-
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class CompositeHmd;
-
-// The view and the controller for the displayd debug HUD.
-// The HUD is enabled and disabled by internally tracking the head pose.
-// When the head pose is upside down for ~3 seconds, the enabled state toggles.
-// See DebugHudData for the data that is reported.
-class DebugHudView {
- public:
-  DebugHudView(const CompositeHmd& hmd);
-  ~DebugHudView();
-
-  // Updates HUD state.
-  void Update();
-
-  // Draws HUD into the current framebuffer if it is currently enabled.
-  void Draw();
-
- private:
-  DebugHudView(const DebugHudView&) = delete;
-  DebugHudView& operator=(const DebugHudView&) = delete;
-
-  DvrPose* pose_client_ = nullptr;
-  vec2i display_size_;
-  bool enabled_ = false;
-  int switch_timer_ = 0;
-  float inter_lens_dist_screen_space_ = 0.0f;
-  std::unique_ptr<DebugText> debug_text_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 61bb71c..a0b3efe 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -9,26 +9,15 @@
 
 #include <array>
 
+using android::dvr::display::DisplayManagerProtocol;
 using android::pdx::Channel;
 using android::pdx::LocalChannelHandle;
 using android::pdx::Message;
 using android::pdx::default_transport::Endpoint;
+using android::pdx::ErrorStatus;
 using android::pdx::rpc::DispatchRemoteMethod;
 using android::pdx::rpc::IfAnyOf;
-
-namespace {
-
-// As a first line of defense, the display manager endpoint is only accessible
-// to the user and group.
-
-// TODO(dnicoara): Remove read/write permission for others. This is in here just
-// to allow us to experiment with cast functionality from a plain old app.
-constexpr mode_t kDisplayManagerEndpointFileMode =
-    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-
-constexpr size_t kMaxSurfacesPerRequest = 32;
-
-}  // anonymous namespace
+using android::pdx::rpc::RemoteMethodError;
 
 namespace android {
 namespace dvr {
@@ -45,8 +34,7 @@
 DisplayManagerService::DisplayManagerService(
     const std::shared_ptr<DisplayService>& display_service)
     : BASE("DisplayManagerService",
-           Endpoint::Create(DisplayManagerRPC::kClientPath,
-                            kDisplayManagerEndpointFileMode)),
+           Endpoint::Create(DisplayManagerProtocol::kClientPath)),
       display_service_(display_service) {
   display_service_->SetDisplayConfigurationUpdateNotifier(
       std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
@@ -54,9 +42,15 @@
 
 std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen(
     pdx::Message& message) {
-  // Prevent more than one display manager from registering at a time.
-  if (display_manager_)
-    REPLY_ERROR_RETURN(message, EPERM, nullptr);
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+  // Prevent more than one display manager from registering at a time or
+  // untrusted UIDs from connecting.
+  if (display_manager_ || !trusted) {
+    RemoteMethodError(message, EPERM);
+    return nullptr;
+  }
 
   display_manager_ =
       std::make_shared<DisplayManager>(this, message.GetChannelId());
@@ -74,18 +68,18 @@
   auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
 
   switch (message.GetOp()) {
-    case DisplayManagerRPC::GetSurfaceList::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceList>(
-          *this, &DisplayManagerService::OnGetSurfaceList, message);
+    case DisplayManagerProtocol::GetSurfaceState::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>(
+          *this, &DisplayManagerService::OnGetSurfaceState, message);
       return {};
 
-    case DisplayManagerRPC::UpdateSurfaces::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
-          *this, &DisplayManagerService::OnUpdateSurfaces, message);
+    case DisplayManagerProtocol::GetSurfaceQueue::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
+          *this, &DisplayManagerService::OnGetSurfaceQueue, message);
       return {};
 
-    case DisplayManagerRPC::SetupNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+    case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
           *this, &DisplayManagerService::OnSetupNamedBuffer, message);
       return {};
 
@@ -94,128 +88,67 @@
   }
 }
 
-std::vector<DisplaySurfaceInfo> DisplayManagerService::OnGetSurfaceList(
-    pdx::Message& /*message*/) {
-  std::vector<DisplaySurfaceInfo> items;
+pdx::Status<std::vector<display::SurfaceState>>
+DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) {
+  std::vector<display::SurfaceState> items;
 
   display_service_->ForEachDisplaySurface(
+      SurfaceType::Application,
       [&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
-        DisplaySurfaceInfo item;
-
-        item.surface_id = surface->surface_id();
-        item.process_id = surface->process_id();
-        item.type = surface->type();
-        item.flags = 0;  // TODO(eieio)
-        item.client_attributes = DisplaySurfaceAttributes{
-            {DisplaySurfaceAttributeEnum::Visible,
-             DisplaySurfaceAttributeValue{surface->client_visible()}},
-            {DisplaySurfaceAttributeEnum::ZOrder,
-             DisplaySurfaceAttributeValue{surface->client_z_order()}},
-            {DisplaySurfaceAttributeEnum::Blur,
-             DisplaySurfaceAttributeValue{0.f}}};
-        item.manager_attributes = DisplaySurfaceAttributes{
-            {DisplaySurfaceAttributeEnum::Visible,
-             DisplaySurfaceAttributeValue{surface->manager_visible()}},
-            {DisplaySurfaceAttributeEnum::ZOrder,
-             DisplaySurfaceAttributeValue{surface->manager_z_order()}},
-            {DisplaySurfaceAttributeEnum::Blur,
-             DisplaySurfaceAttributeValue{surface->manager_blur()}}};
-
-        items.push_back(item);
+        items.push_back({surface->surface_id(), surface->process_id(),
+                         surface->user_id(), surface->attributes(),
+                         surface->update_flags(), surface->GetQueueIds()});
+        surface->ClearUpdate();
       });
 
   // The fact that we're in the message handler implies that display_manager_ is
   // not nullptr. No check required, unless this service becomes multi-threaded.
   display_manager_->SetNotificationsPending(false);
-
   return items;
 }
 
-int DisplayManagerService::OnUpdateSurfaces(
-    pdx::Message& /*message*/,
-    const std::map<int, DisplaySurfaceAttributes>& updates) {
-  for (const auto& surface_update : updates) {
-    const int surface_id = surface_update.first;
-    const DisplaySurfaceAttributes& attributes = surface_update.second;
+pdx::Status<pdx::LocalChannelHandle> DisplayManagerService::OnGetSurfaceQueue(
+    pdx::Message& /*message*/, int surface_id, int queue_id) {
+  auto surface = display_service_->GetDisplaySurface(surface_id);
+  if (!surface || surface->surface_type() != SurfaceType::Application)
+    return ErrorStatus(EINVAL);
 
-    std::shared_ptr<DisplaySurface> surface =
-        display_service_->GetDisplaySurface(surface_id);
+  auto queue =
+      std::static_pointer_cast<ApplicationDisplaySurface>(surface)->GetQueue(
+          queue_id);
+  if (!queue)
+    return ErrorStatus(EINVAL);
 
-    if (!surface)
-      return -ENOENT;
+  auto status = queue->CreateConsumerQueueHandle();
+  ALOGE_IF(
+      !status,
+      "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer "
+      "queue for queue_id=%d: %s",
+      queue->id(), status.GetErrorMessage().c_str());
 
-    for (const auto& attribute : attributes) {
-      const auto& key = attribute.first;
-      const auto* variant = &attribute.second;
-      bool invalid_value = false;
-      switch (key) {
-        case DisplaySurfaceAttributeEnum::ZOrder:
-          invalid_value =
-              !IfAnyOf<int32_t>::Call(variant, [&surface](const auto& value) {
-                surface->ManagerSetZOrder(value);
-              });
-          break;
-        case DisplaySurfaceAttributeEnum::Visible:
-          invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-              variant, [&surface](const auto& value) {
-                surface->ManagerSetVisible(value);
-              });
-          break;
-        case DisplaySurfaceAttributeEnum::Blur:
-          invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
-              variant, [&surface](const auto& value) {
-                surface->ManagerSetBlur(value);
-              });
-          break;
-        default:
-          ALOGW(
-              "DisplayManagerService::OnUpdateSurfaces: Attempt to set invalid "
-              "attribute %u on surface %d",
-              key, surface_id);
-          break;
-      }
-
-      if (invalid_value) {
-        ALOGW(
-            "DisplayManagerService::OnUpdateSurfaces: Failed to set display "
-            "surface attribute '%s' because of incompatible type: %d",
-            DisplaySurfaceAttributeEnum::ToString(key).c_str(),
-            variant->index());
-      }
-    }
-  }
-
-  // Reconfigure the display layers for any active surface changes.
-  display_service_->UpdateActiveDisplaySurfaces();
-  return 0;
+  return status;
 }
 
 pdx::Status<BorrowedNativeBufferHandle>
 DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
                                           const std::string& name, size_t size,
                                           uint64_t usage) {
-  if (message.GetEffectiveUserId() != AID_ROOT &&
-      !IsTrustedUid(message.GetEffectiveUserId())) {
-    // Only trusted users can setup named buffers.
-    ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
-          message.GetEffectiveUserId());
-    return {};
+  const int user_id = message.GetEffectiveUserId();
+  const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+  if (!trusted) {
+    ALOGE(
+        "DisplayService::SetupNamedBuffer: Named buffers may only be created "
+        "by trusted UIDs: user_id=%d",
+        user_id);
+    return ErrorStatus(EPERM);
   }
   return display_service_->SetupNamedBuffer(name, size, usage);
 }
 
 void DisplayManagerService::OnDisplaySurfaceChange() {
-  if (display_manager_) {
+  if (display_manager_)
     display_manager_->SetNotificationsPending(true);
-  } else {
-    // If there isn't a display manager registered, default all display surfaces
-    // to visible.
-    display_service_->ForEachDisplaySurface(
-        [](const std::shared_ptr<DisplaySurface>& surface) {
-          surface->ManagerSetVisible(true);
-        });
-    display_service_->UpdateActiveDisplaySurfaces();
-  }
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index f59520c..0857eb5 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -1,7 +1,8 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#ifndef ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
+#define ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
 
 #include <pdx/service.h>
+#include <pdx/status.h>
 #include <private/dvr/display_protocol.h>
 
 #include "display_service.h"
@@ -50,10 +51,11 @@
   explicit DisplayManagerService(
       const std::shared_ptr<DisplayService>& display_service);
 
-  std::vector<DisplaySurfaceInfo> OnGetSurfaceList(pdx::Message& message);
-  int OnUpdateSurfaces(pdx::Message& message,
-                       const std::map<int, DisplaySurfaceAttributes>& updates);
-
+  pdx::Status<std::vector<display::SurfaceState>> OnGetSurfaceState(
+      pdx::Message& message);
+  pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
+                                                         int surface_id,
+                                                         int queue_id);
   pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
       pdx::Message& message, const std::string& name, size_t size,
       uint64_t usage);
@@ -72,4 +74,4 @@
 }  // namespace dvr
 }  // namespace android
 
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#endif  // ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index f56bc02..47efa76 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -3,30 +3,30 @@
 #include <unistd.h>
 #include <vector>
 
+#include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <pdx/rpc/remote_method.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/device_metrics.h>
 #include <private/dvr/display_protocol.h>
-#include <private/dvr/display_types.h>
 #include <private/dvr/numeric.h>
-#include <private/dvr/polynomial_radial_distortion.h>
 #include <private/dvr/types.h>
 
+using android::dvr::display::DisplayProtocol;
 using android::pdx::Channel;
+using android::pdx::ErrorStatus;
 using android::pdx::Message;
+using android::pdx::Status;
 using android::pdx::default_transport::Endpoint;
 using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::WrapBuffer;
 
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService() : DisplayService(nullptr) {}
-
-DisplayService::DisplayService(Hwc2::Composer* hidl)
-    : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
-      hardware_composer_(hidl) {
+DisplayService::DisplayService(Hwc2::Composer* hidl,
+                               RequestDisplayCallback request_display_callback)
+    : BASE("DisplayService",
+           Endpoint::Create(display::DisplayProtocol::kClientPath)),
+      hardware_composer_(hidl, request_display_callback),
+      request_display_callback_(request_display_callback) {
   hardware_composer_.Initialize();
 }
 
@@ -34,68 +34,51 @@
   return BASE::IsInitialized() && hardware_composer_.IsInitialized();
 }
 
-std::string DisplayService::DumpState(size_t max_length) {
-  std::vector<char> buffer(max_length);
-  uint32_t max_len_p = static_cast<uint32_t>(max_length);
-  hardware_composer_.Dump(buffer.data(), &max_len_p);
-  return std::string(buffer.data());
+std::string DisplayService::DumpState(size_t /*max_length*/) {
+  return hardware_composer_.Dump();
 }
 
-void DisplayService::OnChannelClose(pdx::Message& /*message*/,
+void DisplayService::OnChannelClose(pdx::Message& message,
                                     const std::shared_ptr<Channel>& channel) {
-  auto surface = std::static_pointer_cast<SurfaceChannel>(channel);
-  if (surface && surface->type() == SurfaceTypeEnum::Normal) {
-    auto display_surface = std::static_pointer_cast<DisplaySurface>(surface);
-    display_surface->ManagerSetVisible(false);
-    display_surface->ClientSetVisible(false);
-    NotifyDisplayConfigurationUpdate();
+  if (auto surface = std::static_pointer_cast<DisplaySurface>(channel)) {
+    surface->OnSetAttributes(message,
+                             {{display::SurfaceAttribute::Visible,
+                               display::SurfaceAttributeValue{false}}});
+    SurfaceUpdated(surface->surface_type(),
+                   display::SurfaceUpdateFlags::VisibilityChanged);
   }
-  // TODO(jwcai) Handle ChannelClose of VideoMeshSurface.
 }
 
 // First-level dispatch for display service messages. Directly handles messages
 // that are independent of the display surface (metrics, creation) and routes
 // surface-specific messages to the per-instance handlers.
-pdx::Status<void> DisplayService::HandleMessage(pdx::Message& message) {
-  auto channel = message.GetChannel<SurfaceChannel>();
-
+Status<void> DisplayService::HandleMessage(pdx::Message& message) {
+  ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
   switch (message.GetOp()) {
-    case DisplayRPC::GetMetrics::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetMetrics>(
+    case DisplayProtocol::GetMetrics::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
           *this, &DisplayService::OnGetMetrics, message);
       return {};
 
-    case DisplayRPC::GetEdsCapture::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
-          *this, &DisplayService::OnGetEdsCapture, message);
-      return {};
-
-    case DisplayRPC::CreateSurface::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateSurface>(
+    case DisplayProtocol::CreateSurface::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
           *this, &DisplayService::OnCreateSurface, message);
       return {};
 
-    case DisplayRPC::SetViewerParams::Opcode:
-      DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
-          *this, &DisplayService::OnSetViewerParams, message);
-      return {};
-
-    case DisplayRPC::GetNamedBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+    case DisplayProtocol::GetNamedBuffer::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
           *this, &DisplayService::OnGetNamedBuffer, message);
       return {};
 
-    case DisplayRPC::IsVrAppRunning::Opcode:
-      DispatchRemoteMethod<DisplayRPC::IsVrAppRunning>(
+    case DisplayProtocol::IsVrAppRunning::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::IsVrAppRunning>(
           *this, &DisplayService::IsVrAppRunning, message);
       return {};
 
     // Direct the surface specific messages to the surface instance.
-    case DisplayRPC::CreateBufferQueue::Opcode:
-    case DisplayRPC::SetAttributes::Opcode:
-    case DisplayRPC::GetMetadataBuffer::Opcode:
-    case DisplayRPC::CreateVideoMeshSurface::Opcode:
-    case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
+    case DisplayProtocol::SetAttributes::Opcode:
+    case DisplayProtocol::CreateQueue::Opcode:
+    case DisplayProtocol::GetSurfaceInfo::Opcode:
       return HandleSurfaceMessage(message);
 
     default:
@@ -103,49 +86,29 @@
   }
 }
 
-SystemDisplayMetrics DisplayService::OnGetMetrics(pdx::Message& message) {
-  const Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-
-  HeadMountMetrics head_mount = compositor->head_mount_metrics();
-  CompositeHmd hmd(head_mount, hardware_composer_.GetHmdDisplayMetrics());
-  vec2i distorted_render_size = hmd.GetRecommendedRenderTargetSize();
-  FieldOfView left_fov = hmd.GetEyeFov(kLeftEye);
-  FieldOfView right_fov = hmd.GetEyeFov(kRightEye);
-
-  SystemDisplayMetrics metrics;
-
-  metrics.display_native_width = GetDisplayMetrics().width;
-  metrics.display_native_height = GetDisplayMetrics().height;
-  metrics.display_x_dpi = GetDisplayMetrics().dpi.x;
-  metrics.display_y_dpi = GetDisplayMetrics().dpi.y;
-  metrics.distorted_width = distorted_render_size[0];
-  metrics.distorted_height = distorted_render_size[1];
-  metrics.vsync_period_ns =
-      hardware_composer_.native_display_metrics().vsync_period_ns;
-  metrics.hmd_ipd_mm = 0;
-  metrics.inter_lens_distance_m = head_mount.GetInterLensDistance();
-  metrics.left_fov_lrbt[0] = left_fov.GetLeft();
-  metrics.left_fov_lrbt[1] = left_fov.GetRight();
-  metrics.left_fov_lrbt[2] = left_fov.GetBottom();
-  metrics.left_fov_lrbt[3] = left_fov.GetTop();
-  metrics.right_fov_lrbt[0] = right_fov.GetLeft();
-  metrics.right_fov_lrbt[1] = right_fov.GetRight();
-  metrics.right_fov_lrbt[2] = right_fov.GetBottom();
-  metrics.right_fov_lrbt[3] = right_fov.GetTop();
-
-  return metrics;
+Status<display::Metrics> DisplayService::OnGetMetrics(
+    pdx::Message& /*message*/) {
+  return {{static_cast<uint32_t>(GetDisplayMetrics().width),
+           static_cast<uint32_t>(GetDisplayMetrics().height),
+           static_cast<uint32_t>(GetDisplayMetrics().dpi.x),
+           static_cast<uint32_t>(GetDisplayMetrics().dpi.y),
+           static_cast<uint32_t>(
+               hardware_composer_.native_display_metrics().vsync_period_ns),
+           0,
+           0,
+           0,
+           0.0,
+           {},
+           {}}};
 }
 
 // Creates a new DisplaySurface and associates it with this channel. This may
 // only be done once per channel.
-int DisplayService::OnCreateSurface(pdx::Message& message, int width,
-                                    int height, int format, int usage,
-                                    DisplaySurfaceFlags flags) {
+Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
+    pdx::Message& message, const display::SurfaceAttributes& attributes) {
   // A surface may only be created once per channel.
   if (message.GetChannel())
-    return -EINVAL;
+    return ErrorStatus(EINVAL);
 
   ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
            message.GetChannelId());
@@ -153,119 +116,66 @@
   // Use the channel id as the unique surface id.
   const int surface_id = message.GetChannelId();
   const int process_id = message.GetProcessId();
+  const int user_id = message.GetEffectiveUserId();
 
   ALOGI_IF(TRACE,
-           "DisplayService::OnCreateSurface: surface_id=%d process_id=%d "
-           "width=%d height=%d format=%x usage=%x flags=%x",
-           surface_id, process_id, width, height, format, usage, flags);
+           "DisplayService::OnCreateSurface: surface_id=%d process_id=%d",
+           surface_id, process_id);
 
-  // TODO(eieio,jbates): Validate request parameters.
-  auto channel = std::make_shared<DisplaySurface>(
-      this, surface_id, process_id, width, height, format, usage, flags);
+  auto surface_status =
+      DisplaySurface::Create(this, surface_id, process_id, user_id, attributes);
+  if (!surface_status) {
+    ALOGE("DisplayService::OnCreateSurface: Failed to create surface: %s",
+          surface_status.GetErrorMessage().c_str());
+    return ErrorStatus(surface_status.error());
+  }
 
-  message.SetChannel(channel);
-  NotifyDisplayConfigurationUpdate();
-  return 0;
+  SurfaceType surface_type = surface_status.get()->surface_type();
+  display::SurfaceUpdateFlags update_flags =
+      surface_status.get()->update_flags();
+  display::SurfaceInfo surface_info{surface_status.get()->surface_id(),
+                                    surface_status.get()->visible(),
+                                    surface_status.get()->z_order()};
+
+  message.SetChannel(surface_status.take());
+
+  SurfaceUpdated(surface_type, update_flags);
+  return {surface_info};
 }
 
-DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
-  Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-
-  std::vector<std::uint8_t> buffer(sizeof(LateLatchOutput));
-
-  if (!compositor->GetLastEdsPose(
-          reinterpret_cast<LateLatchOutput*>(buffer.data()))) {
-    REPLY_ERROR_RETURN(message, EPERM, {});
+void DisplayService::SurfaceUpdated(SurfaceType surface_type,
+                                    display::SurfaceUpdateFlags update_flags) {
+  ALOGD_IF(TRACE, "DisplayService::SurfaceUpdated: update_flags=%x",
+           update_flags.value());
+  if (update_flags.value() != 0) {
+    if (surface_type == SurfaceType::Application)
+      NotifyDisplayConfigurationUpdate();
+    else
+      UpdateActiveDisplaySurfaces();
   }
-
-  return WrapBuffer(std::move(buffer));
-}
-
-void DisplayService::OnSetViewerParams(pdx::Message& message,
-                                       const ViewerParams& view_params) {
-  Compositor* compositor = hardware_composer_.GetCompositor();
-  if (compositor == nullptr)
-    REPLY_ERROR_RETURN(message, EINVAL);
-
-  FieldOfView left(55.0f, 55.0f, 55.0f, 55.0f);
-  FieldOfView right(55.0f, 55.0f, 55.0f, 55.0f);
-  if (view_params.left_eye_field_of_view_angles.size() >= 4) {
-    left = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[0]),
-                       ToRad(view_params.left_eye_field_of_view_angles[1]),
-                       ToRad(view_params.left_eye_field_of_view_angles[2]),
-                       ToRad(view_params.left_eye_field_of_view_angles[3]));
-    right = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[1]),
-                        ToRad(view_params.left_eye_field_of_view_angles[0]),
-                        ToRad(view_params.left_eye_field_of_view_angles[2]),
-                        ToRad(view_params.left_eye_field_of_view_angles[3]));
-  }
-
-  std::shared_ptr<ColorChannelDistortion> red_distortion;
-  std::shared_ptr<ColorChannelDistortion> green_distortion;
-  std::shared_ptr<ColorChannelDistortion> blue_distortion;
-
-  // We should always have a red distortion.
-  LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
-  red_distortion = std::make_shared<PolynomialRadialDistortion>(
-      view_params.distortion_coefficients_r);
-
-  if (!view_params.distortion_coefficients_g.empty()) {
-    green_distortion = std::make_shared<PolynomialRadialDistortion>(
-        view_params.distortion_coefficients_g);
-  }
-
-  if (!view_params.distortion_coefficients_b.empty()) {
-    blue_distortion = std::make_shared<PolynomialRadialDistortion>(
-        view_params.distortion_coefficients_b);
-  }
-
-  HeadMountMetrics::EyeOrientation left_orientation =
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
-  HeadMountMetrics::EyeOrientation right_orientation =
-      HeadMountMetrics::EyeOrientation::kCCW0Degrees;
-
-  if (view_params.eye_orientations.size() > 1) {
-    left_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
-        view_params.eye_orientations[0]);
-    right_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
-        view_params.eye_orientations[1]);
-  }
-
-  HeadMountMetrics head_mount_metrics(
-      view_params.inter_lens_distance, view_params.tray_to_lens_distance,
-      view_params.screen_to_lens_distance,
-      static_cast<HeadMountMetrics::VerticalAlignment>(
-          view_params.vertical_alignment),
-      left, right, red_distortion, green_distortion, blue_distortion,
-      left_orientation, right_orientation,
-      view_params.screen_center_to_lens_distance);
-
-  compositor->UpdateHeadMountMetrics(head_mount_metrics);
 }
 
 pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
     pdx::Message& /* message */, const std::string& name) {
+  ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
   auto named_buffer = named_buffers_.find(name);
-  if (named_buffer != named_buffers_.end()) {
+  if (named_buffer != named_buffers_.end())
     return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
-  }
-
-  return pdx::ErrorStatus(EINVAL);
+  else
+    return pdx::ErrorStatus(EINVAL);
 }
 
 // Calls the message handler for the DisplaySurface associated with this
 // channel.
-pdx::Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
-  auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
+Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
+  auto surface = std::static_pointer_cast<DisplaySurface>(message.GetChannel());
   ALOGW_IF(!surface,
            "DisplayService::HandleSurfaceMessage: surface is nullptr!");
 
   if (surface)
     return surface->HandleMessage(message);
   else
-    REPLY_ERROR_RETURN(message, EINVAL, {});
+    return ErrorStatus(EINVAL);
 }
 
 std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
@@ -278,14 +188,18 @@
   return GetChannels<DisplaySurface>();
 }
 
-std::vector<std::shared_ptr<DisplaySurface>>
+std::vector<std::shared_ptr<DirectDisplaySurface>>
 DisplayService::GetVisibleDisplaySurfaces() const {
-  std::vector<std::shared_ptr<DisplaySurface>> visible_surfaces;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> visible_surfaces;
 
   ForEachDisplaySurface(
+      SurfaceType::Direct,
       [&](const std::shared_ptr<DisplaySurface>& surface) mutable {
-        if (surface->IsVisible())
-          visible_surfaces.push_back(surface);
+        if (surface->visible()) {
+          visible_surfaces.push_back(
+              std::static_pointer_cast<DirectDisplaySurface>(surface));
+          surface->ClearUpdate();
+        }
       });
 
   return visible_surfaces;
@@ -294,40 +208,21 @@
 void DisplayService::UpdateActiveDisplaySurfaces() {
   auto visible_surfaces = GetVisibleDisplaySurfaces();
 
-  // Sort the surfaces based on manager z order first, then client z order.
   std::sort(visible_surfaces.begin(), visible_surfaces.end(),
             [](const std::shared_ptr<DisplaySurface>& a,
                const std::shared_ptr<DisplaySurface>& b) {
-              return a->manager_z_order() != b->manager_z_order()
-                         ? a->manager_z_order() < b->manager_z_order()
-                         : a->client_z_order() < b->client_z_order();
+              return a->z_order() < b->z_order();
             });
 
   ALOGD_IF(TRACE,
            "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
            visible_surfaces.size());
 
-  // TODO(jbates) Have the shell manage blurred layers.
-  bool blur_requested = false;
-  auto end = visible_surfaces.crend();
-  for (auto it = visible_surfaces.crbegin(); it != end; ++it) {
-    auto surface = *it;
-    // Surfaces with exclude_from_blur==true are not blurred
-    // and are excluded from blur computation of other layers.
-    if (surface->client_exclude_from_blur()) {
-      surface->ManagerSetBlur(0.0f);
-      continue;
-    }
-    surface->ManagerSetBlur(blur_requested ? 1.0f : 0.0f);
-    if (surface->client_blur_behind())
-      blur_requested = true;
-  }
-
   hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
 pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
-    const std::string& name, size_t size, int usage) {
+    const std::string& name, size_t size, uint64_t usage) {
   auto named_buffer = named_buffers_.find(name);
   if (named_buffer == named_buffers_.end()) {
     auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
@@ -354,15 +249,16 @@
     update_notifier_();
 }
 
-int DisplayService::IsVrAppRunning(pdx::Message& message) {
+Status<bool> DisplayService::IsVrAppRunning(pdx::Message& /*message*/) {
   bool visible = false;
   ForEachDisplaySurface(
+      SurfaceType::Application,
       [&visible](const std::shared_ptr<DisplaySurface>& surface) {
-        if (surface->client_z_order() == 0 && surface->IsVisible())
+        if (surface->visible())
           visible = true;
       });
 
-  REPLY_SUCCESS_RETURN(message, visible, 0);
+  return {visible};
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 3b0d07e..bb4eeef 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -2,10 +2,10 @@
 #define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
 
 #include <pdx/service.h>
+#include <pdx/status.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/display_protocol.h>
-#include <private/dvr/late_latch.h>
 
 #include <functional>
 #include <iterator>
@@ -15,12 +15,13 @@
 
 #include "acquired_buffer.h"
 #include "display_surface.h"
+#include "epoll_event_dispatcher.h"
 #include "hardware_composer.h"
 
 namespace android {
 namespace dvr {
 
-// DisplayService implements the displayd display service over ServiceFS.
+// DisplayService implements the display service component of VrFlinger.
 class DisplayService : public pdx::ServiceBase<DisplayService> {
  public:
   bool IsInitialized() const override;
@@ -32,7 +33,7 @@
 
   std::shared_ptr<DisplaySurface> GetDisplaySurface(int surface_id) const;
   std::vector<std::shared_ptr<DisplaySurface>> GetDisplaySurfaces() const;
-  std::vector<std::shared_ptr<DisplaySurface>> GetVisibleDisplaySurfaces()
+  std::vector<std::shared_ptr<DirectDisplaySurface>> GetVisibleDisplaySurfaces()
       const;
 
   // Updates the list of actively displayed surfaces. This must be called after
@@ -40,14 +41,15 @@
   void UpdateActiveDisplaySurfaces();
 
   pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
-      const std::string& name, size_t size, int usage);
+      const std::string& name, size_t size, uint64_t usage);
 
   template <class A>
-  void ForEachDisplaySurface(A action) const {
-    ForEachChannel([action](const ChannelIterator::value_type& pair) mutable {
-      auto surface = std::static_pointer_cast<SurfaceChannel>(pair.second);
-      if (surface->type() == SurfaceTypeEnum::Normal)
-        action(std::static_pointer_cast<DisplaySurface>(surface));
+  void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
+    ForEachChannel([surface_type,
+                    action](const ChannelIterator::value_type& pair) mutable {
+      auto surface = std::static_pointer_cast<DisplaySurface>(pair.second);
+      if (surface->surface_type() == surface_type)
+        action(surface);
     });
   }
 
@@ -75,22 +77,30 @@
 
   friend class VrDisplayStateService;
 
-  DisplayService();
-  DisplayService(android::Hwc2::Composer* hidl);
+  using RequestDisplayCallback = std::function<void(bool)>;
 
-  SystemDisplayMetrics OnGetMetrics(pdx::Message& message);
-  int OnCreateSurface(pdx::Message& message, int width, int height, int format,
-                      int usage, DisplaySurfaceFlags flags);
+  DisplayService(android::Hwc2::Composer* hidl,
+                 RequestDisplayCallback request_display_callback);
 
-  DisplayRPC::ByteBuffer OnGetEdsCapture(pdx::Message& message);
-
-  void OnSetViewerParams(pdx::Message& message,
-                         const ViewerParams& view_params);
   pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
       pdx::Message& message, const std::string& name);
+  pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
+  pdx::Status<display::SurfaceInfo> OnCreateSurface(
+      pdx::Message& message, const display::SurfaceAttributes& attributes);
 
   // Temporary query for current VR status. Will be removed later.
-  int IsVrAppRunning(pdx::Message& message);
+  pdx::Status<bool> IsVrAppRunning(pdx::Message& message);
+
+  pdx::Status<void> AddEventHandler(int fd, int events,
+                                    EpollEventDispatcher::Handler handler) {
+    return dispatcher_.AddEventHandler(fd, events, handler);
+  }
+  pdx::Status<void> RemoveEventHandler(int fd) {
+    return dispatcher_.RemoveEventHandler(fd);
+  }
+
+  void SurfaceUpdated(SurfaceType surface_type,
+                      display::SurfaceUpdateFlags update_flags);
 
   // Called by DisplaySurface to signal that a surface property has changed and
   // the display manager should be notified.
@@ -98,13 +108,15 @@
 
   pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
 
-  DisplayService(const DisplayService&) = delete;
-  void operator=(const DisplayService&) = delete;
-
   HardwareComposer hardware_composer_;
+  RequestDisplayCallback request_display_callback_;
+  EpollEventDispatcher dispatcher_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
   std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+
+  DisplayService(const DisplayService&) = delete;
+  void operator=(const DisplayService&) = delete;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index a7220fe..5829788 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -1,16 +1,21 @@
 #include "display_surface.h"
 
+#include <private/android_filesystem_config.h>
 #include <utils/Trace.h>
 
 #include <private/dvr/platform_defines.h>
+#include <private/dvr/trusted_uids.h>
 
 #include "display_service.h"
 #include "hardware_composer.h"
 
 #define LOCAL_TRACE 1
 
+using android::dvr::display::DisplayProtocol;
 using android::pdx::BorrowedChannelHandle;
+using android::pdx::ErrorStatus;
 using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
 using android::pdx::Message;
 using android::pdx::RemoteChannelHandle;
 using android::pdx::Status;
@@ -20,104 +25,320 @@
 namespace android {
 namespace dvr {
 
-DisplaySurface::DisplaySurface(DisplayService* service, int surface_id,
-                               int process_id, int width, int height,
-                               int format, int usage, int flags)
-    : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
-                     sizeof(DisplaySurfaceMetadata)),
+DisplaySurface::DisplaySurface(DisplayService* service,
+                               SurfaceType surface_type, int surface_id,
+                               int process_id, int user_id,
+                               const display::SurfaceAttributes& attributes)
+    : service_(service),
+      surface_type_(surface_type),
+      surface_id_(surface_id),
       process_id_(process_id),
-      acquired_buffers_(kMaxPostedBuffers),
-      video_mesh_surfaces_updated_(false),
-      width_(width),
-      height_(height),
-      format_(format),
-      usage_(usage),
-      flags_(flags),
-      client_visible_(false),
-      client_z_order_(0),
-      client_exclude_from_blur_(false),
-      client_blur_behind_(false),
-      manager_visible_(false),
-      manager_z_order_(0),
-      manager_blur_(0.0f),
-      layer_order_(0),
-      allocated_buffer_index_(0) {}
+      user_id_(user_id),
+      attributes_(attributes),
+      update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
 
 DisplaySurface::~DisplaySurface() {
   ALOGD_IF(LOCAL_TRACE,
            "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
-           surface_id(), process_id_);
+           surface_id(), process_id());
 }
 
-void DisplaySurface::ManagerSetVisible(bool visible) {
+Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
+  switch (message.GetOp()) {
+    case DisplayProtocol::SetAttributes::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
+          *this, &DisplaySurface::OnSetAttributes, message);
+      break;
+
+    case DisplayProtocol::GetSurfaceInfo::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
+          *this, &DisplaySurface::OnGetSurfaceInfo, message);
+      break;
+
+    case DisplayProtocol::CreateQueue::Opcode:
+      DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
+          *this, &DisplaySurface::OnCreateQueue, message);
+      break;
+  }
+
+  return {};
+}
+
+Status<void> DisplaySurface::OnSetAttributes(
+    pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
+  display::SurfaceUpdateFlags update_flags;
+
+  for (const auto& attribute : attributes) {
+    const auto& key = attribute.first;
+    const auto* variant = &attribute.second;
+    bool invalid_value = false;
+    bool visibility_changed = false;
+
+    // Catch attributes that have significance to the display service.
+    switch (key) {
+      case display::SurfaceAttribute::ZOrder:
+        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
+            variant, [&](const auto& value) {
+              if (z_order_ != value) {
+                visibility_changed = true;
+                z_order_ = value;
+              }
+            });
+        break;
+      case display::SurfaceAttribute::Visible:
+        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
+            variant, [&](const auto& value) {
+              if (visible_ != value) {
+                visibility_changed = true;
+                visible_ = value;
+              }
+            });
+        break;
+    }
+
+    if (invalid_value) {
+      ALOGW(
+          "DisplaySurface::OnClientSetAttributes: Failed to set display "
+          "surface attribute '%d' because of incompatible type: %d",
+          key, variant->index());
+    } else {
+      // Only update the attribute map with valid values.
+      attributes_[attribute.first] = attribute.second;
+
+      // All attribute changes generate a notification, even if the value
+      // doesn't change. Visibility attributes set a flag only if the value
+      // changes.
+      update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
+      if (visibility_changed)
+        update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
+    }
+  }
+
+  SurfaceUpdated(update_flags);
+  return {};
+}
+
+void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
+  ALOGD_IF(TRACE,
+           "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
+           surface_id(), update_flags.value());
+
+  update_flags_.Set(update_flags);
+  service()->SurfaceUpdated(surface_type(), update_flags_);
+}
+
+void DisplaySurface::ClearUpdate() {
+  ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
+  update_flags_ = display::SurfaceUpdateFlags::None;
+}
+
+Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
+    Message& /*message*/) {
+  ALOGD_IF(
+      TRACE,
+      "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
+      surface_id(), visible(), z_order());
+  return {{surface_id(), visible(), z_order()}};
+}
+
+Status<void> DisplaySurface::RegisterQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+  ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
+           surface_id(), consumer_queue->id());
+  // Capture references for the lambda to work around apparent clang bug.
+  // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
+  // capturing self and consumer_queue by copy in the following case:
+  //    auto self = Self();
+  //    [self, consumer_queue](int events) {
+  //        self->OnQueueEvent(consuemr_queue, events); }
+  //
+  struct State {
+    std::shared_ptr<DisplaySurface> surface;
+    std::shared_ptr<ConsumerQueue> queue;
+  };
+  State state{Self(), consumer_queue};
+
+  return service()->AddEventHandler(
+      consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
+      [state](int events) {
+        state.surface->OnQueueEvent(state.queue, events);
+      });
+}
+
+Status<void> DisplaySurface::UnregisterQueue(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+  ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
+           surface_id(), consumer_queue->id());
+  return service()->RemoveEventHandler(consumer_queue->queue_fd());
+}
+
+void DisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
+  ALOGE(
+      "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
+      "called!!!");
+}
+
+std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
+    int32_t queue_id) {
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
+           surface_id(), queue_id);
+
+  auto search = consumer_queues_.find(queue_id);
+  if (search != consumer_queues_.end())
+    return search->second;
+  else
+    return nullptr;
+}
+
+std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+  std::vector<int32_t> queue_ids;
+  for (const auto& entry : consumer_queues_)
+    queue_ids.push_back(entry.first);
+  return queue_ids;
+}
+
+Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
+    Message& /*message*/, size_t meta_size_bytes) {
+  ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
+           "meta_size_bytes=%zu",
+           surface_id(), meta_size_bytes);
+
   std::lock_guard<std::mutex> autolock(lock_);
-  manager_visible_ = visible;
-}
-
-void DisplaySurface::ManagerSetZOrder(int z_order) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  manager_z_order_ = z_order;
-}
-
-void DisplaySurface::ManagerSetBlur(float blur) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  manager_blur_ = blur;
-}
-
-void DisplaySurface::ClientSetVisible(bool visible) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_visible_ = visible;
-}
-
-void DisplaySurface::ClientSetZOrder(int z_order) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_z_order_ = z_order;
-}
-
-void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_exclude_from_blur_ = exclude_from_blur;
-}
-
-void DisplaySurface::ClientSetBlurBehind(bool blur_behind) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  client_blur_behind_ = blur_behind;
-}
-
-void DisplaySurface::DequeueBuffersLocked() {
-  if (consumer_queue_ == nullptr) {
+  auto producer = ProducerQueue::Create(meta_size_bytes);
+  if (!producer) {
     ALOGE(
-        "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+        "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
+        "queue!");
+    return ErrorStatus(ENOMEM);
+  }
+
+  std::shared_ptr<ConsumerQueue> consumer =
+      producer->CreateSilentConsumerQueue();
+  auto status = RegisterQueue(consumer);
+  if (!status) {
+    ALOGE(
+        "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
+        "queue: %s",
+        status.GetErrorMessage().c_str());
+    return status.error_status();
+  }
+
+  consumer_queues_[consumer->id()] = std::move(consumer);
+
+  SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+  return std::move(producer->GetChannelHandle());
+}
+
+void ApplicationDisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+  ALOGD_IF(TRACE,
+           "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+           consumer_queue->id(), events);
+
+  // Always give the queue a chance to handle its internal bookkeeping.
+  consumer_queue->HandleQueueEvents();
+
+  // Check for hangup and remove a queue that is no longer needed.
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (consumer_queue->hung_up()) {
+    ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
+    UnregisterQueue(consumer_queue);
+    auto search = consumer_queues_.find(consumer_queue->id());
+    if (search != consumer_queues_.end()) {
+      consumer_queues_.erase(search);
+    } else {
+      ALOGE(
+          "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
+          consumer_queue->id());
+    }
+    SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+  }
+}
+
+Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
+    Message& /*message*/, size_t meta_size_bytes) {
+  ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
+  ALOGD_IF(
+      TRACE,
+      "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
+      surface_id(), meta_size_bytes);
+
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (!direct_queue_) {
+    auto producer = ProducerQueue::Create(meta_size_bytes);
+    if (!producer) {
+      ALOGE(
+          "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
+          "queue!");
+      return ErrorStatus(ENOMEM);
+    }
+
+    direct_queue_ = producer->CreateConsumerQueue();
+    auto status = RegisterQueue(direct_queue_);
+    if (!status) {
+      ALOGE(
+          "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
+          "queue: %s",
+          status.GetErrorMessage().c_str());
+      return status.error_status();
+    }
+
+    return std::move(producer->GetChannelHandle());
+  } else {
+    return ErrorStatus(EALREADY);
+  }
+}
+
+void DirectDisplaySurface::OnQueueEvent(
+    const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+  ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+           consumer_queue->id(), events);
+
+  // Always give the queue a chance to handle its internal bookkeeping.
+  consumer_queue->HandleQueueEvents();
+
+  // Check for hangup and remove a queue that is no longer needed.
+  std::lock_guard<std::mutex> autolock(lock_);
+  if (consumer_queue->hung_up()) {
+    ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
+    UnregisterQueue(consumer_queue);
+    direct_queue_ = nullptr;
+  }
+}
+
+void DirectDisplaySurface::DequeueBuffersLocked() {
+  if (direct_queue_ == nullptr) {
+    ALOGE(
+        "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
         "initialized.");
     return;
   }
 
-  size_t slot;
-  uint64_t sequence;
   while (true) {
     LocalHandle acquire_fence;
-    auto buffer_consumer =
-        consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
-    if (!buffer_consumer) {
-      ALOGD_IF(TRACE,
-               "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
-               "available buffers.");
+    size_t slot;
+    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
+    if (!buffer_status) {
+      ALOGD_IF(
+          TRACE && buffer_status.error() == ETIMEDOUT,
+          "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
+      ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+               "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
+               "buffer: %s",
+               buffer_status.GetErrorMessage().c_str());
       return;
     }
+    auto buffer_consumer = buffer_status.take();
 
-    // Save buffer index, associated with the buffer id so that it can be looked
-    // up later.
-    int buffer_id = buffer_consumer->id();
-    if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
-      buffer_id_to_index_[buffer_id] = allocated_buffer_index_;
-      ++allocated_buffer_index_;
-    }
-
-    if (!IsVisible()) {
+    if (!visible()) {
       ATRACE_NAME("DropFrameOnInvisibleSurface");
       ALOGD_IF(TRACE,
-               "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
-               "on invisible surface.",
+               "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
+               "buffer_id=%d on invisible surface.",
                buffer_consumer->id());
       buffer_consumer->Discard();
       continue;
@@ -125,34 +346,34 @@
 
     if (acquired_buffers_.IsFull()) {
       ALOGE(
-          "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+          "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
           "overwriting.");
       acquired_buffers_.PopBack();
     }
 
     acquired_buffers_.Append(
-        AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+        AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
   }
 }
 
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
   if (acquired_buffers_.IsEmpty()) {
     ALOGE(
-        "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
-        "none are posted.");
+        "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
+        "when none are posted.");
     return AcquiredBuffer();
   }
   AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
   acquired_buffers_.PopFront();
-  ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+  ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
            buffer.buffer().get());
   return buffer;
 }
 
-AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
+AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
     AcquiredBuffer* skipped_buffer) {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
@@ -175,23 +396,13 @@
     if (frames == 2)
       break;
   }
-  ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+  ALOGD_IF(TRACE,
+           "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
            buffer.buffer().get());
   return buffer;
 }
 
-uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) {
-  std::lock_guard<std::mutex> autolock(lock_);
-
-  if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
-    ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.",
-          buffer_id);
-    return 0;
-  }
-  return buffer_id_to_index_[buffer_id];
-}
-
-bool DisplaySurface::IsBufferAvailable() {
+bool DirectDisplaySurface::IsBufferAvailable() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
@@ -199,158 +410,48 @@
          acquired_buffers_.Front().IsAvailable();
 }
 
-bool DisplaySurface::IsBufferPosted() {
+bool DirectDisplaySurface::IsBufferPosted() {
   std::lock_guard<std::mutex> autolock(lock_);
   DequeueBuffersLocked();
 
   return !acquired_buffers_.IsEmpty();
 }
 
-pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
-  switch (message.GetOp()) {
-    case DisplayRPC::SetAttributes::Opcode:
-      DispatchRemoteMethod<DisplayRPC::SetAttributes>(
-          *this, &DisplaySurface::OnClientSetAttributes, message);
-      break;
-
-    case DisplayRPC::CreateBufferQueue::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
-          *this, &DisplaySurface::OnCreateBufferQueue, message);
-      break;
-
-    case DisplayRPC::CreateVideoMeshSurface::Opcode:
-      DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(
-          *this, &DisplaySurface::OnCreateVideoMeshSurface, message);
-      break;
-
-    default:
-      return SurfaceChannel::HandleMessage(message);
-  }
-
-  return {};
-}
-
-int DisplaySurface::OnClientSetAttributes(
-    pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) {
-  for (const auto& attribute : attributes) {
-    const auto& key = attribute.first;
-    const auto* variant = &attribute.second;
-    bool invalid_value = false;
-    switch (key) {
-      case DisplaySurfaceAttributeEnum::ZOrder:
-        invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetZOrder(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::Visible:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetVisible(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetExcludeFromBlur(value);
-            });
-        break;
-      case DisplaySurfaceAttributeEnum::BlurBehind:
-        invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
-            variant, [this](const auto& value) {
-              DisplaySurface::ClientSetBlurBehind(value);
-            });
-        break;
-      default:
-        ALOGW(
-            "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d "
-            "surface_id=%d",
-            key, surface_id());
-        break;
-    }
-
-    if (invalid_value) {
-      ALOGW(
-          "DisplaySurface::OnClientSetAttributes: Failed to set display "
-          "surface attribute '%s' because of incompatible type: %d",
-          DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
+Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
+    DisplayService* service, int surface_id, int process_id, int user_id,
+    const display::SurfaceAttributes& attributes) {
+  bool direct = false;
+  auto search = attributes.find(display::SurfaceAttribute::Direct);
+  if (search != attributes.end()) {
+    if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
+                                                     &direct)) {
+      ALOGE(
+          "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
+      return ErrorStatus(EINVAL);
     }
   }
 
-  service()->NotifyDisplayConfigurationUpdate();
-  return 0;
-}
+  ALOGD_IF(TRACE,
+           "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
+           "direct=%d",
+           surface_id, process_id, user_id, direct);
 
-LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
-  ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
-
-  if (consumer_queue_ != nullptr) {
-    ALOGE(
-        "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
-        "created and transported to DisplayClient.");
-    REPLY_ERROR_RETURN(message, EALREADY, {});
-  }
-
-  auto producer = ProducerQueue::Create<uint64_t>();
-  consumer_queue_ = producer->CreateConsumerQueue();
-
-  return std::move(producer->GetChannelHandle());
-}
-
-RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
-    pdx::Message& message) {
-  if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: system distortion is "
-        "disabled on this display surface, cannot create VideoMeshSurface on "
-        "top of it.");
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-  }
-
-  int channel_id;
-  auto status = message.PushChannel(0, nullptr, &channel_id);
-  if (!status) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
-        status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, status.error(), {});
-  }
-
-  auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
-  auto channel_status = service()->SetChannel(channel_id, surface);
-  if (!channel_status) {
-    ALOGE(
-        "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
-        "mesh surface channel: %s",
-        channel_status.GetErrorMessage().c_str());
-    REPLY_ERROR_RETURN(message, channel_status.error(), {});
-  }
-
-  {
-    std::lock_guard<std::mutex> autolock(lock_);
-    pending_video_mesh_surfaces_.push_back(surface);
-    video_mesh_surfaces_updated_ = true;
-  }
-
-  return status.take();
-}
-
-std::vector<std::shared_ptr<VideoMeshSurface>>
-DisplaySurface::GetVideoMeshSurfaces() {
-  std::lock_guard<std::mutex> autolock(lock_);
-  std::vector<std::shared_ptr<VideoMeshSurface>> surfaces;
-
-  for (auto& surface : pending_video_mesh_surfaces_) {
-    if (auto video_surface = surface.lock()) {
-      surfaces.push_back(video_surface);
+  if (direct) {
+    const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+    if (trusted) {
+      return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
+          service, surface_id, process_id, user_id, attributes)}};
     } else {
-      ALOGE("Unable to lock video mesh surface.");
+      ALOGE(
+          "DisplaySurface::Create: Direct surfaces may only be created by "
+          "trusted UIDs: user_id=%d",
+          user_id);
+      return ErrorStatus(EPERM);
     }
+  } else {
+    return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
+        service, surface_id, process_id, user_id, attributes)}};
   }
-
-  pending_video_mesh_surfaces_.clear();
-  video_mesh_surfaces_updated_ = false;
-  return surfaces;
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 1fec344..47a07f0 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -3,7 +3,9 @@
 
 #include <pdx/file_handle.h>
 #include <pdx/service.h>
+#include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/display_protocol.h>
+#include <private/dvr/graphics_private.h>
 #include <private/dvr/ring_buffer.h>
 
 #include <functional>
@@ -13,54 +15,136 @@
 #include <vector>
 
 #include "acquired_buffer.h"
-#include "surface_channel.h"
-#include "video_mesh_surface.h"
 
 namespace android {
 namespace dvr {
 
 class DisplayService;
 
-// DisplaySurface is the service-side notion of a client display context. It is
-// responsible for managing display buffer format, geometry, and state, and
-// maintains the buffer consumers connected to the client.
-class DisplaySurface : public SurfaceChannel {
+enum class SurfaceType {
+  Direct,
+  Application,
+};
+
+class DisplaySurface : public pdx::Channel {
  public:
-  DisplaySurface(DisplayService* service, int surface_id, int process_id,
-                 int width, int height, int format, int usage, int flags);
+  static pdx::Status<std::shared_ptr<DisplaySurface>> Create(
+      DisplayService* service, int surface_id, int process_id, int user_id,
+      const display::SurfaceAttributes& attributes);
+
   ~DisplaySurface() override;
 
+  DisplayService* service() const { return service_; }
+  SurfaceType surface_type() const { return surface_type_; }
+  int surface_id() const { return surface_id_; }
   int process_id() const { return process_id_; }
-  int width() const { return width_; }
-  int height() const { return height_; }
-  int format() const { return format_; }
-  int usage() const { return usage_; }
-  int flags() const { return flags_; }
+  int user_id() const { return user_id_; }
 
-  bool client_visible() const { return client_visible_; }
-  int client_z_order() const { return client_z_order_; }
-  bool client_exclude_from_blur() const { return client_exclude_from_blur_; }
-  bool client_blur_behind() const { return client_blur_behind_; }
+  bool visible() const { return visible_; }
+  int z_order() const { return z_order_; }
 
-  bool manager_visible() const { return manager_visible_; }
-  int manager_z_order() const { return manager_z_order_; }
-  float manager_blur() const { return manager_blur_; }
+  const display::SurfaceAttributes& attributes() const { return attributes_; }
+  display::SurfaceUpdateFlags update_flags() const { return update_flags_; }
 
-  bool video_mesh_surfaces_updated() const {
-    return video_mesh_surfaces_updated_;
+  virtual std::vector<int32_t> GetQueueIds() const { return {}; }
+
+  bool IsUpdatePending() const {
+    return update_flags_.value() != display::SurfaceUpdateFlags::None;
   }
 
-  volatile const DisplaySurfaceMetadata* GetMetadataBufferPtr() {
-    if (EnsureMetadataBuffer()) {
-      void* addr = nullptr;
-      metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
-      return static_cast<const volatile DisplaySurfaceMetadata*>(addr);
-    } else {
-      return nullptr;
-    }
+ protected:
+  DisplaySurface(DisplayService* service, SurfaceType surface_type,
+                 int surface_id, int process_id, int user_id,
+                 const display::SurfaceAttributes& attributes);
+
+  // Utility to retrieve a shared pointer to this channel as the desired derived
+  // type.
+  template <
+      typename T = DisplaySurface,
+      typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>>
+  std::shared_ptr<T> Self() {
+    return std::static_pointer_cast<T>(shared_from_this());
   }
 
-  uint32_t GetRenderBufferIndex(int buffer_id);
+  virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) = 0;
+
+  // Registers a consumer queue with the event dispatcher in DisplayService. The
+  // OnQueueEvent callback below is called to handle queue events.
+  pdx::Status<void> RegisterQueue(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue);
+  pdx::Status<void> UnregisterQueue(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue);
+
+  // Called by the event dispatcher in DisplayService when a registered queue
+  // event triggers. Executes on the event dispatcher thread.
+  virtual void OnQueueEvent(
+      const std::shared_ptr<ConsumerQueue>& consumer_queue, int events);
+
+  void SurfaceUpdated(display::SurfaceUpdateFlags update_flags);
+  void ClearUpdate();
+
+  // Synchronizes access to mutable state below between message dispatch thread
+  // and frame post thread.
+  mutable std::mutex lock_;
+
+ private:
+  friend class DisplayService;
+  friend class DisplayManagerService;
+
+  // Dispatches display surface messages to the appropriate handlers. This
+  // handler runs on the VrFlinger message dispatch thread.
+  pdx::Status<void> HandleMessage(pdx::Message& message);
+
+  pdx::Status<void> OnSetAttributes(
+      pdx::Message& message, const display::SurfaceAttributes& attributes);
+  pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message);
+
+  DisplayService* service_;
+  SurfaceType surface_type_;
+  int surface_id_;
+  int process_id_;
+  int user_id_;
+
+  display::SurfaceAttributes attributes_;
+  display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None;
+
+  // Subset of attributes that may be interpreted by the display service.
+  bool visible_ = false;
+  int z_order_ = 0;
+
+  DisplaySurface(const DisplaySurface&) = delete;
+  void operator=(const DisplaySurface&) = delete;
+};
+
+class ApplicationDisplaySurface : public DisplaySurface {
+ public:
+  ApplicationDisplaySurface(DisplayService* service, int surface_id,
+                            int process_id, int user_id,
+                            const display::SurfaceAttributes& attributes)
+      : DisplaySurface(service, SurfaceType::Application, surface_id,
+                       process_id, user_id, attributes) {}
+
+  std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
+  std::vector<int32_t> GetQueueIds() const override;
+
+ private:
+  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) override;
+  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+                    int events) override;
+
+  std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
+};
+
+class DirectDisplaySurface : public DisplaySurface {
+ public:
+  DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
+                       int user_id,
+                       const display::SurfaceAttributes& attributes)
+      : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
+                       user_id, attributes),
+        acquired_buffers_(kMaxPostedBuffers) {}
   bool IsBufferAvailable();
   bool IsBufferPosted();
   AcquiredBuffer AcquireCurrentBuffer();
@@ -69,31 +153,11 @@
   // skipped, it will be stored in skipped_buffer if non null.
   AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer);
 
-  // Display manager interface to control visibility and z order.
-  void ManagerSetVisible(bool visible);
-  void ManagerSetZOrder(int z_order);
-  void ManagerSetBlur(float blur);
-
-  // A surface must be set visible by both the client and the display manager to
-  // be visible on screen.
-  bool IsVisible() const { return client_visible_ && manager_visible_; }
-
-  // A surface is blurred if the display manager requests it.
-  bool IsBlurred() const { return manager_blur_ > 0.0f; }
-
-  // Set by HardwareComposer to the current logical layer order of this surface.
-  void SetLayerOrder(int layer_order) { layer_order_ = layer_order; }
-  // Gets the unique z-order index of this surface among other visible surfaces.
-  // This is not the same as the hardware layer index, as not all display
-  // surfaces map directly to hardware layers. Lower layer orders should be
-  // composited underneath higher layer orders.
-  int layer_order() const { return layer_order_; }
-
-  // Lock all video mesh surfaces so that VideoMeshCompositor can access them.
-  std::vector<std::shared_ptr<VideoMeshSurface>> GetVideoMeshSurfaces();
-
  private:
-  friend class DisplayService;
+  pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+      pdx::Message& message, size_t meta_size_bytes) override;
+  void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+                    int events) override;
 
   // The capacity of the pending buffer queue. Should be enough to hold all the
   // buffers of this DisplaySurface, although in practice only 1 or 2 frames
@@ -104,75 +168,14 @@
   // Returns whether a frame is available without locking the mutex.
   bool IsFrameAvailableNoLock() const;
 
-  // Dispatches display surface messages to the appropriate handlers. This
-  // handler runs on the displayd message dispatch thread.
-  pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
-  // Sets display surface's client-controlled attributes.
-  int OnClientSetAttributes(pdx::Message& message,
-                            const DisplaySurfaceAttributes& attributes);
-
-  // Creates a BufferHubQueue associated with this surface and returns the PDX
-  // handle of its producer side to the client.
-  pdx::LocalChannelHandle OnCreateBufferQueue(pdx::Message& message);
-
-  // Creates a video mesh surface associated with this surface and returns its
-  // PDX handle to the client.
-  pdx::RemoteChannelHandle OnCreateVideoMeshSurface(pdx::Message& message);
-
-  // Client interface (called through IPC) to set visibility and z order.
-  void ClientSetVisible(bool visible);
-  void ClientSetZOrder(int z_order);
-  void ClientSetExcludeFromBlur(bool exclude_from_blur);
-  void ClientSetBlurBehind(bool blur_behind);
-
   // Dequeue all available buffers from the consumer queue.
   void DequeueBuffersLocked();
 
-  DisplaySurface(const DisplaySurface&) = delete;
-  void operator=(const DisplaySurface&) = delete;
-
-  int process_id_;
-
-  // Synchronizes access to mutable state below between message dispatch thread,
-  // epoll event thread, and frame post thread.
-  mutable std::mutex lock_;
-
-  // The consumer end of a BufferHubQueue. VrFlinger allocates and controls the
-  // buffer queue and pass producer end to the app and the consumer end to
-  // compositor.
-  // TODO(jwcai) Add support for multiple buffer queues per display surface.
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-
   // In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
   // posted and pending.
   RingBuffer<AcquiredBuffer> acquired_buffers_;
 
-  // Provides access to VideoMeshSurface. Here we don't want to increase
-  // the reference count immediately on allocation, will leave it into
-  // compositor's hand.
-  std::vector<std::weak_ptr<VideoMeshSurface>> pending_video_mesh_surfaces_;
-  volatile bool video_mesh_surfaces_updated_;
-
-  // Surface parameters.
-  int width_;
-  int height_;
-  int format_;
-  int usage_;
-  int flags_;
-  bool client_visible_;
-  int client_z_order_;
-  bool client_exclude_from_blur_;
-  bool client_blur_behind_;
-  bool manager_visible_;
-  int manager_z_order_;
-  float manager_blur_;
-  int layer_order_;
-
-  // The monotonically increasing index for allocated buffers in this surface.
-  uint32_t allocated_buffer_index_;
-  // Maps from the buffer id to the corresponding allocated buffer index.
-  std::unordered_map<int, uint32_t> buffer_id_to_index_;
+  std::shared_ptr<ConsumerQueue> direct_queue_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
new file mode 100644
index 0000000..06b69bb
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -0,0 +1,142 @@
+#include "epoll_event_dispatcher.h"
+
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/prctl.h>
+
+#include <dvr/performance_client_api.h>
+
+namespace android {
+namespace dvr {
+
+EpollEventDispatcher::EpollEventDispatcher() {
+  epoll_fd_.Reset(epoll_create(64));
+  if (!epoll_fd_) {
+    ALOGE("Failed to create epoll fd: %s", strerror(errno));
+    return;
+  }
+
+  event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  if (!event_fd_) {
+    ALOGE("Failed to create event for epolling: %s", strerror(errno));
+    return;
+  }
+
+  // Add watch for eventfd. This should only watch for EPOLLIN, which gets set
+  // when eventfd_write occurs. Use "this" as a unique sentinal value to
+  // identify events from the event fd.
+  epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}};
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) {
+    ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno));
+    return;
+  }
+
+  thread_ = std::thread(&EpollEventDispatcher::EventThread, this);
+}
+
+EpollEventDispatcher::~EpollEventDispatcher() { Stop(); }
+
+void EpollEventDispatcher::Stop() {
+  exit_thread_.store(true);
+  eventfd_write(event_fd_.Get(), 1);
+}
+
+pdx::Status<void> EpollEventDispatcher::AddEventHandler(int fd, int event_mask,
+                                                        Handler handler) {
+  std::lock_guard<std::mutex> lock(lock_);
+
+  epoll_event event;
+  event.events = event_mask;
+  event.data.ptr = &(handlers_[fd] = handler);
+
+  ALOGD_IF(
+      TRACE,
+      "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p",
+      fd, event_mask, event.data.ptr);
+
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd, &event) < 0) {
+    const int error = errno;
+    ALOGE("Failed to add fd to epoll set because: %s", strerror(error));
+    return pdx::ErrorStatus(error);
+  } else {
+    return {};
+  }
+}
+
+pdx::Status<void> EpollEventDispatcher::RemoveEventHandler(int fd) {
+  ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
+  std::lock_guard<std::mutex> lock(lock_);
+
+  epoll_event dummy;  // See BUGS in man 2 epoll_ctl.
+  if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &dummy) < 0) {
+    const int error = errno;
+    ALOGE("Failed to remove fd from epoll set because: %s", strerror(error));
+    return pdx::ErrorStatus(error);
+  }
+
+  // If the fd was valid above, add it to the list of ids to remove.
+  removed_handlers_.push_back(fd);
+
+  // Wake up the event thread to clean up.
+  eventfd_write(event_fd_.Get(), 1);
+
+  return {};
+}
+
+void EpollEventDispatcher::EventThread() {
+  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrEvent"), 0, 0, 0);
+
+  const int error = dvrSetSchedulerClass(0, "graphics");
+  LOG_ALWAYS_FATAL_IF(
+      error < 0,
+      "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s",
+      strerror(-error));
+
+  const size_t kMaxNumEvents = 128;
+  epoll_event events[kMaxNumEvents];
+
+  while (!exit_thread_.load()) {
+    const int num_events = epoll_wait(epoll_fd_.Get(), events, kMaxNumEvents, -1);
+    if (num_events < 0 && errno != EINTR)
+      break;
+
+    ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
+             num_events);
+
+    for (int i = 0; i < num_events; i++) {
+      ALOGD_IF(
+          TRACE,
+          "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
+          i, events[i].data.ptr, events[i].events);
+
+      if (events[i].data.ptr == this) {
+        // Clear pending event on event_fd_. Serialize the read with respect to
+        // writes from other threads.
+        std::lock_guard<std::mutex> lock(lock_);
+        eventfd_t value;
+        eventfd_read(event_fd_.Get(), &value);
+      } else {
+        auto handler = reinterpret_cast<Handler*>(events[i].data.ptr);
+        if (handler)
+          (*handler)(events[i].events);
+      }
+    }
+
+    // Remove any handlers that have been posted for removal. This is done here
+    // instead of in RemoveEventHandler() to prevent races between the dispatch
+    // thread and the code requesting the removal. Handlers are guaranteed to
+    // stay alive between exiting epoll_wait() and the dispatch loop above.
+    std::lock_guard<std::mutex> lock(lock_);
+    for (auto handler_fd : removed_handlers_) {
+      ALOGD_IF(TRACE,
+               "EpollEventDispatcher::EventThread: removing handler: fd=%d",
+               handler_fd);
+      handlers_.erase(handler_fd);
+    }
+    removed_handlers_.clear();
+  }
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h
new file mode 100644
index 0000000..eb687f4
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.h
@@ -0,0 +1,63 @@
+#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+
+#include <sys/epoll.h>
+
+#include <atomic>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+#include <pdx/file_handle.h>
+#include <pdx/status.h>
+
+namespace android {
+namespace dvr {
+
+class EpollEventDispatcher {
+ public:
+  // Function type for event handlers. The handler receives a bitmask of the
+  // epoll events that occurred on the file descriptor associated with the
+  // handler.
+  using Handler = std::function<void(int)>;
+
+  EpollEventDispatcher();
+  ~EpollEventDispatcher();
+
+  // |handler| is called on the internal dispatch thread when |fd| is signaled
+  // by events in |event_mask|.
+  pdx::Status<void> AddEventHandler(int fd, int event_mask, Handler handler);
+  pdx::Status<void> RemoveEventHandler(int fd);
+
+  void Stop();
+
+ private:
+  void EventThread();
+
+  std::thread thread_;
+  std::atomic<bool> exit_thread_{false};
+
+  // Protects handlers_ and removed_handlers_ and serializes operations on
+  // epoll_fd_ and event_fd_.
+  std::mutex lock_;
+
+  // Maintains a map of fds to event handlers. This is primarily to keep any
+  // references alive that may be bound in the std::function instances. It is
+  // not used at dispatch time to avoid performance problems with different
+  // versions of std::unordered_map.
+  std::unordered_map<int, Handler> handlers_;
+
+  // List of fds to be removed from the map. The actual removal is performed
+  // by the event dispatch thread to avoid races.
+  std::vector<int> removed_handlers_;
+
+  pdx::LocalHandle epoll_fd_;
+  pdx::LocalHandle event_fd_;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index bac9872..079d6fd 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1,9 +1,9 @@
 #include "hardware_composer.h"
 
-#include <log/log.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <fcntl.h>
+#include <log/log.h>
 #include <poll.h>
 #include <sync/sync.h>
 #include <sys/eventfd.h>
@@ -11,23 +11,27 @@
 #include <sys/resource.h>
 #include <sys/system_properties.h>
 #include <sys/timerfd.h>
+#include <time.h>
 #include <unistd.h>
 #include <utils/Trace.h>
 
 #include <algorithm>
+#include <chrono>
 #include <functional>
 #include <map>
 
+#include <dvr/dvr_display_types.h>
 #include <dvr/performance_client_api.h>
 #include <private/dvr/clock_ns.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/ion_buffer.h>
 #include <private/dvr/pose_client_internal.h>
 #include <private/dvr/sync_util.h>
 
-#include "debug_hud_data.h"
-#include "screenshot_service.h"
-
 using android::pdx::LocalHandle;
+using android::pdx::rpc::EmptyVariant;
+using android::pdx::rpc::IfAnyOf;
+
+using namespace std::chrono_literals;
 
 namespace android {
 namespace dvr {
@@ -42,13 +46,8 @@
 // display and the EDS timing coincides with zero pending fences, so this is 0.
 constexpr int kAllowedPendingFenceCount = 0;
 
-// If we think we're going to miss vsync by more than this amount, skip the
-// frame.
-constexpr int64_t kFrameSkipThresholdNs = 4000000;  // 4ms
-
-// Counter PostLayers() deficiency by requiring apps to produce a frame at least
-// 2.5ms before vsync. See b/28881672.
-constexpr int64_t kFrameTimeEstimateMin = 2500000;  // 2.5ms
+// Offset before vsync to submit frames to hardware composer.
+constexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
 
 constexpr size_t kDefaultDisplayConfigCount = 32;
 
@@ -93,44 +92,52 @@
   return (vsync_period_ns * 150) / 100;
 }
 
+// Attempts to set the scheduler class and partiton for the current thread.
+// Returns true on success or false on failure.
+bool SetThreadPolicy(const std::string& scheduler_class,
+                     const std::string& partition) {
+  int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
+  if (error < 0) {
+    ALOGE(
+        "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
+        "thread_id=%d: %s",
+        scheduler_class.c_str(), gettid(), strerror(-error));
+    return false;
+  }
+  error = dvrSetCpuPartition(0, partition.c_str());
+  if (error < 0) {
+    ALOGE(
+        "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
+        "%s",
+        partition.c_str(), gettid(), strerror(-error));
+    return false;
+  }
+  return true;
+}
+
 }  // anonymous namespace
 
-HardwareComposer::HardwareComposer()
-  : HardwareComposer(nullptr) {
-}
+// Layer static data.
+Hwc2::Composer* Layer::hwc2_hidl_;
+const HWCDisplayMetrics* Layer::display_metrics_;
 
-HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
+// HardwareComposer static data;
+constexpr size_t HardwareComposer::kMaxHardwareLayers;
+
+HardwareComposer::HardwareComposer()
+    : HardwareComposer(nullptr, RequestDisplayCallback()) {}
+
+HardwareComposer::HardwareComposer(
+    Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
     : initialized_(false),
       hwc2_hidl_(hwc2_hidl),
-      display_transform_(HWC_TRANSFORM_NONE),
-      active_surfaces_updated_(false),
-      active_layer_count_(0),
-      gpu_layer_(nullptr),
-      post_thread_enabled_(false),
-      post_thread_running_(false),
-      post_thread_quit_requested_(false),
-      post_thread_interrupt_event_fd_(-1),
-      backlight_brightness_fd_(-1),
-      primary_display_vsync_event_fd_(-1),
-      primary_display_wait_pp_fd_(-1),
-      vsync_sleep_timer_fd_(-1),
-      last_vsync_timestamp_(0),
-      vsync_count_(0),
-      frame_skip_count_(0),
-      pose_client_(nullptr) {
-  std::transform(layer_storage_.begin(), layer_storage_.end(), layers_.begin(),
-                 [](auto& layer) { return &layer; });
-
-  callbacks_ = new ComposerCallback;
-}
+      request_display_callback_(request_display_callback),
+      callbacks_(new ComposerCallback) {}
 
 HardwareComposer::~HardwareComposer(void) {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  if (post_thread_.joinable()) {
-    post_thread_quit_requested_ = true;
-    post_thread_cond_var_.notify_all();
+  UpdatePostThreadState(PostThreadState::Quit, true);
+  if (post_thread_.joinable())
     post_thread_.join();
-  }
 }
 
 bool HardwareComposer::Initialize() {
@@ -139,25 +146,25 @@
     return false;
   }
 
-  int32_t ret = HWC2_ERROR_NONE;
+  HWC::Error error = HWC::Error::None;
 
   Hwc2::Config config;
-  ret = (int32_t)hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+  error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
 
-  if (ret != HWC2_ERROR_NONE) {
+  if (error != HWC::Error::None) {
     ALOGE("HardwareComposer: Failed to get current display config : %d",
           config);
     return false;
   }
 
-  ret =
+  error =
       GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
 
-  if (ret != HWC2_ERROR_NONE) {
+  if (error != HWC::Error::None) {
     ALOGE(
         "HardwareComposer: Failed to get display attributes for current "
         "configuration : %d",
-        ret);
+        error.value);
     return false;
   }
 
@@ -173,10 +180,12 @@
   display_transform_ = HWC_TRANSFORM_NONE;
   display_metrics_ = native_display_metrics_;
 
-  post_thread_interrupt_event_fd_.Reset(
-      eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  // Pass hwc instance and metrics to setup globals for Layer.
+  Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
+
+  post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
   LOG_ALWAYS_FATAL_IF(
-      !post_thread_interrupt_event_fd_,
+      !post_thread_event_fd_,
       "HardwareComposer: Failed to create interrupt event fd : %s",
       strerror(errno));
 
@@ -188,38 +197,47 @@
 }
 
 void HardwareComposer::Enable() {
-  std::lock_guard<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = true;
-  post_thread_cond_var_.notify_all();
+  UpdatePostThreadState(PostThreadState::Suspended, false);
 }
 
 void HardwareComposer::Disable() {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = false;
-  if (post_thread_running_) {
-    // Write to the interrupt fd to get fast interrupt of the post thread
-    int error = eventfd_write(post_thread_interrupt_event_fd_.Get(), 1);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not write post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
-
-    post_thread_cond_var_.wait(lock, [this] { return !post_thread_running_; });
-
-    // Read the interrupt fd to clear its state
-    uint64_t interrupt_count= 0;
-    error = eventfd_read(post_thread_interrupt_event_fd_.Get(),
-                         &interrupt_count);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not read post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
-  }
+  UpdatePostThreadState(PostThreadState::Suspended, true);
 }
 
-bool HardwareComposer::PostThreadHasWork() {
-  return !display_surfaces_.empty() ||
-      (active_surfaces_updated_ && !active_surfaces_.empty());
+// Update the post thread quiescent state based on idle and suspended inputs.
+void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
+                                             bool suspend) {
+  std::unique_lock<std::mutex> lock(post_thread_mutex_);
+
+  // Update the votes in the state variable before evaluating the effective
+  // quiescent state. Any bits set in post_thread_state_ indicate that the post
+  // thread should be suspended.
+  if (suspend) {
+    post_thread_state_ |= state;
+  } else {
+    post_thread_state_ &= ~state;
+  }
+
+  const bool quit = post_thread_state_ & PostThreadState::Quit;
+  const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
+  if (quit) {
+    post_thread_quiescent_ = true;
+    eventfd_write(post_thread_event_fd_.Get(), 1);
+    post_thread_wait_.notify_one();
+  } else if (effective_suspend && !post_thread_quiescent_) {
+    post_thread_quiescent_ = true;
+    eventfd_write(post_thread_event_fd_.Get(), 1);
+  } else if (!effective_suspend && post_thread_quiescent_) {
+    post_thread_quiescent_ = false;
+    eventfd_t value;
+    eventfd_read(post_thread_event_fd_.Get(), &value);
+    post_thread_wait_.notify_one();
+  }
+
+  // Wait until the post thread is in the requested state.
+  post_thread_ready_.wait(lock, [this, effective_suspend] {
+    return effective_suspend != post_thread_resumed_;
+  });
 }
 
 void HardwareComposer::OnPostThreadResumed() {
@@ -233,16 +251,17 @@
 
   hwc2_hidl_->resetCommands();
 
-  // Associate each Layer instance with a hardware composer layer.
-  for (auto layer : layers_) {
-    layer->Initialize(hwc2_hidl_.get(), &native_display_metrics_);
-  }
-
   // Connect to pose service.
   pose_client_ = dvrPoseCreate();
   ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
 
+  // HIDL HWC seems to have an internal race condition. If we submit a frame too
+  // soon after turning on VSync we don't get any VSync signals. Give poor HWC
+  // implementations a chance to enable VSync before we continue.
+  EnableVsync(false);
+  std::this_thread::sleep_for(100ms);
   EnableVsync(true);
+  std::this_thread::sleep_for(100ms);
 
   // TODO(skiazyk): We need to do something about accessing this directly,
   // supposedly there is a backlight service on the way.
@@ -251,33 +270,19 @@
   // control of the display back to surface flinger?
   SetBacklightBrightness(255);
 
-  // Initialize the GPU compositor.
-  LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()),
-                      "Failed to initialize the compositor");
-
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "performance");
 }
 
 void HardwareComposer::OnPostThreadPaused() {
-  retire_fence_fds_.clear();
-  gpu_layer_ = nullptr;
-
-  // We have to destroy the layers to fully clear hwc device state before
-  // handing off back to surface flinger
-  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
-    layers_[i]->Reset();
-  }
-
-  active_layer_count_ = 0;
-
   framebuffer_target_.reset();
-
+  retire_fence_fds_.clear();
   display_surfaces_.clear();
-  compositor_surfaces_.clear();
 
-  // Since we're clearing display_surfaces_ we'll need an update.
-  active_surfaces_updated_ = true;
+  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
+    layers_[i].Reset();
+  }
+  active_layer_count_ = 0;
 
   if (pose_client_) {
     dvrPoseDestroy(pose_client_);
@@ -286,50 +291,24 @@
 
   EnableVsync(false);
 
-  frame_time_history_.ResetWithSeed(GuessFrameTime(0));
-  frame_time_backlog_.clear();
-
-  compositor_.Shutdown();
-
   hwc2_hidl_->resetCommands();
 
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "idle");
 }
 
-DisplayMetrics HardwareComposer::GetHmdDisplayMetrics() const {
-  vec2i screen_size(display_metrics_.width, display_metrics_.height);
-  DisplayOrientation orientation =
-      (display_metrics_.width > display_metrics_.height
-           ? DisplayOrientation::kLandscape
-           : DisplayOrientation::kPortrait);
-  float dpi_x = static_cast<float>(display_metrics_.dpi.x) / 1000.0f;
-  float dpi_y = static_cast<float>(display_metrics_.dpi.y) / 1000.0f;
-  float meters_per_pixel_x = kMetersPerInch / dpi_x;
-  float meters_per_pixel_y = kMetersPerInch / dpi_y;
-  vec2 meters_per_pixel(meters_per_pixel_x, meters_per_pixel_y);
-  double frame_duration_s =
-      static_cast<double>(display_metrics_.vsync_period_ns) / 1000000000.0;
-  // TODO(hendrikw): Hard coding to 3mm.  The Pixel is actually 4mm, but it
-  //                 seems that their tray to lens distance is wrong too, which
-  //                 offsets this, at least for the pixel.
-  float border_size = 0.003f;
-  return DisplayMetrics(screen_size, meters_per_pixel, border_size,
-                        static_cast<float>(frame_duration_s), orientation);
-}
-
-int32_t HardwareComposer::Validate(hwc2_display_t display) {
+HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
   uint32_t num_types;
   uint32_t num_requests;
-  int32_t error =
-      (int32_t)hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+  HWC::Error error =
+      hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
 
   if (error == HWC2_ERROR_HAS_CHANGES) {
     // TODO(skiazyk): We might need to inspect the requested changes first, but
     // so far it seems like we shouldn't ever hit a bad state.
     // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
     //                                               display);
-    error = (int32_t)hwc2_hidl_->acceptDisplayChanges(display);
+    error = hwc2_hidl_->acceptDisplayChanges(display);
   }
 
   return error;
@@ -342,13 +321,13 @@
                                              : HWC2_VSYNC_DISABLE));
 }
 
-int32_t HardwareComposer::Present(hwc2_display_t display) {
+HWC::Error HardwareComposer::Present(hwc2_display_t display) {
   int32_t present_fence;
-  int32_t error = (int32_t)hwc2_hidl_->presentDisplay(display, &present_fence);
+  HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
 
   // According to the documentation, this fence is signaled at the time of
   // vsync/DMA for physical displays.
-  if (error == HWC2_ERROR_NONE) {
+  if (error == HWC::Error::None) {
     ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
     retire_fence_fds_.emplace_back(present_fence);
   } else {
@@ -358,82 +337,81 @@
   return error;
 }
 
-int32_t HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
-                                              hwc2_config_t config,
-                                              hwc2_attribute_t attribute,
-                                              int32_t* out_value) const {
-  return (int32_t)hwc2_hidl_->getDisplayAttribute(
+HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+                                                 hwc2_config_t config,
+                                                 hwc2_attribute_t attribute,
+                                                 int32_t* out_value) const {
+  return hwc2_hidl_->getDisplayAttribute(
       display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
 }
 
-int32_t HardwareComposer::GetDisplayMetrics(
+HWC::Error HardwareComposer::GetDisplayMetrics(
     hwc2_display_t display, hwc2_config_t config,
     HWCDisplayMetrics* out_metrics) const {
-  int32_t ret = HWC2_ERROR_NONE;
+  HWC::Error error;
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
-                            &out_metrics->width);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display width");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+                              &out_metrics->width);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
-                            &out_metrics->height);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display height");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+                              &out_metrics->height);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
-                            &out_metrics->vsync_period_ns);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display height");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+                              &out_metrics->vsync_period_ns);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
-                            &out_metrics->dpi.x);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display DPI X");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+                              &out_metrics->dpi.x);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
-                            &out_metrics->dpi.y);
-  if (ret != HWC2_ERROR_NONE) {
-    ALOGE("HardwareComposer: Failed to get display DPI Y");
-    return ret;
+  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+                              &out_metrics->dpi.y);
+  if (error != HWC::Error::None) {
+    ALOGE(
+        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
+        error.to_string().c_str());
+    return error;
   }
 
-  return HWC2_ERROR_NONE;
+  return HWC::Error::None;
 }
 
-void HardwareComposer::Dump(char* buffer, uint32_t* out_size) {
-  std::string debug_str = hwc2_hidl_->dumpDebugInfo();
-  ALOGI("%s", debug_str.c_str());
+std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
 
-  if (buffer == nullptr) {
-    *out_size = debug_str.size();
-  } else {
-    std::copy(debug_str.begin(), debug_str.begin() + *out_size, buffer);
-  }
-}
-
-// TODO(skiazyk): Figure out what to do with `is_geometry_changed`. There does
-// not seem to be any equivalent in the HWC2 API, but that doesn't mean its not
-// there.
-void HardwareComposer::PostLayers(bool /*is_geometry_changed*/) {
+void HardwareComposer::PostLayers() {
   ATRACE_NAME("HardwareComposer::PostLayers");
 
   // Setup the hardware composer layers with current buffers.
   for (size_t i = 0; i < active_layer_count_; i++) {
-    layers_[i]->Prepare();
+    layers_[i].Prepare();
   }
 
-  int32_t ret = Validate(HWC_DISPLAY_PRIMARY);
-  if (ret) {
-    ALOGE("HardwareComposer::Validate failed; ret=%d", ret);
+  HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
+  if (error != HWC::Error::None) {
+    ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
+          error.to_string().c_str());
     return;
   }
 
@@ -462,7 +440,7 @@
              retire_fence_fds_.size());
 
     for (size_t i = 0; i < active_layer_count_; i++) {
-      layers_[i]->Drop();
+      layers_[i].Drop();
     }
     return;
   } else {
@@ -473,55 +451,71 @@
 
 #if TRACE
   for (size_t i = 0; i < active_layer_count_; i++)
-    ALOGI("HardwareComposer::PostLayers: dl[%zu] ctype=0x%08x", i,
-          layers_[i]->GetCompositionType());
+    ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
+          layers_[i].GetCompositionType().to_string().c_str());
 #endif
 
-  ret = Present(HWC_DISPLAY_PRIMARY);
-  if (ret) {
-    ALOGE("HardwareComposer::Present failed; ret=%d", ret);
+  error = Present(HWC_DISPLAY_PRIMARY);
+  if (error != HWC::Error::None) {
+    ALOGE("HardwareComposer::PostLayers: Present failed: %s",
+          error.to_string().c_str());
     return;
   }
 
   std::vector<Hwc2::Layer> out_layers;
   std::vector<int> out_fences;
-  ret = (int32_t)hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
-                                              &out_fences);
-  uint32_t num_elements = out_layers.size();
-
-  ALOGE_IF(ret, "HardwareComposer: GetReleaseFences failed; ret=%d", ret);
+  error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+                                       &out_fences);
+  ALOGE_IF(error != HWC::Error::None,
+           "HardwareComposer::PostLayers: Failed to get release fences: %s",
+           error.to_string().c_str());
 
   // Perform post-frame bookkeeping. Unused layers are a no-op.
+  uint32_t num_elements = out_layers.size();
   for (size_t i = 0; i < num_elements; ++i) {
     for (size_t j = 0; j < active_layer_count_; ++j) {
-      if (layers_[j]->GetLayerHandle() == out_layers[i]) {
-        layers_[j]->Finish(out_fences[i]);
+      if (layers_[j].GetLayerHandle() == out_layers[i]) {
+        layers_[j].Finish(out_fences[i]);
       }
     }
   }
 }
 
 void HardwareComposer::SetDisplaySurfaces(
-    std::vector<std::shared_ptr<DisplaySurface>> surfaces) {
+    std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
   ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
         surfaces.size());
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  active_surfaces_ = std::move(surfaces);
-  active_surfaces_updated_ = true;
-  if (post_thread_enabled_)
-    post_thread_cond_var_.notify_all();
+  const bool display_idle = surfaces.size() == 0;
+  {
+    std::unique_lock<std::mutex> lock(post_thread_mutex_);
+    pending_surfaces_ = std::move(surfaces);
+  }
+
+  // Set idle state based on whether there are any surfaces to handle.
+  UpdatePostThreadState(PostThreadState::Idle, display_idle);
+
+  // XXX: TEMPORARY
+  // Request control of the display based on whether there are any surfaces to
+  // handle. This callback sets the post thread active state once the transition
+  // is complete in SurfaceFlinger.
+  // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
+  // mode. Currently this is hooked up to persistent VR mode, but perhaps this
+  // makes more sense to control it from VrCore, which could in turn base its
+  // decision on persistent VR mode.
+  if (request_display_callback_)
+    request_display_callback_(!display_idle);
 }
 
-int HardwareComposer::PostThreadPollInterruptible(int event_fd,
-                                                  int requested_events) {
+int HardwareComposer::PostThreadPollInterruptible(
+    const pdx::LocalHandle& event_fd, int requested_events) {
   pollfd pfd[2] = {
       {
-          .fd = event_fd,
+          .fd = event_fd.Get(),
           .events = static_cast<short>(requested_events),
           .revents = 0,
       },
       {
-          .fd = post_thread_interrupt_event_fd_.Get(),
+          .fd = post_thread_event_fd_.Get(),
           .events = POLLPRI | POLLIN,
           .revents = 0,
       },
@@ -642,9 +636,8 @@
 // TODO(eieio): This is pretty driver specific, this should be moved to a
 // separate class eventually.
 int HardwareComposer::BlockUntilVSync() {
-  return PostThreadPollInterruptible(primary_display_vsync_event_fd_.Get(),
-                                     // There will be a POLLPRI event on vsync
-                                     POLLPRI);
+  // Vsync is signaled by POLLPRI on the fb vsync node.
+  return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
 }
 
 // Waits for the next vsync and returns the timestamp of the vsync event. If
@@ -683,7 +676,7 @@
     // See how close we are to the next expected vsync. If we're within 1ms,
     // sleep for 1ms and try again.
     const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
-    const int64_t threshold_ns = 1000000;
+    const int64_t threshold_ns = 1000000;  // 1ms
 
     const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
     const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
@@ -695,7 +688,7 @@
         return error;
     } else {
       // Sleep for a short time (1 millisecond) before retrying.
-      error = SleepUntil(GetSystemClockNs() + 1000000);
+      error = SleepUntil(GetSystemClockNs() + threshold_ns);
       if (error < 0 || error == kPostThreadInterrupted)
         return error;
     }
@@ -717,24 +710,18 @@
     return -error;
   }
 
-  return PostThreadPollInterruptible(timer_fd, POLLIN);
+  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
 }
 
 void HardwareComposer::PostThread() {
   // NOLINTNEXTLINE(runtime/int)
   prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
 
-  // Set the scheduler to SCHED_FIFO with high priority.
-  int error = dvrSetSchedulerClass(0, "graphics:high");
-  LOG_ALWAYS_FATAL_IF(
-      error < 0,
-      "HardwareComposer::PostThread: Failed to set scheduler class: %s",
-      strerror(-error));
-  error = dvrSetCpuPartition(0, "/system/performance");
-  LOG_ALWAYS_FATAL_IF(
-      error < 0,
-      "HardwareComposer::PostThread: Failed to set cpu partition: %s",
-      strerror(-error));
+  // Set the scheduler to SCHED_FIFO with high priority. If this fails here
+  // there may have been a startup timing issue between this thread and
+  // performanced. Try again later when this thread becomes active.
+  bool thread_policy_setup =
+      SetThreadPolicy("graphics:high", "/system/performance");
 
 #if ENABLE_BACKLIGHT_BRIGHTNESS
   // TODO(hendrikw): This isn't required at the moment. It's possible that there
@@ -744,7 +731,7 @@
   ALOGW_IF(!backlight_brightness_fd_,
            "HardwareComposer: Failed to open backlight brightness control: %s",
            strerror(errno));
-#endif // ENABLE_BACKLIGHT_BRIGHTNESS
+#endif  // ENABLE_BACKLIGHT_BRIGHTNESS
 
   // Open the vsync event node for the primary display.
   // TODO(eieio): Move this into a platform-specific class.
@@ -783,11 +770,6 @@
   right_eye_photon_offset_ns =
       property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
 
-  compositor_surfaces_.reserve(2);
-
-  constexpr int kFrameTimeBacklogMax = 2;
-  frame_time_backlog_.reserve(kFrameTimeBacklogMax);
-
   // Storage for retrieving fence info.
   FenceInfoBuffer fence_info_buffer;
 
@@ -796,35 +778,42 @@
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
-    {
+    while (post_thread_quiescent_) {
       std::unique_lock<std::mutex> lock(post_thread_mutex_);
-      while (!post_thread_enabled_ || post_thread_quit_requested_ ||
-             !PostThreadHasWork()) {
-        if (was_running) {
-          const char* pause_reason = "unknown";
-          if (!post_thread_enabled_)
-            pause_reason = "disabled";
-          else if (post_thread_quit_requested_)
-            pause_reason = "quit requested";
-          else if (!PostThreadHasWork())
-            pause_reason = "no work";
-          ALOGI("VrHwcPost thread paused. Reason: %s.", pause_reason);
-          OnPostThreadPaused();
-          was_running = false;
-        }
-        post_thread_running_ = false;
-        post_thread_cond_var_.notify_all();
-        if (post_thread_quit_requested_)
-          return;
-        post_thread_cond_var_.wait(lock);
+      ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
+
+      // Tear down resources.
+      OnPostThreadPaused();
+
+      was_running = false;
+      post_thread_resumed_ = false;
+      post_thread_ready_.notify_all();
+
+      if (post_thread_state_ & PostThreadState::Quit) {
+        ALOGI("HardwareComposer::PostThread: Quitting.");
+        return;
       }
-      post_thread_running_ = true;
+
+      post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
+
+      post_thread_resumed_ = true;
+      post_thread_ready_.notify_all();
+
+      ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
     }
 
     if (!was_running) {
-      ALOGI("VrHwcPost thread resumed");
+      // Setup resources.
       OnPostThreadResumed();
       was_running = true;
+
+      // Try to setup the scheduler policy if it failed during startup. Only
+      // attempt to do this on transitions from inactive to active to avoid
+      // spamming the system with RPCs and log messages.
+      if (!thread_policy_setup) {
+        thread_policy_setup =
+            SetThreadPolicy("graphics:high", "/system/performance");
+      }
     }
 
     int64_t vsync_timestamp = 0;
@@ -834,7 +823,7 @@
                vsync_count_ + 1);
       ATRACE_NAME(buf.data());
 
-      error = WaitForVSync(&vsync_timestamp);
+      const int error = WaitForVSync(&vsync_timestamp);
       ALOGE_IF(
           error < 0,
           "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
@@ -854,74 +843,27 @@
                                 ns_per_frame, right_eye_photon_offset_ns);
     }
 
-    bool layer_config_changed = UpdateLayerConfig();
-
-    if (!was_running || layer_config_changed) {
-      frame_time_history_.ResetWithSeed(
-          GuessFrameTime(compositor_surfaces_.size()));
-      frame_time_backlog_.clear();
-    } else {
-      UpdateFrameTimeHistory(&frame_time_backlog_, kFrameTimeBacklogMax,
-                             &fence_info_buffer, &frame_time_history_);
-    }
-
-    // Get our current best estimate at how long the next frame will take to
-    // render, based on how long previous frames took to render. Use this
-    // estimate to decide when to wake up for EDS.
-    int64_t frame_time_estimate =
-        frame_time_history_.GetSampleCount() == 0
-            ? GuessFrameTime(compositor_surfaces_.size())
-            : frame_time_history_.GetAverage();
-    frame_time_estimate = std::max(frame_time_estimate, kFrameTimeEstimateMin);
-    DebugHudData::data.hwc_latency = frame_time_estimate;
+    const bool layer_config_changed = UpdateLayerConfig();
 
     // Signal all of the vsync clients. Because absolute time is used for the
     // wakeup time below, this can take a little time if necessary.
     if (vsync_callback_)
-      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp, frame_time_estimate,
-                      vsync_count_);
+      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
+                      /*frame_time_estimate*/ 0, vsync_count_);
 
     {
-      // Sleep until async EDS wakeup time.
+      // Sleep until shortly before vsync.
       ATRACE_NAME("sleep");
 
-      int64_t display_time_est = vsync_timestamp + ns_per_frame;
-      int64_t now = GetSystemClockNs();
-      int64_t frame_finish_time_est = now + frame_time_estimate;
-      int64_t sleep_time_ns = display_time_est - now - frame_time_estimate;
+      const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
+      const int64_t now_ns = GetSystemClockNs();
+      const int64_t sleep_time_ns =
+          display_time_est_ns - now_ns - kFramePostOffsetNs;
+      const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
 
       ATRACE_INT64("sleep_time_ns", sleep_time_ns);
-      if (frame_finish_time_est - display_time_est >= kFrameSkipThresholdNs) {
-        ATRACE_INT("frame_skip_count", ++frame_skip_count_);
-        ALOGE(
-            "HardwareComposer::PostThread: Missed frame schedule, drop "
-            "frame. Expected frame miss: %.1fms",
-            static_cast<double>(frame_finish_time_est - display_time_est) /
-                1000000);
-
-        // There are several reasons we might skip a frame, but one possibility
-        // is we mispredicted the frame time. Clear out the frame time history.
-        frame_time_history_.ResetWithSeed(
-            GuessFrameTime(compositor_surfaces_.size()));
-        frame_time_backlog_.clear();
-        DebugHudData::data.hwc_frame_stats.SkipFrame();
-
-        if (layer_config_changed) {
-          // If the layer config changed we need to validateDisplay() even if
-          // we're going to drop the frame, to flush the Composer object's
-          // internal command buffer and apply our layer changes.
-          Validate(HWC_DISPLAY_PRIMARY);
-        }
-
-        continue;
-      } else {
-        // Make the transition more obvious in systrace when the frame skip
-        // happens above.
-        ATRACE_INT("frame_skip_count", 0);
-      }
-
       if (sleep_time_ns > 0) {
-        error = SleepUntil(display_time_est - frame_time_estimate);
+        int error = SleepUntil(wakeup_time_ns);
         ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
                  strerror(-error));
         if (error == kPostThreadInterrupted) {
@@ -936,314 +878,58 @@
       }
     }
 
-    DebugHudData::data.hwc_frame_stats.AddFrame();
-
-    int64_t frame_start_time = GetSystemClockNs();
-
-    // Setup the output buffer for the compositor. This needs to happen before
-    // you draw with the compositor.
-    if (gpu_layer_ != nullptr) {
-      gpu_layer_->UpdateDirectBuffer(compositor_.GetBuffer());
-    }
-
-    // Call PostLayers now before performing the GL code for the compositor to
-    // avoid missing the deadline that can cause the lower-level hwc to get
-    // permanently backed up.
-    PostLayers(layer_config_changed);
-
-    PostCompositorBuffers();
-
-    if (gpu_layer_ != nullptr) {
-      // Note, with scanline racing, this draw is timed along with the post
-      // layers to finish just in time.
-      LocalHandle frame_fence_fd;
-      compositor_.DrawFrame(vsync_count_ + 1, &frame_fence_fd);
-      if (frame_fence_fd) {
-        LOG_ALWAYS_FATAL_IF(frame_time_backlog_.size() >= kFrameTimeBacklogMax,
-                            "Frame time backlog exceeds capacity");
-        frame_time_backlog_.push_back(
-            {frame_start_time, std::move(frame_fence_fd)});
-      }
-    } else if (!layer_config_changed) {
-      frame_time_history_.AddSample(GetSystemClockNs() - frame_start_time);
-    }
-
-    HandlePendingScreenshots();
+    PostLayers();
   }
 }
 
+// Checks for changes in the surface stack and updates the layer config to
+// accomodate the new stack.
 bool HardwareComposer::UpdateLayerConfig() {
-  std::vector<std::shared_ptr<DisplaySurface>> old_display_surfaces;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
   {
-    std::lock_guard<std::mutex> lock(post_thread_mutex_);
-    if (!active_surfaces_updated_)
+    std::unique_lock<std::mutex> lock(post_thread_mutex_);
+    if (pending_surfaces_.empty())
       return false;
-    old_display_surfaces = display_surfaces_;
-    display_surfaces_ = active_surfaces_;
-    active_surfaces_updated_ = false;
+
+    surfaces = std::move(pending_surfaces_);
   }
 
-  DebugHudData::data.ResetLayers();
-
-  // Figure out whether we need to update hardware layers. If this surface
-  // change does not add or remove hardware layers we can avoid display hiccups
-  // by gracefully updating only the GPU compositor layers.
-  int old_gpu_layer_count = 0;
-  int new_gpu_layer_count = 0;
-  bool hardware_layers_need_update = false;
-  // Look for new hardware layers and count new GPU layers.
-  for (const auto& surface : display_surfaces_) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++new_gpu_layer_count;
-    else if (std::find(old_display_surfaces.begin(), old_display_surfaces.end(),
-                       surface) == old_display_surfaces.end())
-      // This is a new hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Look for deleted hardware layers or compositor layers.
-  for (const auto& surface : old_display_surfaces) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++old_gpu_layer_count;
-    else if (std::find(display_surfaces_.begin(), display_surfaces_.end(),
-                       surface) == display_surfaces_.end())
-      // This is a deleted hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Check for compositor hardware layer transition.
-  if ((!old_gpu_layer_count && new_gpu_layer_count) ||
-      (old_gpu_layer_count && !new_gpu_layer_count))
-    hardware_layers_need_update = true;
-
-  // Set the chosen layer order for all surfaces.
-  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-    display_surfaces_[i]->SetLayerOrder(static_cast<int>(i));
-  }
-
-  // Update compositor layers.
-  {
-    ATRACE_NAME("UpdateLayerConfig_GpuLayers");
-    compositor_.UpdateSurfaces(display_surfaces_);
-    compositor_surfaces_.clear();
-    for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-      const auto& surface = display_surfaces_[i];
-      if (!(surface->flags() &
-            DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) {
-        compositor_surfaces_.push_back(surface);
-      }
-    }
-  }
-
-  if (!hardware_layers_need_update)
-    return true;
-
-  // Update hardware layers.
-
   ATRACE_NAME("UpdateLayerConfig_HwLayers");
 
-  // Update the display layers in a non-destructive fashion.
+  display_surfaces_.clear();
 
-  // Create a map from surface id to hardware layer
-  std::map<int, Layer*> display_surface_layers;
-
-  for (size_t i = 0; i < active_layer_count_; ++i) {
-    auto layer = layers_[i];
-    int surface_id = layer->GetSurfaceId();
-
-    auto found =
-        std::find_if(display_surfaces_.begin(), display_surfaces_.end(),
-                     [surface_id](const auto& surface) {
-                       return surface->surface_id() == surface_id;
-                     });
-
-    if (found != display_surfaces_.end()) {
-      display_surface_layers[surface_id] = layer;
-    }
+  Layer* target_layer;
+  size_t layer_index;
+  for (layer_index = 0;
+       layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
+       layer_index++) {
+    // The bottom layer is opaque, other layers blend.
+    HWC::BlendMode blending =
+        layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
+    layers_[layer_index].Setup(surfaces[layer_index], blending,
+                               display_transform_, HWC::Composition::Device,
+                               layer_index);
+    display_surfaces_.push_back(surfaces[layer_index]);
   }
 
-  bool has_gpu_layer = std::any_of(
-      display_surfaces_.begin(), display_surfaces_.end(),
-      [](const auto& surface) {
-        return !(surface->flags() &
-                 DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION);
-      });
+  // Clear unused layers.
+  for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
+    layers_[i].Reset();
 
-  if (!has_gpu_layer) {
-    gpu_layer_ = nullptr;
-  }
-
-  auto is_layer_active = [&display_surface_layers, has_gpu_layer](auto layer) {
-    int surface_id = layer->GetSurfaceId();
-    if (surface_id >= 0) {
-      return display_surface_layers.count(surface_id) > 0;
-    } else {
-      return has_gpu_layer;
-    }
-  };
-
-  // Compress the in-use layers to the top of the list
-  auto part = std::partition(
-      layers_.begin(), layers_.begin() + active_layer_count_, is_layer_active);
-
-  size_t new_active_layer_count = part - layers_.begin();
-
-  // Clear any unused layers
-  for (size_t i = new_active_layer_count; i < active_layer_count_; ++i) {
-    layers_[i]->Reset();
-  }
-
-  active_layer_count_ = new_active_layer_count;
-
-  bool gpu_layer_applied = false;
-
-  // Create/update all of the hardware layers
-  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-    const auto& surface = display_surfaces_[i];
-    bool is_hw_surface =
-        surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION;
-    hwc2_blend_mode_t blending =
-        i == 0 ? HWC2_BLEND_MODE_NONE : HWC2_BLEND_MODE_COVERAGE;
-
-    DebugHudData::data.SetLayerInfo(
-        i, surface->width(), surface->height(),
-        !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2));
-
-    if (!is_hw_surface && gpu_layer_applied) {
-      continue;
-    }
-
-    Layer* target_layer;
-    bool existing_layer = false;
-
-    if (is_hw_surface) {
-      auto it = display_surface_layers.find(surface->surface_id());
-
-      if (it != display_surface_layers.end()) {
-        target_layer = it->second;
-        existing_layer = true;
-      }
-    } else if (gpu_layer_ != nullptr) {
-      target_layer = gpu_layer_;
-      existing_layer = true;
-    }
-
-    if (!existing_layer) {
-      if (active_layer_count_ >= kMaxHardwareLayers) {
-        ALOGI("HardwareComposer: More than %d hardware layers requested.",
-              kMaxHardwareLayers);
-        break;
-      } else {
-        target_layer = layers_[active_layer_count_];
-        ++active_layer_count_;
-      }
-
-      ALOGD_IF(TRACE,
-               "HardwareComposer::UpdateLayerConfig: (new) surface_id=%d -> "
-               "layer=%zd",
-               surface->surface_id(), i);
-
-      if (is_hw_surface) {
-        target_layer->Setup(surface, blending, display_transform_,
-                            HWC2_COMPOSITION_DEVICE, i);
-      } else {
-        gpu_layer_ = target_layer;
-        target_layer->Setup(compositor_.GetBuffer(), blending,
-                            display_transform_, HWC2_COMPOSITION_DEVICE, i);
-      }
-    } else {
-      ALOGD_IF(TRACE,
-               "HardwareComposer::UpdateLayerConfig: (retained) surface_id=%d "
-               "-> layer=%zd",
-               surface->surface_id(), i);
-
-      target_layer->SetBlending(blending);
-      target_layer->SetZOrderIndex(i);
-      target_layer->UpdateLayerSettings();
-    }
-
-    gpu_layer_applied = !is_hw_surface;
-  }
-
+  active_layer_count_ = layer_index;
   ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
            active_layer_count_);
 
+  // Any surfaces left over could not be assigned a hardware layer and will
+  // not be displayed.
+  ALOGW_IF(surfaces.size() != display_surfaces_.size(),
+           "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
+           "pending_surfaces=%zu display_surfaces=%zu",
+           surfaces.size(), display_surfaces_.size());
+
   return true;
 }
 
-void HardwareComposer::PostCompositorBuffers() {
-  ATRACE_NAME("PostCompositorBuffers");
-  for (const auto& surface : compositor_surfaces_) {
-    compositor_.PostBuffer(surface);
-  }
-}
-
-void HardwareComposer::UpdateFrameTimeHistory(
-    std::vector<FrameTimeMeasurementRecord>* backlog, int backlog_max,
-    FenceInfoBuffer* fence_info_buffer, FrameTimeHistory* history) {
-  while (!backlog->empty()) {
-    const auto& frame_time_record = backlog->front();
-    int64_t end_time = 0;
-    bool frame_finished = CheckFrameFinished(frame_time_record.fence.Get(),
-                                             fence_info_buffer, &end_time);
-    if (frame_finished) {
-      int64_t frame_duration = end_time - frame_time_record.start_time;
-      history->AddSample(frame_duration);
-      // Our backlog is tiny (2 elements), so erasing from the front is ok
-      backlog->erase(backlog->begin());
-    } else {
-      break;
-    }
-  }
-
-  if (backlog->size() == static_cast<size_t>(backlog_max)) {
-    // Yikes, something must've gone wrong if our oldest frame hasn't finished
-    // yet. Give up on waiting for it.
-    const auto& stale_frame_time_record = backlog->front();
-    int64_t frame_duration =
-        GetSystemClockNs() - stale_frame_time_record.start_time;
-    backlog->erase(backlog->begin());
-    history->AddSample(frame_duration);
-    ALOGW("Frame didn't finish after %.1fms",
-          static_cast<double>(frame_duration) / 1000000);
-  }
-}
-
-bool HardwareComposer::CheckFrameFinished(int frame_fence_fd,
-                                          FenceInfoBuffer* fence_info_buffer,
-                                          int64_t* timestamp) {
-  int result = -1;
-  int sync_result = sync_wait(frame_fence_fd, 0);
-  if (sync_result == 0) {
-    result =
-        GetFenceSignaledTimestamp(frame_fence_fd, fence_info_buffer, timestamp);
-    if (result < 0) {
-      ALOGE("Failed getting signaled timestamp from fence");
-    }
-  } else if (errno != ETIME) {
-    ALOGE("sync_wait on frame fence failed");
-  }
-  return result >= 0;
-}
-
-void HardwareComposer::HandlePendingScreenshots() {
-  // Take a screenshot of the requested layer, if available.
-  // TODO(eieio): Look into using virtual displays to composite the layer stack
-  // into a single output buffer that can be returned to the screenshot clients.
-  if (active_layer_count_ > 0) {
-    if (auto screenshot_service = ScreenshotService::GetInstance()) {
-      if (screenshot_service->IsScreenshotRequestPending()) {
-        ATRACE_NAME("screenshot");
-        screenshot_service->TakeIfNeeded(layers_, compositor_);
-      }
-    } else {
-      ALOGW(
-          "HardwareComposer::HandlePendingScreenshots: Failed to get "
-          "screenshot service!");
-    }
-  }
-}
-
 void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
   vsync_callback_ = callback;
 }
@@ -1280,145 +966,133 @@
   }
 }
 
-Layer::Layer()
-    : hwc2_hidl_(nullptr),
-      surface_index_(-1),
-      hardware_composer_layer_(0),
-      display_metrics_(nullptr),
-      blending_(HWC2_BLEND_MODE_NONE),
-      transform_(HWC_TRANSFORM_NONE),
-      composition_type_(HWC2_COMPOSITION_DEVICE),
-      surface_rect_functions_applied_(false) {}
-
-void Layer::Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics) {
+void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+                              const HWCDisplayMetrics* metrics) {
   hwc2_hidl_ = hwc2_hidl;
   display_metrics_ = metrics;
 }
 
 void Layer::Reset() {
-  const int ret = acquired_buffer_.Release(std::move(release_fence_));
-  ALOGE_IF(ret < 0, "Layer::Reset: failed to release buffer: %s",
-           strerror(-ret));
-
   if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
     hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
     hardware_composer_layer_ = 0;
   }
 
-  surface_index_ = static_cast<size_t>(-1);
-  blending_ = HWC2_BLEND_MODE_NONE;
-  transform_ = HWC_TRANSFORM_NONE;
-  composition_type_ = HWC2_COMPOSITION_DEVICE;
-  direct_buffer_ = nullptr;
-  surface_ = nullptr;
-  acquire_fence_fd_.Close();
+  z_order_ = 0;
+  blending_ = HWC::BlendMode::None;
+  transform_ = HWC::Transform::None;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type_;
+  source_ = EmptyVariant{};
+  acquire_fence_.Close();
   surface_rect_functions_applied_ = false;
 }
 
-void Layer::Setup(const std::shared_ptr<DisplaySurface>& surface,
-                  hwc2_blend_mode_t blending, hwc_transform_t transform,
-                  hwc2_composition_t composition_type, size_t index) {
+void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+                  HWC::BlendMode blending, HWC::Transform transform,
+                  HWC::Composition composition_type, size_t z_order) {
   Reset();
-  surface_index_ = index;
-  surface_ = surface;
+  z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
-  composition_type_ = composition_type;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type;
+  source_ = SourceSurface{surface};
   CommonLayerSetup();
 }
 
 void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
-                  hwc2_blend_mode_t blending, hwc_transform_t transform,
-                  hwc2_composition_t composition_type, size_t z_order) {
+                  HWC::BlendMode blending, HWC::Transform transform,
+                  HWC::Composition composition_type, size_t z_order) {
   Reset();
-  surface_index_ = z_order;
-  direct_buffer_ = buffer;
+  z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
-  composition_type_ = composition_type;
+  composition_type_ = HWC::Composition::Invalid;
+  target_composition_type_ = composition_type;
+  source_ = SourceBuffer{buffer};
   CommonLayerSetup();
 }
 
-void Layer::UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer) {
-  direct_buffer_ = buffer;
+void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
+  if (source_.is<SourceBuffer>())
+    std::get<SourceBuffer>(source_) = {buffer};
 }
 
-void Layer::SetBlending(hwc2_blend_mode_t blending) { blending_ = blending; }
-
-void Layer::SetZOrderIndex(int z_index) { surface_index_ = z_index; }
+void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
+void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
 
 IonBuffer* Layer::GetBuffer() {
-  if (direct_buffer_)
-    return direct_buffer_.get();
-  else if (acquired_buffer_.IsAvailable())
-    return acquired_buffer_.buffer()->buffer();
-  else
-    return nullptr;
+  struct Visitor {
+    IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
+    IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
+    IonBuffer* operator()(EmptyVariant) { return nullptr; }
+  };
+  return source_.Visit(Visitor{});
 }
 
 void Layer::UpdateLayerSettings() {
   if (!IsLayerSetup()) {
-    ALOGE("HardwareComposer: Trying to update layers data on an unused layer.");
+    ALOGE(
+        "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
+        "unused Layer!");
     return;
   }
 
-  int32_t ret = HWC2_ERROR_NONE;
-
+  HWC::Error error;
   hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
-  ret = (int32_t)hwc2_hidl_->setLayerCompositionType(
+  error = hwc2_hidl_->setLayerCompositionType(
       display, hardware_composer_layer_,
-      (Hwc2::IComposerClient::Composition)composition_type_);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer composition type : %d",
-           ret);
-  // ret = (int32_t) hwc2_hidl_->setLayerTransform(display,
-  // hardware_composer_layer_,
-  //                                    (Hwc2::IComposerClient::Transform)
-  //                                    transform_);
-  // ALOGE_IF(ret, "HardwareComposer: Error setting layer transform : %d", ret);
+      composition_type_.cast<Hwc2::IComposerClient::Composition>());
+  ALOGE_IF(
+      error != HWC::Error::None,
+      "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
+      error.to_string().c_str());
 
-  // ret = hwc2_funcs_->set_layer_blend_mode_fn_(
-  //    hardware_composer_device_, display, hardware_composer_layer_,
-  //    blending_);
-  ret = (int32_t)hwc2_hidl_->setLayerBlendMode(
+  error = hwc2_hidl_->setLayerBlendMode(
       display, hardware_composer_layer_,
-      (Hwc2::IComposerClient::BlendMode)blending_);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer blend mode : %d", ret);
+      blending_.cast<Hwc2::IComposerClient::BlendMode>());
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+           error.to_string().c_str());
 
-  Hwc2::IComposerClient::Rect display_frame;
-  display_frame.left = 0;
-  display_frame.top = 0;
-  display_frame.right = display_metrics_->width;
-  display_frame.bottom = display_metrics_->height;
-  ret = (int32_t)hwc2_hidl_->setLayerDisplayFrame(
-      display, hardware_composer_layer_, display_frame);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer display frame : %d",
-           ret);
+  // TODO(eieio): Use surface attributes or some other mechanism to control
+  // the layer display frame.
+  error = hwc2_hidl_->setLayerDisplayFrame(
+      display, hardware_composer_layer_,
+      {0, 0, display_metrics_->width, display_metrics_->height});
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
+           error.to_string().c_str());
 
-  std::vector<Hwc2::IComposerClient::Rect> visible_region(1);
-  visible_region[0] = display_frame;
-  ret = (int32_t)hwc2_hidl_->setLayerVisibleRegion(
-      display, hardware_composer_layer_, visible_region);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer visible region : %d",
-           ret);
+  error = hwc2_hidl_->setLayerVisibleRegion(
+      display, hardware_composer_layer_,
+      {{0, 0, display_metrics_->width, display_metrics_->height}});
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
+           error.to_string().c_str());
 
-  ret = (int32_t)hwc2_hidl_->setLayerPlaneAlpha(display,
-                                                hardware_composer_layer_, 1.0f);
-  ALOGE_IF(ret, "HardwareComposer: Error setting layer plane alpha : %d", ret);
+  error =
+      hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
+           error.to_string().c_str());
 
-  ret = (int32_t)hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_,
-                                            surface_index_);
-  ALOGE_IF(ret, "HardwareComposer: Error, setting z order index : %d", ret);
+  error =
+      hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+  ALOGE_IF(error != HWC::Error::None,
+           "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+           error.to_string().c_str());
 }
 
 void Layer::CommonLayerSetup() {
-  int32_t ret = (int32_t)hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY,
-                                                 &hardware_composer_layer_);
-
-  ALOGE_IF(ret,
-           "HardwareComposer: Failed to create layer on primary display : %d",
-           ret);
-
+  HWC::Error error =
+      hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+  ALOGE_IF(
+      error != HWC::Error::None,
+      "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
+      error.to_string().c_str());
   UpdateLayerSettings();
 }
 
@@ -1426,114 +1100,69 @@
   int right, bottom;
   sp<GraphicBuffer> handle;
 
-  if (surface_) {
-    // Only update the acquired buffer when one is either available or this is
-    // the first time through.
-    if (surface_->IsBufferAvailable()) {
-      // If we previously set this to a solid color layer to stall for time,
-      // revert it to a device layer.
-      if (acquired_buffer_.IsEmpty() &&
-          composition_type_ != HWC2_COMPOSITION_DEVICE) {
-        composition_type_ = HWC2_COMPOSITION_DEVICE;
-        hwc2_hidl_->setLayerCompositionType(
-            HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-            (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_DEVICE);
-      }
+  // Acquire the next buffer according to the type of source.
+  IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
+    std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
+  });
 
-      DebugHudData::data.AddLayerFrame(surface_index_);
-      acquired_buffer_.Release(std::move(release_fence_));
-      acquired_buffer_ = surface_->AcquireCurrentBuffer();
-
-      // Basic latency stopgap for when the application misses a frame:
-      // If the application recovers on the 2nd or 3rd (etc) frame after
-      // missing, this code will skip a frame to catch up by checking if
-      // the next frame is also available.
-      if (surface_->IsBufferAvailable()) {
-        DebugHudData::data.SkipLayerFrame(surface_index_);
-        ATRACE_NAME("DropToCatchUp");
-        ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
-        acquired_buffer_ = surface_->AcquireCurrentBuffer();
-      }
-      ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
-    } else if (acquired_buffer_.IsEmpty()) {
-      // While we are waiting for a buffer, set this to be an empty layer
-      if (composition_type_ != HWC2_COMPOSITION_SOLID_COLOR) {
-        composition_type_ = HWC2_COMPOSITION_SOLID_COLOR;
-        hwc2_hidl_->setLayerCompositionType(
-            HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-            (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_SOLID_COLOR);
-
-        Hwc2::IComposerClient::Color layer_color = {
-            0, 0, 0, 0,
-        };
-        hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-                                  layer_color);
-      }
-      return;
+  // When a layer is first setup there may be some time before the first buffer
+  // arrives. Setup the HWC layer as a solid color to stall for time until the
+  // first buffer arrives. Once the first buffer arrives there will always be a
+  // buffer for the frame even if it is old.
+  if (!handle.get()) {
+    if (composition_type_ == HWC::Composition::Invalid) {
+      composition_type_ = HWC::Composition::SolidColor;
+      hwc2_hidl_->setLayerCompositionType(
+          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          composition_type_.cast<Hwc2::IComposerClient::Composition>());
+      Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
+      hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+                                layer_color);
+    } else {
+      // The composition type is already set. Nothing else to do until a
+      // buffer arrives.
     }
-    right = acquired_buffer_.buffer()->width();
-    bottom = acquired_buffer_.buffer()->height();
-    handle = acquired_buffer_.buffer()->buffer()->buffer();
-    acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
   } else {
-    // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
-    // mechanism to accept distorted layers from VrCore.
-    right = direct_buffer_->width();
-    bottom = direct_buffer_->height();
-    handle = direct_buffer_->buffer();
-    acquire_fence_fd_.Close();
-  }
+    if (composition_type_ != target_composition_type_) {
+      composition_type_ = target_composition_type_;
+      hwc2_hidl_->setLayerCompositionType(
+          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+          composition_type_.cast<Hwc2::IComposerClient::Composition>());
+    }
 
-  int32_t ret = HWC2_ERROR_NONE;
+    HWC::Error error{HWC::Error::None};
+    error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+                                       hardware_composer_layer_, 0, handle,
+                                       acquire_fence_.Get());
 
-  if (composition_type_ == HWC2_COMPOSITION_DEVICE) {
-    ret = (int32_t)hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
-                                              hardware_composer_layer_, 0,
-                                              handle,
-                                              acquire_fence_fd_.Get());
+    ALOGE_IF(error != HWC::Error::None,
+             "Layer::Prepare: Error setting layer buffer: %s",
+             error.to_string().c_str());
 
-    ALOGE_IF(ret, "HardwareComposer: Error setting layer buffer : %d", ret);
-  }
+    if (!surface_rect_functions_applied_) {
+      const float float_right = right;
+      const float float_bottom = bottom;
+      error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+                                             hardware_composer_layer_,
+                                             {0, 0, float_right, float_bottom});
 
-  if (!surface_rect_functions_applied_) {
-    Hwc2::IComposerClient::FRect crop_rect = {
-        0, 0, static_cast<float>(right), static_cast<float>(bottom),
-    };
-    hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
-                                   hardware_composer_layer_, crop_rect);
+      ALOGE_IF(error != HWC::Error::None,
+               "Layer::Prepare: Error setting layer source crop: %s",
+               error.to_string().c_str());
 
-    ALOGE_IF(ret, "HardwareComposer: Error setting layer source crop : %d",
-             ret);
-
-// TODO(skiazyk): why is this ifdef'd out. Is if a driver-specific issue where
-// it must/cannot be called?
-#ifdef QCOM_BSP
-    hwc_rect_t damage_rect = {
-        0, 0, right, bottom,
-    };
-    hwc_region_t damage = {
-        1, &damage_rect,
-    };
-    // ret = hwc2_funcs_->set_layer_surface_damage(
-    //    hardware_composer_device_, HWC_DISPLAY_PRIMARY,
-    //    hardware_composer_layer_, damage);
-    // uses a std::vector as the listing
-    // hwc2_hidl_->setLayerSurfaceDamage(HWC_DISPLAY_PRIMARY,
-    // hardware_composer_layer_, vector here);
-
-    ALOGE_IF(ret, "HardwareComposer: Error settings layer surface damage : %d",
-             ret);
-#endif
-
-    surface_rect_functions_applied_ = true;
+      surface_rect_functions_applied_ = true;
+    }
   }
 }
 
 void Layer::Finish(int release_fence_fd) {
-  release_fence_.Reset(release_fence_fd);
+  IfAnyOf<SourceSurface, SourceBuffer>::Call(
+      &source_, [release_fence_fd](auto& source) {
+        source.Finish(LocalHandle(release_fence_fd));
+      });
 }
 
-void Layer::Drop() { acquire_fence_fd_.Close(); }
+void Layer::Drop() { acquire_fence_.Close(); }
 
 }  // namespace dvr
 }  // namespace android
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index e570cb6..5a75f42 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -1,13 +1,12 @@
 #ifndef ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
 #define ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
 
-#include <log/log.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer2.h>
+#include <ui/GraphicBuffer.h>
+#include "DisplayHardware/ComposerHal.h"
+#include "hwc_types.h"
 
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/sync_util.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
 
 #include <array>
 #include <condition_variable>
@@ -17,17 +16,16 @@
 #include <tuple>
 #include <vector>
 
+#include <dvr/pose_client.h>
 #include <pdx/file_handle.h>
+#include <pdx/rpc/variant.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <private/dvr/frame_time_history.h>
 #include <private/dvr/sync_util.h>
 
 #include "acquired_buffer.h"
-#include "compositor.h"
 #include "display_surface.h"
 
-#include "DisplayHardware/ComposerHal.h"
-
 // Hardware composer HAL doesn't define HWC_TRANSFORM_NONE as of this writing.
 #ifndef HWC_TRANSFORM_NONE
 #define HWC_TRANSFORM_NONE static_cast<hwc_transform_t>(0)
@@ -53,29 +51,28 @@
 // source supplying buffers for the layer's contents.
 class Layer {
  public:
-  Layer();
+  Layer() {}
 
-  // Sets the hardware composer layer and display metrics that this Layer should
-  // use each Prepare cycle. This class does not own either of these pointers,
-  // which MUST remain valid for its lifetime. This method MUST be called once
-  // in the life of the instance before any other method is valid to call.
-  void Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics);
+  // Sets up the global state used by all Layer instances. This must be called
+  // before using any Layer methods.
+  static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+                                const HWCDisplayMetrics* metrics);
 
   // Releases any shared pointers and fence handles held by this instance.
   void Reset();
 
   // Sets up the layer to use a display surface as its content source. The Layer
-  // will automatically handle ACQUIRE/RELEASE phases for the surface's buffer
-  // train every frame.
+  // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
+  // every frame.
   //
   // |blending| receives HWC_BLENDING_* values.
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  // |index| is the index of this surface in the DisplaySurface array.
-  void Setup(const std::shared_ptr<DisplaySurface>& surface,
-             hwc2_blend_mode_t blending, hwc_transform_t transform,
-             hwc2_composition_t composition_type, size_t index);
+  // |index| is the index of this surface in the DirectDisplaySurface array.
+  void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+             HWC::BlendMode blending, HWC::Transform transform,
+             HWC::Composition composition_type, size_t z_roder);
 
   // Sets up the layer to use a direct buffer as its content source. No special
   // handling of the buffer is performed; responsibility for updating or
@@ -85,13 +82,13 @@
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  void Setup(const std::shared_ptr<IonBuffer>& buffer,
-             hwc2_blend_mode_t blending, hwc_transform_t transform,
-             hwc2_composition_t composition_type, size_t z_order);
+  void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+             HWC::Transform transform, HWC::Composition composition_type,
+             size_t z_order);
 
   // Layers that use a direct IonBuffer should call this each frame to update
   // which buffer will be used for the next PostLayers.
-  void UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer);
+  void UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer);
 
   // Sets up the hardware composer layer for the next frame. When the layer is
   // associated with a display surface, this method automatically ACQUIRES a new
@@ -107,10 +104,10 @@
   void Finish(int release_fence_fd);
 
   // Sets the blending for the layer. |blending| receives HWC_BLENDING_* values.
-  void SetBlending(hwc2_blend_mode_t blending);
+  void SetBlending(HWC::BlendMode blending);
 
-  // Sets the Z-order of this layer
-  void SetZOrderIndex(int surface_index);
+  // Sets the z-order of this layer
+  void SetZOrder(size_t z_order);
 
   // Gets the current IonBuffer associated with this layer. Ownership of the
   // buffer DOES NOT pass to the caller and the pointer is not guaranteed to
@@ -118,57 +115,111 @@
   // Layer::Reset(). YOU HAVE BEEN WARNED.
   IonBuffer* GetBuffer();
 
-  hwc2_composition_t GetCompositionType() const { return composition_type_; }
-
-  hwc2_layer_t GetLayerHandle() const { return hardware_composer_layer_; }
-
-  bool UsesDirectBuffer() const { return direct_buffer_ != nullptr; }
-
-  bool IsLayerSetup() const {
-    return direct_buffer_ != nullptr || surface_ != nullptr;
-  }
+  HWC::Composition GetCompositionType() const { return composition_type_; }
+  HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
+  bool IsLayerSetup() const { return !source_.empty(); }
 
   // Applies all of the settings to this layer using the hwc functions
   void UpdateLayerSettings();
 
   int GetSurfaceId() const {
-    if (surface_ != nullptr) {
-      return surface_->surface_id();
-    } else {
-      return -1;
-    }
+    int surface_id = -1;
+    pdx::rpc::IfAnyOf<SourceSurface>::Call(
+        &source_, [&surface_id](const SourceSurface& surface_source) {
+          surface_id = surface_source.surface->surface_id();
+        });
+    return surface_id;
   }
 
  private:
   void CommonLayerSetup();
 
-  Hwc2::Composer* hwc2_hidl_;
-
-  // Original display surface array index for tracking purposes.
-  size_t surface_index_;
+  static Hwc2::Composer* hwc2_hidl_;
+  static const HWCDisplayMetrics* display_metrics_;
 
   // The hardware composer layer and metrics to use during the prepare cycle.
-  hwc2_layer_t hardware_composer_layer_;
-  HWCDisplayMetrics* display_metrics_;
+  hwc2_layer_t hardware_composer_layer_ = 0;
 
   // Layer properties used to setup the hardware composer layer during the
   // Prepare phase.
-  hwc2_blend_mode_t blending_;
-  hwc_transform_t transform_;
-  hwc2_composition_t composition_type_;
+  size_t z_order_ = 0;
+  HWC::BlendMode blending_ = HWC::BlendMode::None;
+  HWC::Transform transform_ = HWC::Transform::None;
+  HWC::Composition composition_type_ = HWC::Composition::Invalid;
+  HWC::Composition target_composition_type_ = HWC::Composition::Device;
 
-  // These two members are mutually exclusive. When direct_buffer_ is set the
-  // Layer gets its contents directly from that buffer; when surface_ is set the
-  // Layer gets it contents from the surface's buffer train.
-  std::shared_ptr<IonBuffer> direct_buffer_;
-  std::shared_ptr<DisplaySurface> surface_;
+  // State when the layer is connected to a surface. Provides the same interface
+  // as SourceBuffer to simplify internal use by Layer.
+  struct SourceSurface {
+    std::shared_ptr<DirectDisplaySurface> surface;
+    AcquiredBuffer acquired_buffer;
+    pdx::LocalHandle release_fence;
 
-  // State when associated with a display surface.
-  AcquiredBuffer acquired_buffer_;
-  pdx::LocalHandle release_fence_;
+    SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+        : surface(surface) {}
 
-  pdx::LocalHandle acquire_fence_fd_;
-  bool surface_rect_functions_applied_;
+    // Attempts to acquire a new buffer from the surface and return a tuple with
+    // width, height, buffer handle, and fence. If a new buffer is not available
+    // the previous buffer is returned or an empty value if no buffer has ever
+    // been posted. When a new buffer is acquired the previous buffer's release
+    // fence is passed out automatically.
+    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+      if (surface->IsBufferAvailable()) {
+        acquired_buffer.Release(std::move(release_fence));
+        acquired_buffer = surface->AcquireCurrentBuffer();
+        ATRACE_ASYNC_END("BufferPost", acquired_buffer.buffer()->id());
+      }
+      if (!acquired_buffer.IsEmpty()) {
+        return std::make_tuple(acquired_buffer.buffer()->width(),
+                               acquired_buffer.buffer()->height(),
+                               acquired_buffer.buffer()->buffer()->buffer(),
+                               acquired_buffer.ClaimAcquireFence());
+      } else {
+        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+      }
+    }
+
+    void Finish(pdx::LocalHandle fence) { release_fence = std::move(fence); }
+
+    // Gets a pointer to the current acquired buffer or returns nullptr if there
+    // isn't one.
+    IonBuffer* GetBuffer() {
+      if (acquired_buffer.IsAvailable())
+        return acquired_buffer.buffer()->buffer();
+      else
+        return nullptr;
+    }
+
+    // Returns the surface id of the surface.
+    int GetSurfaceId() { return surface->surface_id(); }
+  };
+
+  // State when the layer is connected to a buffer. Provides the same interface
+  // as SourceSurface to simplify internal use by Layer.
+  struct SourceBuffer {
+    std::shared_ptr<IonBuffer> buffer;
+
+    std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+      if (buffer)
+        return std::make_tuple(buffer->width(), buffer->height(),
+                               buffer->buffer(), pdx::LocalHandle{});
+      else
+        return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+    }
+
+    void Finish(pdx::LocalHandle /*fence*/) {}
+
+    IonBuffer* GetBuffer() { return buffer.get(); }
+
+    int GetSurfaceId() const { return -1; }
+  };
+
+  // The underlying hardware composer layer is supplied buffers either from a
+  // surface buffer train or from a buffer directly.
+  pdx::rpc::Variant<SourceSurface, SourceBuffer> source_;
+
+  pdx::LocalHandle acquire_fence_;
+  bool surface_rect_functions_applied_ = false;
 
   Layer(const Layer&) = delete;
   void operator=(const Layer&) = delete;
@@ -186,13 +237,15 @@
  public:
   // Type for vsync callback.
   using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
+  using RequestDisplayCallback = std::function<void(bool)>;
 
   // Since there is no universal way to query the number of hardware layers,
   // just set it to 4 for now.
-  static constexpr int kMaxHardwareLayers = 4;
+  static constexpr size_t kMaxHardwareLayers = 4;
 
   HardwareComposer();
-  HardwareComposer(Hwc2::Composer* hidl);
+  HardwareComposer(Hwc2::Composer* hidl,
+                   RequestDisplayCallback request_display_callback);
   ~HardwareComposer();
 
   bool Initialize();
@@ -207,14 +260,14 @@
   void Disable();
 
   // Get the HMD display metrics for the current display.
-  DisplayMetrics GetHmdDisplayMetrics() const;
+  display::Metrics GetHmdDisplayMetrics() const;
 
-  int32_t GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
-                              hwc2_attribute_t attributes,
-                              int32_t* out_value) const;
-  int32_t GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
-                            HWCDisplayMetrics* out_metrics) const;
-  void Dump(char* buffer, uint32_t* out_size);
+  HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+                                 hwc2_attribute_t attributes,
+                                 int32_t* out_value) const;
+  HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
+                               HWCDisplayMetrics* out_metrics) const;
+  std::string Dump();
 
   void SetVSyncCallback(VSyncCallback callback);
 
@@ -229,11 +282,9 @@
     return native_display_metrics_;
   }
 
-  // Set the display surface stack to compose to the display each frame.
+  // Sets the display surfaces to compose the hardware layer stack.
   void SetDisplaySurfaces(
-      std::vector<std::shared_ptr<DisplaySurface>> surfaces);
-
-  Compositor* GetCompositor() { return &compositor_; }
+      std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces);
 
   void OnHardwareComposerRefresh();
 
@@ -265,23 +316,36 @@
     }
   };
 
-  int32_t Validate(hwc2_display_t display);
-  int32_t Present(hwc2_display_t display);
+  HWC::Error Validate(hwc2_display_t display);
+  HWC::Error Present(hwc2_display_t display);
 
   void SetBacklightBrightness(int brightness);
 
-  void PostLayers(bool is_geometry_changed);
+  void PostLayers();
   void PostThread();
 
-  // Check to see if we have a value written to post_thread_interrupt_event_fd_,
-  // indicating a control thread interrupted the post thread. This clears the
-  // post_thread_interrupt_event_fd_ state in the process. Returns true if an
-  // interrupt was requested.
-  bool CheckPostThreadInterruptEventFd();
+  // The post thread has two controlling states:
+  // 1. Idle: no work to do (no visible surfaces).
+  // 2. Suspended: explicitly halted (system is not in VR mode).
+  // When either #1 or #2 is true then the post thread is quiescent, otherwise
+  // it is active.
+  using PostThreadStateType = uint32_t;
+  struct PostThreadState {
+    enum : PostThreadStateType {
+      Active = 0,
+      Idle = (1 << 0),
+      Suspended = (1 << 1),
+      Quit = (1 << 2),
+    };
+  };
+
+  void UpdatePostThreadState(uint32_t state, bool suspend);
+
   // Blocks until either event_fd becomes readable, or we're interrupted by a
   // control thread. Any errors are returned as negative errno values. If we're
   // interrupted, kPostThreadInterrupted will be returned.
-  int PostThreadPollInterruptible(int event_fd, int requested_events);
+  int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
+                                  int requested_events);
 
   // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
   // on the post thread that can be interrupted by a control thread. If
@@ -294,49 +358,21 @@
 
   bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
 
-  // Returns true if the layer config changed, false otherwise
+  // Reconfigures the layer stack if the display surfaces changed since the last
+  // frame. Called only from the post thread.
   bool UpdateLayerConfig();
-  void PostCompositorBuffers();
-
-  // Return true if the post thread has work to do (i.e. there are visible
-  // surfaces to post to the screen). Must be called with post_thread_mutex_
-  // locked. Called only from the post thread.
-  bool PostThreadHasWork();
 
   // Called on the post thread when the post thread is resumed.
   void OnPostThreadResumed();
   // Called on the post thread when the post thread is paused or quits.
   void OnPostThreadPaused();
 
-  struct FrameTimeMeasurementRecord {
-    int64_t start_time;
-    pdx::LocalHandle fence;
-
-    FrameTimeMeasurementRecord(FrameTimeMeasurementRecord&&) = default;
-    FrameTimeMeasurementRecord& operator=(FrameTimeMeasurementRecord&&) =
-        default;
-    FrameTimeMeasurementRecord(const FrameTimeMeasurementRecord&) = delete;
-    FrameTimeMeasurementRecord& operator=(const FrameTimeMeasurementRecord&) =
-        delete;
-  };
-
-  void UpdateFrameTimeHistory(std::vector<FrameTimeMeasurementRecord>* backlog,
-                              int backlog_max,
-                              FenceInfoBuffer* fence_info_buffer,
-                              FrameTimeHistory* history);
-
-  // Returns true if the frame finished rendering, false otherwise. If the frame
-  // finished the frame end time is stored in timestamp. Doesn't block.
-  bool CheckFrameFinished(int frame_fence_fd,
-                          FenceInfoBuffer* fence_info_buffer,
-                          int64_t* timestamp);
-
-  void HandlePendingScreenshots();
-
   bool initialized_;
 
-  // Hardware composer HAL device.
-  std::unique_ptr<Hwc2::Composer> hwc2_hidl_;
+  // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
+  // this pointer.
+  Hwc2::Composer* hwc2_hidl_;
+  RequestDisplayCallback request_display_callback_;
   sp<ComposerCallback> callbacks_;
 
   // Display metrics of the physical display.
@@ -345,69 +381,39 @@
   // landscape.
   HWCDisplayMetrics display_metrics_;
   // Transform required to get from native to logical display orientation.
-  hwc_transform_t display_transform_;
+  HWC::Transform display_transform_ = HWC::Transform::None;
 
   // Buffer for the background layer required by hardware composer.
   std::shared_ptr<IonBuffer> framebuffer_target_;
 
-  // Protects access to variables used by the post thread and one of the control
-  // threads (either the vr flinger dispatcher thread or the surface flinger
-  // main thread). This includes active_surfaces_, active_surfaces_updated_,
-  // post_thread_enabled_, post_thread_running_, and
-  // post_thread_quit_requested_.
-  std::mutex post_thread_mutex_;
-
-  // Surfaces configured by the display manager. Written by the vr flinger
-  // dispatcher thread, read by the post thread.
-  std::vector<std::shared_ptr<DisplaySurface>> active_surfaces_;
-  // active_surfaces_updated_ is set to true by the vr flinger dispatcher thread
-  // when the list of active surfaces changes. active_surfaces_updated_ will be
-  // set back to false by the post thread when it processes the update.
-  bool active_surfaces_updated_;
+  // Pending surface list. Set by the display service when DirectSurfaces are
+  // added, removed, or change visibility. Written by the message dispatch
+  // thread and read by the post thread.
+  std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
 
   // The surfaces displayed by the post thread. Used exclusively by the post
   // thread.
-  std::vector<std::shared_ptr<DisplaySurface>> display_surfaces_;
-
-  // The surfaces rendered by the compositor. Used exclusively by the post
-  // thread.
-  std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces_;
+  std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
 
   // Layer array for handling buffer flow into hardware composer layers.
-  // Note that the first array is the actual storage for the layer objects,
-  // and the latter is an array of pointers, which can be freely re-arranged
-  // without messing up the underlying objects.
-  std::array<Layer, kMaxHardwareLayers> layer_storage_;
-  std::array<Layer*, kMaxHardwareLayers> layers_;
-  size_t active_layer_count_;
-
-  // Set by the Post thread to the index of the GPU compositing output
-  // buffer in the layers_ array.
-  Layer* gpu_layer_;
+  std::array<Layer, kMaxHardwareLayers> layers_;
+  size_t active_layer_count_ = 0;
 
   // Handler to hook vsync events outside of this class.
   VSyncCallback vsync_callback_;
 
   // The layer posting thread. This thread wakes up a short time before vsync to
-  // hand buffers to post processing and the results to hardware composer.
+  // hand buffers to hardware composer.
   std::thread post_thread_;
 
-  // Set to true if the post thread is allowed to run. Surface flinger and vr
-  // flinger share access to the display, and vr flinger shouldn't use the
-  // display while surface flinger is using it. While surface flinger owns the
-  // display, post_thread_enabled_ will be set to false to indicate the post
-  // thread shouldn't run.
-  bool post_thread_enabled_;
-  // Set to true by the post thread if it's currently running.
-  bool post_thread_running_;
-  // Set to true if the post thread should quit. Only set when destroying the
-  // HardwareComposer instance.
-  bool post_thread_quit_requested_;
-  // Used to wake the post thread up while it's waiting for vsync or sleeping
-  // until EDS preemption, for faster transition to the paused state.
-  pdx::LocalHandle post_thread_interrupt_event_fd_;
-  // Used to communicate between the control thread and the post thread.
-  std::condition_variable post_thread_cond_var_;
+  // Post thread state machine and synchronization primitives.
+  PostThreadStateType post_thread_state_{PostThreadState::Idle};
+  std::atomic<bool> post_thread_quiescent_{true};
+  bool post_thread_resumed_{false};
+  pdx::LocalHandle post_thread_event_fd_;
+  std::mutex post_thread_mutex_;
+  std::condition_variable post_thread_wait_;
+  std::condition_variable post_thread_ready_;
 
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
@@ -422,16 +428,13 @@
   pdx::LocalHandle vsync_sleep_timer_fd_;
 
   // The timestamp of the last vsync.
-  int64_t last_vsync_timestamp_;
+  int64_t last_vsync_timestamp_ = 0;
 
   // Vsync count since display on.
-  uint32_t vsync_count_;
+  uint32_t vsync_count_ = 0;
 
   // Counter tracking the number of skipped frames.
-  int frame_skip_count_;
-
-  // After construction, only accessed on post_thread_.
-  Compositor compositor_;
+  int frame_skip_count_ = 0;
 
   // Fd array for tracking retire fences that are returned by hwc. This allows
   // us to detect when the display driver begins queuing frames.
@@ -439,16 +442,7 @@
 
   // Pose client for frame count notifications. Pose client predicts poses
   // out to display frame boundaries, so we need to tell it about vsyncs.
-  DvrPose* pose_client_;
-
-  // Our history of frame times. This is used to get a better estimate of how
-  // long the next frame will take, to set a schedule for EDS.
-  FrameTimeHistory frame_time_history_;
-
-  // The backlog is used to allow us to start rendering the next frame before
-  // the previous frame has finished, and still get an accurate measurement of
-  // frame duration.
-  std::vector<FrameTimeMeasurementRecord> frame_time_backlog_;
+  DvrPose* pose_client_ = nullptr;
 
   static constexpr int kPostThreadInterrupted = 1;
 
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
new file mode 100644
index 0000000..cbf636c
--- /dev/null
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -0,0 +1,300 @@
+#ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H
+#define ANDROID_LIBVRFLINGER_HWCTYPES_H
+
+// General HWC type support. Hardware composer type support is a bit of a mess
+// between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the
+// use of enum classes, which make analogous types between versions much
+// harder to deal with in a uniform way.
+//
+// These utilities help address some of these pains by providing a type-safe,
+// flexible interface to translate between different type spaces.
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <string>
+#include <type_traits>
+
+namespace HWC {
+
+// Value types derived from HWC HAL types. Some of these are stand-alone,
+// while others are also wrapped in translator classes below.
+using ColorMode = int32_t;  // android_color_mode_t;
+using Config = hwc2_config_t;
+using ColorTransform =
+    std::underlying_type<android_color_transform_t>::type;          // int32_t;
+using Dataspace = std::underlying_type<android_dataspace_t>::type;  // int32_t;
+using DisplayId = hwc2_display_t;
+using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type;
+using Hdr = std::underlying_type<android_hdr_t>::type;  // int32_t;
+using Layer = hwc2_layer_t;
+using PixelFormat =
+    std::underlying_type<android_pixel_format_t>::type;  // int32_t;
+
+// Type traits and casting utilities.
+
+// SFINAE utility to evaluate type expressions.
+template <typename...>
+using TestTypeExpression = void;
+
+// Traits type to determine the underlying type of an enum, integer,
+// or wrapper class.
+template <typename T, typename = typename std::is_enum<T>::type,
+          typename = typename std::is_integral<T>::type, typename = void>
+struct UnderlyingType {
+  using Type = T;
+};
+// Partial specialization that matches enum types. Captures the underlying type
+// of the enum in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::true_type, std::false_type> {
+  using Type = typename std::underlying_type<T>::type;
+};
+// Partial specialization that matches integral types. Captures the type of the
+// integer in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::true_type> {
+  using Type = T;
+};
+// Partial specialization that matches the wrapper types below. Captures
+// wrapper member type ValueType in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::false_type,
+                      TestTypeExpression<typename T::ValueType>> {
+  using Type = typename T::ValueType;
+};
+
+// Enable if T is an enum with underlying type U.
+template <typename T, typename U, typename ReturnType = void>
+using EnableIfMatchingEnum = typename std::enable_if<
+    std::is_enum<T>::value &&
+        std::is_same<U, typename UnderlyingType<T>::Type>::value,
+    ReturnType>::type;
+
+// Enable if T and U are the same size/alignment and have the same underlying
+// type. Handles enum, integral, and wrapper classes below.
+template <typename T, typename U, typename Return = void>
+using EnableIfSafeCast = typename std::enable_if<
+    sizeof(T) == sizeof(U) && alignof(T) == alignof(U) &&
+        std::is_same<typename UnderlyingType<T>::Type,
+                     typename UnderlyingType<U>::Type>::value,
+    Return>::type;
+
+// Safely cast between std::vectors of matching enum/integer/wraper types.
+// Normally this is not possible with pendantic compiler type checks. However,
+// given the same size, alignment, and underlying type this is safe due to
+// allocator requirements and array-like element access guarantees.
+template <typename T, typename U>
+EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) {
+  return reinterpret_cast<std::vector<T>*>(in);
+}
+
+// Translator classes that wrap specific HWC types to make translating
+// between different types (especially enum class) in code cleaner.
+
+// Base type for the enum wrappers below. This type provides type definitions
+// and implicit conversion logic common to each wrapper type.
+template <typename EnumType>
+struct Wrapper {
+  // Alias type of this instantiantion of Wrapper. Useful for inheriting
+  // constructors in subclasses via "using Base::Base;" statements.
+  using Base = Wrapper<EnumType>;
+
+  // The enum type wrapped by this instantiation of Wrapper.
+  using BaseType = EnumType;
+
+  // The underlying type of the base enum type.
+  using ValueType = typename UnderlyingType<BaseType>::Type;
+
+  // A default constructor is not defined here. Subclasses should define one
+  // as appropriate to define the correct inital value for the enum type.
+
+  // Default copy constructor.
+  Wrapper(const Wrapper&) = default;
+
+  // Implicit conversion from ValueType.
+  Wrapper(ValueType value) : value(value) {}
+
+  // Implicit conversion from BaseType.
+  Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
+
+  // Implicit conversion from an enum type of the same underlying type.
+  template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+  Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
+
+  // Implicit conversion to BaseType.
+  operator BaseType() const { return static_cast<BaseType>(value); }
+
+  // Implicit conversion to ValueType.
+  operator ValueType() const { return value; }
+
+  template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+  T cast() const {
+    return static_cast<T>(value);
+  }
+
+  // Converts to string using HWC2 stringification of BaseType.
+  std::string to_string() const {
+    return HWC2::to_string(static_cast<BaseType>(value));
+  }
+
+  bool operator!=(const Wrapper& other) const { return value != other.value; }
+  bool operator!=(ValueType other_value) const { return value != other_value; }
+  bool operator!=(BaseType other_value) const {
+    return static_cast<BaseType>(value) != other_value;
+  }
+  bool operator==(const Wrapper& other) const { return value == other.value; }
+  bool operator==(ValueType other_value) const { return value == other_value; }
+  bool operator==(BaseType other_value) const {
+    return static_cast<BaseType>(value) == other_value;
+  }
+
+  ValueType value;
+};
+
+struct Attribute final : public Wrapper<HWC2::Attribute> {
+  enum : ValueType {
+    Invalid = HWC2_ATTRIBUTE_INVALID,
+    Width = HWC2_ATTRIBUTE_WIDTH,
+    Height = HWC2_ATTRIBUTE_HEIGHT,
+    VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
+    DpiX = HWC2_ATTRIBUTE_DPI_X,
+    DpiY = HWC2_ATTRIBUTE_DPI_Y,
+  };
+
+  Attribute() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct BlendMode final : public Wrapper<HWC2::BlendMode> {
+  enum : ValueType {
+    Invalid = HWC2_BLEND_MODE_INVALID,
+    None = HWC2_BLEND_MODE_NONE,
+    Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
+    Coverage = HWC2_BLEND_MODE_COVERAGE,
+  };
+
+  BlendMode() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct Composition final : public Wrapper<HWC2::Composition> {
+  enum : ValueType {
+    Invalid = HWC2_COMPOSITION_INVALID,
+    Client = HWC2_COMPOSITION_CLIENT,
+    Device = HWC2_COMPOSITION_DEVICE,
+    SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
+    Cursor = HWC2_COMPOSITION_CURSOR,
+    Sideband = HWC2_COMPOSITION_SIDEBAND,
+  };
+
+  Composition() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct DisplayType final : public Wrapper<HWC2::DisplayType> {
+  enum : ValueType {
+    Invalid = HWC2_DISPLAY_TYPE_INVALID,
+    Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
+    Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
+  };
+
+  DisplayType() : Base(Invalid) {}
+  using Base::Base;
+};
+
+struct Error final : public Wrapper<HWC2::Error> {
+  enum : ValueType {
+    None = HWC2_ERROR_NONE,
+    BadConfig = HWC2_ERROR_BAD_CONFIG,
+    BadDisplay = HWC2_ERROR_BAD_DISPLAY,
+    BadLayer = HWC2_ERROR_BAD_LAYER,
+    BadParameter = HWC2_ERROR_BAD_PARAMETER,
+    HasChanges = HWC2_ERROR_HAS_CHANGES,
+    NoResources = HWC2_ERROR_NO_RESOURCES,
+    NotValidated = HWC2_ERROR_NOT_VALIDATED,
+    Unsupported = HWC2_ERROR_UNSUPPORTED,
+  };
+
+  Error() : Base(None) {}
+  using Base::Base;
+};
+
+struct LayerRequest final : public Wrapper<HWC2::LayerRequest> {
+  enum : ValueType {
+    ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
+  };
+
+  LayerRequest() : Base(0) {}
+  using Base::Base;
+};
+
+struct PowerMode final : public Wrapper<HWC2::PowerMode> {
+  enum : ValueType {
+    Off = HWC2_POWER_MODE_OFF,
+    DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
+    Doze = HWC2_POWER_MODE_DOZE,
+    On = HWC2_POWER_MODE_ON,
+  };
+
+  PowerMode() : Base(Off) {}
+  using Base::Base;
+};
+
+struct Transform final : public Wrapper<HWC2::Transform> {
+  enum : ValueType {
+    None = 0,
+    FlipH = HWC_TRANSFORM_FLIP_H,
+    FlipV = HWC_TRANSFORM_FLIP_V,
+    Rotate90 = HWC_TRANSFORM_ROT_90,
+    Rotate180 = HWC_TRANSFORM_ROT_180,
+    Rotate270 = HWC_TRANSFORM_ROT_270,
+    FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
+    FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
+  };
+
+  Transform() : Base(None) {}
+  using Base::Base;
+};
+
+struct Vsync final : public Wrapper<HWC2::Vsync> {
+  enum : ValueType {
+    Invalid = HWC2_VSYNC_INVALID,
+    Enable = HWC2_VSYNC_ENABLE,
+    Disable = HWC2_VSYNC_DISABLE,
+  };
+
+  Vsync() : Base(Invalid) {}
+  using Base::Base;
+};
+
+// Utility color type.
+struct Color final {
+  Color(const Color&) = default;
+  Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+  Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
+
+  operator hwc_color_t() const { return {r, g, b, a}; }
+
+  uint8_t r __attribute__((aligned(1)));
+  uint8_t g __attribute__((aligned(1)));
+  uint8_t b __attribute__((aligned(1)));
+  uint8_t a __attribute__((aligned(1)));
+};
+
+// Utility rectangle type.
+struct Rect final {
+  // TODO(eieio): Implicit conversion to/from Android rect types.
+
+  int32_t left __attribute__((aligned(4)));
+  int32_t top __attribute__((aligned(4)));
+  int32_t right __attribute__((aligned(4)));
+  int32_t bottom __attribute__((aligned(4)));
+};
+
+}  // namespace HWC
+
+#endif  // ANDROID_LIBVRFLINGER_HWCTYPES_H
diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp
deleted file mode 100644
index d14d588..0000000
--- a/libs/vr/libvrflinger/screenshot_service.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "screenshot_service.h"
-
-#include <utils/Trace.h>
-
-#include <pdx/default_transport/service_endpoint.h>
-#include <private/android_filesystem_config.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/trusted_uids.h>
-
-using android::pdx::Message;
-using android::pdx::MessageInfo;
-using android::pdx::default_transport::Endpoint;
-using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::RemoteMethodError;
-using android::pdx::rpc::RemoteMethodReturn;
-
-namespace android {
-namespace dvr {
-
-ScreenshotService::~ScreenshotService() { instance_ = nullptr; }
-
-pdx::Status<void> ScreenshotService::HandleMessage(pdx::Message& message) {
-  switch (message.GetOp()) {
-    case DisplayScreenshotRPC::GetFormat::Opcode:
-      DispatchRemoteMethod<DisplayScreenshotRPC::GetFormat>(
-          *this, &ScreenshotService::OnGetFormat, message);
-      return {};
-
-    case DisplayScreenshotRPC::TakeScreenshot::Opcode:
-      DispatchRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(
-          *this, &ScreenshotService::OnTakeScreenshot, message);
-      return {};
-
-    default:
-      return Service::HandleMessage(message);
-  }
-}
-
-int ScreenshotService::OnGetFormat(pdx::Message&) {
-  return HAL_PIXEL_FORMAT_RGB_888;
-}
-
-ScreenshotData ScreenshotService::OnTakeScreenshot(pdx::Message& message,
-                                                   int layer_index) {
-  // Also allow AID_SHELL to support vrscreencap commands.
-  if (message.GetEffectiveUserId() != AID_SHELL &&
-      !IsTrustedUid(message.GetEffectiveUserId())) {
-    REPLY_ERROR_RETURN(message, EACCES, {});
-  }
-
-  AddWaiter(std::move(message), layer_index);
-  return {};
-}
-
-void ScreenshotService::AddWaiter(pdx::Message&& message, int layer_index) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  waiters_.emplace_back(std::move(message), layer_index);
-}
-
-void ScreenshotService::TakeIfNeeded(
-    std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
-    Compositor& compositor) {
-  std::lock_guard<std::mutex> lock(mutex_);
-
-  // Send the buffer contents to all of our waiting clients.
-  for (auto& waiter : waiters_) {
-    if (waiter.IsDone())
-      continue;
-
-    if (waiter.layer_index() == 0) {
-      ALOGE(
-          "ScreenshotService::TakeIfNeeded: Capturing the composited display "
-          "output is not yet supported.");
-
-      waiter.Error(EINVAL);
-      continue;
-    }
-
-    if (waiter.layer_index() > 0) {
-      // Check for hardware layer screenshot requests.
-      // Hardware layers are requested with positive indices starting at 1.
-      const size_t layer_index = static_cast<size_t>(waiter.layer_index() - 1);
-
-      if (layer_index >= hw_layers.size()) {
-        waiter.Error(EINVAL);
-        continue;
-      }
-
-      auto buffer = hw_layers[layer_index]->GetBuffer();
-      if (!buffer) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      auto data = compositor.ReadBufferPixels(buffer);
-      if (data.empty()) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      Take(&waiter, data.data(), buffer->width(), buffer->height(),
-           buffer->width());
-    } else {
-      // Check for compositor input layer screenshot requests.
-      // Prewarp surfaces are requested with negative indices starting at -1.
-      const size_t layer_index = static_cast<size_t>(-waiter.layer_index() - 1);
-
-      if (layer_index >= compositor.GetLayerCount()) {
-        waiter.Error(EINVAL);
-        continue;
-      }
-
-      int width = 0;
-      int height = 0;
-      auto data = compositor.ReadLayerPixels(layer_index, &width, &height);
-      if (data.empty()) {
-        waiter.Error(ENOBUFS);
-        continue;
-      }
-
-      Take(&waiter, data.data(), width, height, width);
-    }
-  }
-
-  // Reply with error to requests that did not match up with a source layer.
-  for (auto& waiter : waiters_) {
-    if (!waiter.IsDone())
-      waiter.Error(EAGAIN);
-  }
-  waiters_.clear();
-}
-
-void ScreenshotWaiter::Reply(const ScreenshotData& screenshot) {
-  ALOGI("Returning screenshot: size=%zu recv_size=%zu",
-        screenshot.buffer.size(), message_.GetReceiveLength());
-  RemoteMethodReturn<DisplayScreenshotRPC::TakeScreenshot>(message_,
-                                                           screenshot);
-}
-
-void ScreenshotWaiter::Error(int error) { RemoteMethodError(message_, error); }
-
-void ScreenshotService::Take(ScreenshotWaiter* waiter, const void* rgba_data,
-                             int32_t width, int32_t height, int buffer_stride) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-
-  bool is_portrait = height > width;
-  if (is_portrait) {
-    std::swap(width, height);
-  }
-  int response_stride = width;
-
-  // Convert from RGBA to RGB and if in portrait, rotates to landscape; store
-  // the result in the response buffer.
-  ScreenshotData screenshot{width, height,
-                            std::vector<uint8_t>(width * height * 3)};
-
-  const auto rgba_bytes = static_cast<const uint8_t*>(rgba_data);
-  for (int j = 0; j < height; ++j) {
-    for (int i = 0; i < width; ++i) {
-      // If the screenshot is in portrait mode, rotate into landscape mode.
-      const int response_index = is_portrait
-                                     ? (height - j - 1) * response_stride + i
-                                     : j * response_stride + i;
-      const int buffer_index =
-          is_portrait ? i * buffer_stride + j : j * buffer_stride + i;
-      screenshot.buffer[response_index * 3 + 0] =
-          rgba_bytes[buffer_index * 4 + 0];
-      screenshot.buffer[response_index * 3 + 1] =
-          rgba_bytes[buffer_index * 4 + 1];
-      screenshot.buffer[response_index * 3 + 2] =
-          rgba_bytes[buffer_index * 4 + 2];
-    }
-  }
-
-  waiter->Reply(screenshot);
-}
-
-ScreenshotService::ScreenshotService()
-    : BASE("ScreenshotService",
-           Endpoint::Create(DisplayScreenshotRPC::kClientPath)) {
-  instance_ = this;
-}
-
-ScreenshotService* ScreenshotService::GetInstance() { return instance_; }
-
-ScreenshotService* ScreenshotService::instance_ = nullptr;
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/screenshot_service.h b/libs/vr/libvrflinger/screenshot_service.h
deleted file mode 100644
index f59e872..0000000
--- a/libs/vr/libvrflinger/screenshot_service.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-
-#include <pdx/rpc/pointer_wrapper.h>
-#include <pdx/service.h>
-#include <private/dvr/ion_buffer.h>
-
-#include <mutex>
-#include <vector>
-
-#include "hardware_composer.h"
-
-namespace android {
-namespace dvr {
-
-class ScreenshotWaiter {
- public:
-  explicit ScreenshotWaiter(pdx::Message&& message, int layer_index)
-      : message_(std::move(message)), layer_index_(layer_index) {}
-  ScreenshotWaiter(ScreenshotWaiter&&) = default;
-
-  void Reply(const ScreenshotData& screenshot);
-  void Error(int error);
-
-  bool IsDone() const { return message_.replied(); }
-  int layer_index() const { return layer_index_; }
-
- private:
-  pdx::Message message_;
-  int layer_index_;
-
-  ScreenshotWaiter(const ScreenshotWaiter&) = delete;
-  void operator=(const ScreenshotWaiter&) = delete;
-};
-
-// The screenshot service allows clients to obtain screenshots from displayd.
-class ScreenshotService : public pdx::ServiceBase<ScreenshotService> {
- public:
-  ~ScreenshotService();
-
-  pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
-  // Returns true if there is a pending screenshot request.
-  bool IsScreenshotRequestPending() const {
-    std::lock_guard<std::mutex> lock(mutex_);
-    return !waiters_.empty();
-  }
-
-  // If any clients are currently waiting for a screenshot, read back the
-  // contents of requested layers and send the resulting
-  // image to the clients.
-  void TakeIfNeeded(
-      std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
-      Compositor& compositor);
-
-  static ScreenshotService* GetInstance();
-
- private:
-  friend BASE;
-
-  ScreenshotService();
-
-  void AddWaiter(pdx::Message&& message, int layer_index);
-
-  ScreenshotData OnTakeScreenshot(pdx::Message& message, int index);
-  int OnGetFormat(pdx::Message& message);
-
-  // Copy the given screenshot data into the message reply.
-  void Take(ScreenshotWaiter* waiter, const void* rgba_data, int32_t width,
-            int32_t height, int buffer_stride);
-
-  static ScreenshotService* instance_;
-
-  // Protects access to subsequent member variables.
-  mutable std::mutex mutex_;
-  std::vector<ScreenshotWaiter> waiters_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
diff --git a/libs/vr/libvrflinger/surface_channel.cpp b/libs/vr/libvrflinger/surface_channel.cpp
deleted file mode 100644
index 263b382..0000000
--- a/libs/vr/libvrflinger/surface_channel.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "surface_channel.h"
-
-using android::pdx::BorrowedChannelHandle;
-using android::pdx::Message;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-pdx::Status<void> SurfaceChannel::HandleMessage(Message& message) {
-  switch (message.GetOp()) {
-    case DisplayRPC::GetMetadataBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::GetMetadataBuffer>(
-          *this, &SurfaceChannel::OnGetMetadataBuffer, message);
-      break;
-  }
-
-  return {};
-}
-
-BorrowedChannelHandle SurfaceChannel::OnGetMetadataBuffer(Message& message) {
-  if (EnsureMetadataBuffer()) {
-    return metadata_buffer_->GetChannelHandle().Borrow();
-  } else {
-    REPLY_ERROR_RETURN(message, -ENOMEM, {});
-  }
-}
-
-bool SurfaceChannel::EnsureMetadataBuffer() {
-  if (!metadata_buffer_) {
-    metadata_buffer_ =
-        BufferProducer::CreateUncachedBlob(metadata_size());
-    if (!metadata_buffer_) {
-      ALOGE(
-          "DisplaySurface::EnsureMetadataBuffer: could not allocate metadata "
-          "buffer");
-      return false;
-    }
-  }
-  return true;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/surface_channel.h b/libs/vr/libvrflinger/surface_channel.h
deleted file mode 100644
index 9dcac3f..0000000
--- a/libs/vr/libvrflinger/surface_channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-
-#include <pdx/service.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_protocol.h>
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-class SurfaceChannel : public pdx::Channel {
- public:
-  SurfaceChannel(DisplayService* service, int channel_id, SurfaceType type,
-                 size_t metadata_size)
-      : service_(service),
-        surface_id_(channel_id),
-        type_(type),
-        metadata_size_(metadata_size) {}
-
-  ~SurfaceChannel() override = default;
-
-  DisplayService* service() const { return service_; }
-  int surface_id() const { return surface_id_; }
-  SurfaceType type() const { return type_; }
-  size_t metadata_size() const { return metadata_size_; }
-
-  pdx::LocalHandle GetMetadataBufferFd() {
-    return EnsureMetadataBuffer() ? metadata_buffer_->GetBlobFd()
-                                  : pdx::LocalHandle{};
-  }
-
-  // Dispatches surface channel messages to the appropriate handlers. This
-  // handler runs on the displayd message dispatch thread.
-  virtual pdx::Status<void> HandleMessage(pdx::Message& message);
-
- protected:
-  // Contains the surface metadata.
-  std::shared_ptr<BufferProducer> metadata_buffer_;
-
-  // Returns the metadata buffer for this surface. The first call allocates the
-  // buffer, while subsequent calls return the same buffer.
-  pdx::BorrowedChannelHandle OnGetMetadataBuffer(pdx::Message& message);
-
-  // Allocates the single metadata buffer for this surface unless it is already
-  // allocated. Idempotent when called multiple times.
-  bool EnsureMetadataBuffer();
-
- private:
-  DisplayService* service_;
-  int surface_id_;
-  SurfaceType type_;
-  size_t metadata_size_;
-
-  SurfaceChannel(const SurfaceChannel&) = delete;
-  void operator=(const SurfaceChannel&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
diff --git a/libs/vr/libvrflinger/video_compositor.cpp b/libs/vr/libvrflinger/video_compositor.cpp
deleted file mode 100644
index e42caaa..0000000
--- a/libs/vr/libvrflinger/video_compositor.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "video_compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES2/gl2ext.h>
-
-#include <private/dvr/debug.h>
-#include <private/dvr/display_protocol.h>
-
-namespace android {
-namespace dvr {
-
-VideoCompositor::Texture::Texture(
-    EGLDisplay display, const std::shared_ptr<BufferConsumer>& buffer_consumer)
-    : display_(display),
-      image_(EGL_NO_IMAGE_KHR),
-      texture_id_(0),
-      buffer_consumer_(buffer_consumer) {}
-
-VideoCompositor::Texture::~Texture() {
-  if (image_ != EGL_NO_IMAGE_KHR)
-    eglDestroyImageKHR(display_, image_);
-  if (texture_id_ != 0)
-    glDeleteTextures(1, &texture_id_);
-}
-
-GLuint VideoCompositor::Texture::EnsureTextureReady() {
-  if (!image_) {
-    native_buffer_ = new NativeBuffer(buffer_consumer_);
-    CHECK_GL();
-
-    image_ = eglCreateImageKHR(
-        display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-        static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-    if (!image_) {
-      ALOGE("Failed to create EGLImage.");
-      return 0;
-    }
-
-    glGenTextures(1, &texture_id_);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image_);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
-                    GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
-                    GL_CLAMP_TO_EDGE);
-    CHECK_GL();
-  }
-
-  return texture_id_;
-}
-
-void VideoCompositor::Texture::Release() {
-  const int ret = buffer_consumer_->Release({});
-  if (ret < 0) {
-    ALOGE(
-        "VideoCompositor::Texture::Release: Failed to release buffer, error: "
-        "%s",
-        strerror(-ret));
-  }
-}
-
-VideoCompositor::VideoCompositor(
-    const std::shared_ptr<VideoMeshSurface>& surface,
-    const volatile DisplaySurfaceMetadata* display_surface_metadata)
-    : surface_(surface),
-      consumer_queue_(surface->GetConsumerQueue()),
-      transform_metadata_(display_surface_metadata),
-      active_texture_slot_(-1) {}
-
-GLuint VideoCompositor::GetActiveTextureId(EGLDisplay display) {
-  size_t slot;
-  BufferHubQueueCore::NativeBufferMetadata metadata;
-
-  while (true) {
-    // A native way to pick the active texture: always dequeue all buffers from
-    // the queue until it's empty. This works well as long as video frames are
-    // queued in order from the producer side.
-    // TODO(jwcai) Use |metadata.timestamp_ns| to schedule video frames
-    // accurately.
-    LocalHandle acquire_fence;
-    auto buffer_consumer =
-        consumer_queue_->Dequeue(0, &slot, &metadata, &acquire_fence);
-
-    if (buffer_consumer) {
-      // Create a new texture if it hasn't been created yet, or the same slot
-      // has a new |buffer_consumer|.
-      if (textures_[slot] == nullptr ||
-          textures_[slot]->event_fd() != buffer_consumer->event_fd()) {
-        textures_[slot] =
-            std::unique_ptr<Texture>(new Texture(display, buffer_consumer));
-      }
-
-      if (active_texture_slot_ != static_cast<int>(slot)) {
-        if (active_texture_slot_ >= 0) {
-          // Release the last active texture and move on to use the new one.
-          textures_[active_texture_slot_]->Release();
-        }
-        active_texture_slot_ = slot;
-      }
-    } else {
-      break;
-    }
-  }
-
-  if (active_texture_slot_ < 0) {
-    // No texture is active yet.
-    return 0;
-  }
-
-  return textures_[active_texture_slot_]->EnsureTextureReady();
-}
-
-mat4 VideoCompositor::GetTransform(int eye, size_t render_buffer_index) {
-  volatile const VideoMeshSurfaceMetadata* transform_metadata =
-      surface_->GetMetadataBufferPtr();
-
-  mat4 screen_transform;
-  for (int i = 0; i < 4; ++i) {
-    for (int j = 0; j < 4; ++j) {
-      screen_transform(i, j) =
-          transform_metadata->transform[render_buffer_index][eye].val[i][j];
-    }
-  }
-
-  return screen_transform;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/video_compositor.h b/libs/vr/libvrflinger/video_compositor.h
deleted file mode 100644
index d0e72e1..0000000
--- a/libs/vr/libvrflinger/video_compositor.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/types.h>
-
-#include <vector>
-
-#include "display_surface.h"
-#include "video_mesh_surface.h"
-
-namespace android {
-namespace dvr {
-
-using pdx::LocalHandle;
-
-// Manages video buffer consumers, texture mapping, and playback timing.
-class VideoCompositor {
- public:
-  VideoCompositor(
-      const std::shared_ptr<VideoMeshSurface>& surface,
-      const volatile DisplaySurfaceMetadata* display_surface_metadata);
-
-  int surface_id() const { return surface_ ? surface_->surface_id() : -1; }
-
-  // Returns a GL texture id that should be composited by displayd during the
-  // current rendering loop. Note that this function must be called in
-  // displayd's GL context.
-  GLuint GetActiveTextureId(EGLDisplay display);
-
-  // Returns a basic video mesh tranform.
-  mat4 GetTransform(int eye, size_t render_buffer_index);
-
- private:
-  class Texture {
-   public:
-    Texture(EGLDisplay display,
-            const std::shared_ptr<BufferConsumer>& buffer_consumer);
-    ~Texture();
-
-    // Returns the |event_fd| of the underlying buffer consumer. Caller can use
-    // this to decided whether the Texture need to be recreated for a different
-    // buffer consumer.
-    int event_fd() const { return buffer_consumer_->event_fd(); }
-
-    // Method to map a dvr::BufferConsumer to a GL texture within the current GL
-    // context. If the current Texture object's |image_| hasn't been
-    // initialized, the method will do so based on the |buffer_consumer| and a
-    // new GL texture will be generated, cached, and returned. Otherwise, the
-    // cached |texture_id_| will be returned directly.
-    GLuint EnsureTextureReady();
-
-    // Signal bufferhub that the texture is done rendering so that the buffer
-    // can be re-gained by the producer for future use.
-    void Release();
-
-   private:
-    using NativeBuffer = BufferHubQueueCore::NativeBuffer;
-
-    EGLDisplay display_;
-    EGLImageKHR image_;
-    GLuint texture_id_;
-    sp<NativeBuffer> native_buffer_;
-    std::shared_ptr<BufferConsumer> buffer_consumer_;
-  };
-
-  std::shared_ptr<VideoMeshSurface> surface_;
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-  std::array<std::unique_ptr<Texture>, BufferHubQueue::kMaxQueueCapacity>
-      textures_;
-
-  const volatile DisplaySurfaceMetadata* transform_metadata_;
-  int active_texture_slot_;
-
-  VideoCompositor(const VideoCompositor&) = delete;
-  void operator=(const VideoCompositor&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/video_mesh_surface.cpp b/libs/vr/libvrflinger/video_mesh_surface.cpp
deleted file mode 100644
index 76dd94f..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "video_mesh_surface.h"
-
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/display_protocol.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-VideoMeshSurface::VideoMeshSurface(DisplayService* service, int surface_id)
-    : SurfaceChannel(service, surface_id, SurfaceTypeEnum::VideoMesh,
-                     sizeof(VideoMeshSurfaceMetadata)) {}
-
-VideoMeshSurface::~VideoMeshSurface() {}
-
-pdx::Status<void> VideoMeshSurface::HandleMessage(Message& message) {
-  ATRACE_NAME("VideoMeshSurface::HandleMessage");
-
-  switch (message.GetOp()) {
-    case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
-      DispatchRemoteMethod<DisplayRPC::VideoMeshSurfaceCreateProducerQueue>(
-          *this, &VideoMeshSurface::OnCreateProducerQueue, message);
-      break;
-
-    default:
-      return SurfaceChannel::HandleMessage(message);
-  }
-
-  return {};
-}
-
-std::shared_ptr<ConsumerQueue> VideoMeshSurface::GetConsumerQueue() {
-  if (!consumer_queue_) {
-    ALOGE(
-        "VideoMeshSurface::GetConsumerQueue: consumer_queue is uninitialized.");
-  }
-
-  return consumer_queue_;
-}
-
-LocalChannelHandle VideoMeshSurface::OnCreateProducerQueue(Message& message) {
-  ATRACE_NAME("VideoMeshSurface::OnCreateProducerQueue");
-
-  if (consumer_queue_ != nullptr) {
-    ALOGE(
-        "VideoMeshSurface::OnCreateProducerQueue: A ProdcuerQueue has already "
-        "been created and transported to VideoMeshSurfaceClient.");
-    REPLY_ERROR_RETURN(message, EALREADY, {});
-  }
-
-  auto producer =
-      ProducerQueue::Create<BufferHubQueueCore::NativeBufferMetadata>();
-  consumer_queue_ = producer->CreateConsumerQueue();
-
-  return std::move(producer->GetChannelHandle());
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/libs/vr/libvrflinger/video_mesh_surface.h b/libs/vr/libvrflinger/video_mesh_surface.h
deleted file mode 100644
index 2c9f3e8..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-
-#include "surface_channel.h"
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-// VideoMeshSurface takes three inputs: 1) buffers filled by Android system
-// components (e.g. MediaCodec or camera stack) other than applications' GL
-// context; 2) a 3D mesh chosen by application to define the shape of the
-// surface; 3) a transformation matrix from application to define the rotation,
-// position, and scaling of the video surface.
-class VideoMeshSurface : public SurfaceChannel {
- public:
-  using Message = pdx::Message;
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-
-  VideoMeshSurface(DisplayService* service, int channel_id);
-  ~VideoMeshSurface() override;
-
-  volatile const VideoMeshSurfaceMetadata* GetMetadataBufferPtr() {
-    if (EnsureMetadataBuffer()) {
-      void* addr = nullptr;
-      metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
-      return static_cast<const volatile VideoMeshSurfaceMetadata*>(addr);
-    } else {
-      return nullptr;
-    }
-  }
-
-  pdx::Status<void> HandleMessage(Message& message) override;
-
-  std::shared_ptr<ConsumerQueue> GetConsumerQueue();
-
- private:
-  LocalChannelHandle OnCreateProducerQueue(Message& message);
-
-  std::shared_ptr<ConsumerQueue> consumer_queue_;
-
-  VideoMeshSurface(const VideoMeshSurface&) = delete;
-  void operator=(const VideoMeshSurface&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 21226db..b2dc1d8 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -11,9 +11,9 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
-#include <log/log.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
+#include <log/log.h>
 #include <private/dvr/display_client.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
@@ -25,7 +25,6 @@
 #include "DisplayHardware/ComposerHal.h"
 #include "display_manager_service.h"
 #include "display_service.h"
-#include "screenshot_service.h"
 #include "vsync_service.h"
 
 namespace android {
@@ -77,11 +76,11 @@
 
   request_display_callback_ = request_display_callback;
 
-  dispatcher_ =
-      android::pdx::default_transport::ServiceDispatcher::Create();
+  dispatcher_ = android::pdx::default_transport::ServiceDispatcher::Create();
   CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
 
-  display_service_ = android::dvr::DisplayService::Create(hidl);
+  display_service_ =
+      android::dvr::DisplayService::Create(hidl, request_display_callback);
   CHECK_ERROR(!display_service_, error, "Failed to create display service.");
   dispatcher_->AddService(display_service_);
 
@@ -89,10 +88,6 @@
   CHECK_ERROR(!service, error, "Failed to create display manager service.");
   dispatcher_->AddService(service);
 
-  service = android::dvr::ScreenshotService::Create();
-  CHECK_ERROR(!service, error, "Failed to create screenshot service.");
-  dispatcher_->AddService(service);
-
   service = android::dvr::VSyncService::Create();
   CHECK_ERROR(!service, error, "Failed to create vsync service.");
   dispatcher_->AddService(service);
@@ -147,7 +142,9 @@
 void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
     bool enabled) {
   ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
-  request_display_callback_(enabled);
+  // TODO(eieio): Determine the correct signal to request display control.
+  // Persistent VR mode is not enough.
+  // request_display_callback_(enabled);
 }
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index cda815c..2a83933 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -1,17 +1,19 @@
 #include "vsync_service.h"
 
-#include <log/log.h>
 #include <hardware/hwcomposer.h>
+#include <log/log.h>
 #include <poll.h>
 #include <sys/prctl.h>
 #include <time.h>
 #include <utils/Trace.h>
 
+#include <dvr/dvr_display_types.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/display_protocol.h>
-#include <private/dvr/display_types.h>
 
+using android::dvr::display::VSyncProtocol;
+using android::dvr::display::VSyncSchedInfo;
 using android::pdx::Channel;
 using android::pdx::Message;
 using android::pdx::MessageInfo;
@@ -22,7 +24,7 @@
 namespace dvr {
 
 VSyncService::VSyncService()
-    : BASE("VSyncService", Endpoint::Create(DisplayVSyncRPC::kClientPath)),
+    : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)),
       last_vsync_(0),
       current_vsync_(0),
       compositor_time_ns_(0),
@@ -109,22 +111,22 @@
 
 pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
   switch (message.GetOp()) {
-    case DisplayVSyncRPC::Wait::Opcode:
+    case VSyncProtocol::Wait::Opcode:
       AddWaiter(message);
       return {};
 
-    case DisplayVSyncRPC::GetLastTimestamp::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>(
+    case VSyncProtocol::GetLastTimestamp::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
           *this, &VSyncService::OnGetLastTimestamp, message);
       return {};
 
-    case DisplayVSyncRPC::GetSchedInfo::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::GetSchedInfo>(
+    case VSyncProtocol::GetSchedInfo::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
           *this, &VSyncService::OnGetSchedInfo, message);
       return {};
 
-    case DisplayVSyncRPC::Acknowledge::Opcode:
-      DispatchRemoteMethod<DisplayVSyncRPC::Acknowledge>(
+    case VSyncProtocol::Acknowledge::Opcode:
+      DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
           *this, &VSyncService::OnAcknowledge, message);
       return {};
 
@@ -133,16 +135,17 @@
   }
 }
 
-int64_t VSyncService::OnGetLastTimestamp(pdx::Message& message) {
+pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
 
   // Getting the timestamp has the side effect of ACKing.
   client->Ack();
-  return current_vsync_;
+  return {current_vsync_};
 }
 
-VSyncSchedInfo VSyncService::OnGetSchedInfo(pdx::Message& message) {
+pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
+    pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
 
@@ -176,23 +179,25 @@
     }
   }
 
-  return {vsync_period_ns, next_warp, next_vsync_count};
+  return {{vsync_period_ns, next_warp, next_vsync_count}};
 }
 
-int VSyncService::OnAcknowledge(pdx::Message& message) {
+pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
   auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
   std::lock_guard<std::mutex> autolock(mutex_);
   client->Ack();
-  return 0;
+  return {};
 }
 
 void VSyncWaiter::Notify(int64_t timestamp) {
   timestamp_ = timestamp;
-  DispatchRemoteMethod<DisplayVSyncRPC::Wait>(*this, &VSyncWaiter::OnWait,
-                                              message_);
+  DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
+                                            message_);
 }
 
-int64_t VSyncWaiter::OnWait(pdx::Message& /*message*/) { return timestamp_; }
+pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
+  return {timestamp_};
+}
 
 void VSyncChannel::Ack() {
   ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index 1c86d42..215948e 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -23,7 +23,7 @@
   void Notify(int64_t timestamp);
 
  private:
-  int64_t OnWait(pdx::Message& message);
+  pdx::Status<int64_t> OnWait(pdx::Message& message);
 
   pdx::Message message_;
   int64_t timestamp_ = 0;
@@ -62,10 +62,9 @@
   void OnChannelClose(pdx::Message& message,
                       const std::shared_ptr<pdx::Channel>& channel) override;
 
-  // Called by the hardware composer HAL, or similar,
-  // whenever a vsync event occurs.
-  // |compositor_time_ns| is the number of ns before the next vsync when the
-  // compositor will preempt the GPU to do EDS and lens warp.
+  // Called by the hardware composer HAL, or similar, whenever a vsync event
+  // occurs. |compositor_time_ns| is the number of ns before the next vsync when
+  // the compositor will preempt the GPU to do EDS and lens warp.
   void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns,
                   uint32_t vsync_count);
 
@@ -74,9 +73,9 @@
 
   VSyncService();
 
-  int64_t OnGetLastTimestamp(pdx::Message& message);
-  VSyncSchedInfo OnGetSchedInfo(pdx::Message& message);
-  int OnAcknowledge(pdx::Message& message);
+  pdx::Status<int64_t> OnGetLastTimestamp(pdx::Message& message);
+  pdx::Status<display::VSyncSchedInfo> OnGetSchedInfo(pdx::Message& message);
+  pdx::Status<void> OnAcknowledge(pdx::Message& message);
 
   void NotifierThreadFunction();