Eliminate code duplication from hwcomposer

Move all common code to guest/hals/hwcomposer/common, which includes
the implementation of cpu-based compositions (vsoc_composer.* files
are renamed to cpu_composer.*).
Encapsulate the differences in classes implementing the contract
defined in the ScreenView abstract class (VsocketScreenView for crosvm
and VSoCScreenView for qemu).
Fix formatting of some files.

Bug: 135628605
Test: run locally with qemu & crosvm
Change-Id: Iae3c8a31155f935a4ee60ef1e16c934ad4878587
diff --git a/guest/hals/hwcomposer/common/Android.bp b/guest/hals/hwcomposer/common/Android.bp
index 5e16041..1b5125a 100644
--- a/guest/hals/hwcomposer/common/Android.bp
+++ b/guest/hals/hwcomposer/common/Android.bp
@@ -17,6 +17,28 @@
     name: "hwcomposer_common",
     defaults: ["cuttlefish_guest_only"],
     vendor: true,
-    srcs: ["hwcomposer.cpp"],
-    shared_libs: ["libhardware", "liblog"],
+    srcs: [
+        "hwcomposer.cpp",
+        "screen_view.cpp",
+        "base_composer.cpp",
+        "geometry_utils.cpp",
+        "cpu_composer.cpp",
+        "stats_keeper.cpp",
+    ],
+    static_libs: [
+        "libyuv_static",
+    ],
+    shared_libs: [
+        "cuttlefish_auto_resources",
+        "liblog",
+        "libhardware",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libsync",
+        "libhardware",
+        "libjpeg",
+        "libcuttlefish_utils",
+        "libcuttlefish_fs",
+    ],
 }
diff --git a/guest/hals/hwcomposer/common/base_composer.cpp b/guest/hals/hwcomposer/common/base_composer.cpp
new file mode 100644
index 0000000..61e6e99
--- /dev/null
+++ b/guest/hals/hwcomposer/common/base_composer.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+
+#include <string.h>
+
+#include <cutils/properties.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+
+namespace cvd {
+
+BaseComposer::BaseComposer(int64_t vsync_base_timestamp,
+                           std::unique_ptr<ScreenView> screen_view)
+    : screen_view_(std::move(screen_view)),
+      vsync_base_timestamp_(vsync_base_timestamp),
+      vsync_period_ns_(1e9 / screen_view_->refresh_rate()) {
+  hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+                reinterpret_cast<const hw_module_t**>(&gralloc_module_));
+}
+
+void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
+
+int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
+  auto buffer_id = screen_view_->NextBuffer();
+  void* frame_buffer = screen_view_->GetBuffer(buffer_id);
+  const private_handle_t* p_handle =
+      reinterpret_cast<const private_handle_t*>(buffer_handle);
+  void* buffer;
+  int retval = gralloc_module_->lock(gralloc_module_, buffer_handle,
+                                     GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
+                                     p_handle->x_res, p_handle->y_res, &buffer);
+  if (retval != 0) {
+    ALOGE("Got error code %d from lock function", retval);
+    return -1;
+  }
+  memcpy(frame_buffer, buffer, screen_view_->buffer_size());
+  screen_view_->Broadcast(buffer_id);
+  return 0;
+}  // namespace cvd
+
+int BaseComposer::PrepareLayers(size_t num_layers, cvd_hwc_layer* layers) {
+  // find unsupported overlays
+  for (size_t i = 0; i < num_layers; i++) {
+    if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) {
+      continue;
+    }
+    layers[i].compositionType = HWC_FRAMEBUFFER;
+  }
+  return 0;
+}
+
+int BaseComposer::SetLayers(size_t num_layers, cvd_hwc_layer* layers) {
+  for (size_t idx = 0; idx < num_layers; idx++) {
+    if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
+      return PostFrameBufferTarget(layers[idx].handle);
+    }
+  }
+  return -1;
+}
+
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/common/base_composer.h b/guest/hals/hwcomposer/common/base_composer.h
new file mode 100644
index 0000000..8e7dd36
--- /dev/null
+++ b/guest/hals/hwcomposer/common/base_composer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+namespace cvd {
+
+class BaseComposer {
+ public:
+  BaseComposer(int64_t vsync_base_timestamp,
+               std::unique_ptr<ScreenView> screen_view);
+  ~BaseComposer() = default;
+
+  // Sets the composition type of each layer and returns the number of layers
+  // to be composited by the hwcomposer.
+  int PrepareLayers(size_t num_layers, cvd_hwc_layer* layers);
+  // Returns 0 if successful.
+  int SetLayers(size_t num_layers, cvd_hwc_layer* layers);
+  void Dump(char* buff, int buff_len);
+
+  int32_t x_res() { return screen_view_->x_res(); }
+  int32_t y_res() { return screen_view_->y_res(); }
+  int32_t dpi() { return screen_view_->dpi(); }
+  int32_t refresh_rate() { return screen_view_->refresh_rate(); }
+
+ protected:
+  std::unique_ptr<ScreenView> screen_view_;
+  const gralloc_module_t* gralloc_module_;
+  int64_t vsync_base_timestamp_;
+  int32_t vsync_period_ns_;
+
+ private:
+  // Returns buffer offset or negative on error.
+  int PostFrameBufferTarget(buffer_handle_t handle);
+};
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsoc_composer.cpp b/guest/hals/hwcomposer/common/cpu_composer.cpp
similarity index 91%
rename from guest/hals/hwcomposer/cutf_cvm/vsoc_composer.cpp
rename to guest/hals/hwcomposer/common/cpu_composer.cpp
index 5b55e84..5e7a29d 100644
--- a/guest/hals/hwcomposer/cutf_cvm/vsoc_composer.cpp
+++ b/guest/hals/hwcomposer/common/cpu_composer.cpp
@@ -14,28 +14,27 @@
  * limitations under the License.
  */
 
-#include "vsoc_composer.h"
+#include "guest/hals/hwcomposer/common/cpu_composer.h"
 
 #include <algorithm>
 #include <cstdlib>
 #include <utility>
 #include <vector>
 
-#include <log/log.h>
 #include <hardware/hwcomposer.h>
 #include <hardware/hwcomposer_defs.h>
 #include <libyuv.h>
+#include <log/log.h>
 #include <system/graphics.h>
 
-#include <common/libs/utils/size_utils.h>
-
-#include "geometry_utils.h"
+#include "common/libs/utils/size_utils.h"
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
 
 namespace cvd {
 
 namespace {
 
-bool LayerNeedsScaling(const vsoc_hwc_layer& layer) {
+bool LayerNeedsScaling(const cvd_hwc_layer& layer) {
   int from_w = layer.sourceCrop.right - layer.sourceCrop.left;
   int from_h = layer.sourceCrop.bottom - layer.sourceCrop.top;
   int to_w = layer.displayFrame.right - layer.displayFrame.left;
@@ -49,11 +48,11 @@
   return needs_rot ? rot_scale : not_rot_scale;
 }
 
-bool LayerNeedsBlending(const vsoc_hwc_layer& layer) {
+bool LayerNeedsBlending(const cvd_hwc_layer& layer) {
   return layer.blending != HWC_BLENDING_NONE;
 }
 
-bool LayerNeedsAttenuation(const vsoc_hwc_layer& layer) {
+bool LayerNeedsAttenuation(const cvd_hwc_layer& layer) {
   return layer.blending == HWC_BLENDING_COVERAGE;
 }
 
@@ -103,7 +102,7 @@
 // Whether we support a given format
 bool IsFormatSupported(uint32_t format) { return GetConverter(format) != NULL; }
 
-bool CanCompositeLayer(const vsoc_hwc_layer& layer) {
+bool CanCompositeLayer(const cvd_hwc_layer& layer) {
   if (layer.handle == NULL) {
     ALOGW("%s received a layer with a null handler", __FUNCTION__);
     return false;
@@ -175,7 +174,7 @@
   int stride_y = stride_in_pixels;
   uint8_t* src_v = src_y + stride_y * src.height;
   int stride_v = cvd::AlignToPowerOf2(stride_y / 2, 4);
-  uint8_t* src_u = src_v + stride_v *  src.height / 2;
+  uint8_t* src_u = src_v + stride_v * src.height / 2;
   int stride_u = cvd::AlignToPowerOf2(stride_y / 2, 4);
 
   // Adjust for crop
@@ -293,8 +292,7 @@
 
 }  // namespace
 
-void VSoCComposer::CompositeLayer(vsoc_hwc_layer* src_layer,
-                                  int buffer_idx) {
+void CpuComposer::CompositeLayer(cvd_hwc_layer* src_layer, int buffer_idx) {
   libyuv::RotationMode rotation =
       GetRotationFromTransform(src_layer->transform);
 
@@ -313,8 +311,8 @@
                       needs_vflip || needs_attenuation || needs_blending);
 
   uint8_t* src_buffer;
-  uint8_t* dst_buffer = reinterpret_cast<uint8_t*>(
-      frame_buffer_.GetBuffer(buffer_idx));
+  uint8_t* dst_buffer =
+      reinterpret_cast<uint8_t*>(screen_view_->GetBuffer(buffer_idx));
   int retval = gralloc_module_->lock(
       gralloc_module_, src_layer->handle, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
       src_priv_handle->x_res, src_priv_handle->y_res,
@@ -342,9 +340,9 @@
       src_layer->sourceCrop.bottom - src_layer->sourceCrop.top;
   src_layer_spec.format = src_priv_handle->format;
 
-  BufferSpec dst_layer_spec(dst_buffer, frame_buffer_.buffer_size(),
-                            frame_buffer_.x_res(), frame_buffer_.y_res(),
-                            frame_buffer_.line_length());
+  BufferSpec dst_layer_spec(dst_buffer, screen_view_->buffer_size(),
+                            screen_view_->x_res(), screen_view_->y_res(),
+                            screen_view_->line_length());
   dst_layer_spec.crop_x = src_layer->displayFrame.left;
   dst_layer_spec.crop_y = src_layer->displayFrame.top;
   dst_layer_spec.crop_width =
@@ -372,13 +370,11 @@
   int x_res = src_layer->displayFrame.right - src_layer->displayFrame.left;
   int y_res = src_layer->displayFrame.bottom - src_layer->displayFrame.top;
   size_t output_frame_size =
-      x_res *
-    cvd::AlignToPowerOf2(y_res * frame_buffer_.bytes_per_pixel(), 4);
+      x_res * cvd::AlignToPowerOf2(y_res * screen_view_->bytes_per_pixel(), 4);
   while (needed_tmp_buffers > 0) {
-    BufferSpec tmp(RotateTmpBuffer(needed_tmp_buffers), output_frame_size,
-                   x_res, y_res,
-                   cvd::AlignToPowerOf2(
-                       x_res * frame_buffer_.bytes_per_pixel(), 4));
+    BufferSpec tmp(
+        RotateTmpBuffer(needed_tmp_buffers), output_frame_size, x_res, y_res,
+        cvd::AlignToPowerOf2(x_res * screen_view_->bytes_per_pixel(), 4));
     dest_buffer_stack.push_back(tmp);
     needed_tmp_buffers--;
   }
@@ -399,8 +395,8 @@
       // Make width and height match the crop sizes on the source
       int src_width = src_layer_spec.crop_width;
       int src_height = src_layer_spec.crop_height;
-      int dst_stride = cvd::AlignToPowerOf2(
-          src_width * frame_buffer_.bytes_per_pixel(), 4);
+      int dst_stride =
+          cvd::AlignToPowerOf2(src_width * screen_view_->bytes_per_pixel(), 4);
       size_t needed_size = dst_stride * src_height;
       dst_buffer_spec.width = src_width;
       dst_buffer_spec.height = src_height;
@@ -440,7 +436,7 @@
       // TODO (jemoreira): Aligment (To align here may cause the needed size to
       // be bigger than the buffer, so care should be taken)
       dst_buffer_spec.stride =
-          dst_buffer_spec.width * frame_buffer_.bytes_per_pixel();
+          dst_buffer_spec.width * screen_view_->bytes_per_pixel();
     }
     retval = DoScaling(src_layer_spec, dst_buffer_spec, needs_vflip);
     needs_vflip = false;
@@ -498,16 +494,14 @@
   gralloc_module_->unlock(gralloc_module_, src_priv_handle);
 }
 
-/* static */ const int VSoCComposer::kNumTmpBufferPieces = 2;
+/* static */ const int CpuComposer::kNumTmpBufferPieces = 2;
 
-VSoCComposer::VSoCComposer(int64_t vsync_base_timestamp)
-    : BaseComposer(vsync_base_timestamp),
-      tmp_buffer_(kNumTmpBufferPieces *
-                  frame_buffer_.buffer_size()) {}
+CpuComposer::CpuComposer(int64_t vsync_base_timestamp,
+                         std::unique_ptr<ScreenView> screen_view)
+    : BaseComposer(vsync_base_timestamp, std::move(screen_view)),
+      tmp_buffer_(kNumTmpBufferPieces * screen_view_->buffer_size()) {}
 
-VSoCComposer::~VSoCComposer() {}
-
-int VSoCComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+int CpuComposer::PrepareLayers(size_t num_layers, cvd_hwc_layer* layers) {
   int composited_layers_count = 0;
 
   // Loop over layers in inverse order of z-index
@@ -549,9 +543,9 @@
   return composited_layers_count;
 }
 
-int VSoCComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+int CpuComposer::SetLayers(size_t num_layers, cvd_hwc_layer* layers) {
   int targetFbs = 0;
-  int buffer_idx = frame_buffer_.NextScreenBuffer();
+  int buffer_idx = screen_view_->NextBuffer();
 
   // The framebuffer target layer should be composed if at least one layers was
   // marked HWC_FRAMEBUFFER or if it's the only layer in the composition
@@ -591,16 +585,16 @@
   if (targetFbs != 1) {
     ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
   }
-  frame_buffer_.Broadcast(buffer_idx);
+  screen_view_->Broadcast(buffer_idx);
   return 0;
 }
 
-uint8_t* VSoCComposer::RotateTmpBuffer(unsigned int order) {
+uint8_t* CpuComposer::RotateTmpBuffer(unsigned int order) {
   return &tmp_buffer_[(order % kNumTmpBufferPieces) * tmp_buffer_.size() /
                       kNumTmpBufferPieces];
 }
 
-uint8_t* VSoCComposer::GetSpecialTmpBuffer(size_t needed_size) {
+uint8_t* CpuComposer::GetSpecialTmpBuffer(size_t needed_size) {
   special_tmp_buffer_.resize(needed_size);
   return &special_tmp_buffer_[0];
 }
diff --git a/guest/hals/hwcomposer/vsoc/vsoc_composer.h b/guest/hals/hwcomposer/common/cpu_composer.h
similarity index 69%
rename from guest/hals/hwcomposer/vsoc/vsoc_composer.h
rename to guest/hals/hwcomposer/common/cpu_composer.h
index 0e8e2c2..3e745df 100644
--- a/guest/hals/hwcomposer/vsoc/vsoc_composer.h
+++ b/guest/hals/hwcomposer/common/cpu_composer.h
@@ -1,4 +1,3 @@
-#pragma once
 /*
  * Copyright (C) 2016 The Android Open Source Project
  *
@@ -15,32 +14,35 @@
  * limitations under the License.
  */
 
+#pragma once
+
 #include <vector>
 
 #include <hardware/gralloc.h>
 
 #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
 
-#include "base_composer.h"
-#include "hwcomposer.h"
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
 
 namespace cvd {
 
-class VSoCComposer : public BaseComposer {
+class CpuComposer : public BaseComposer {
  public:
-  VSoCComposer(int64_t vsync_base_timestamp, int32_t vsync_period_ns);
-  ~VSoCComposer();
+  CpuComposer(int64_t vsync_base_timestamp,
+              std::unique_ptr<ScreenView> screen_view);
+  ~CpuComposer() = default;
 
   // override
-  int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
+  int PrepareLayers(size_t num_layers, cvd_hwc_layer* layers);
   // override
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
+  int SetLayers(size_t num_layers, cvd_hwc_layer* layers);
 
  protected:
   static const int kNumTmpBufferPieces;
   uint8_t* RotateTmpBuffer(unsigned int order);
   uint8_t* GetSpecialTmpBuffer(size_t needed_size);
-  void CompositeLayer(vsoc_hwc_layer* src_layer, int32_t fb_offset);
+  void CompositeLayer(cvd_hwc_layer* src_layer, int32_t fb_offset);
   std::vector<uint8_t> tmp_buffer_;
   std::vector<uint8_t> special_tmp_buffer_;
 };
diff --git a/guest/hals/hwcomposer/cutf_cvm/geometry_utils.cpp b/guest/hals/hwcomposer/common/geometry_utils.cpp
similarity index 89%
rename from guest/hals/hwcomposer/cutf_cvm/geometry_utils.cpp
rename to guest/hals/hwcomposer/common/geometry_utils.cpp
index 75b7a61..a348026 100644
--- a/guest/hals/hwcomposer/cutf_cvm/geometry_utils.cpp
+++ b/guest/hals/hwcomposer/common/geometry_utils.cpp
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#include "geometry_utils.h"
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+
 #include <algorithm>
 #include <utility>
 
 namespace cvd {
 
-bool LayersOverlap(const vsoc_hwc_layer& layer1, const vsoc_hwc_layer& layer2) {
+bool LayersOverlap(const cvd_hwc_layer& layer1, const cvd_hwc_layer& layer2) {
   int left1 = layer1.displayFrame.left;
   int right1 = layer1.displayFrame.right;
   int top1 = layer1.displayFrame.top;
diff --git a/guest/hals/hwcomposer/cutf_cvm/geometry_utils.h b/guest/hals/hwcomposer/common/geometry_utils.h
similarity index 83%
rename from guest/hals/hwcomposer/cutf_cvm/geometry_utils.h
rename to guest/hals/hwcomposer/common/geometry_utils.h
index 937283f..aadaec3 100644
--- a/guest/hals/hwcomposer/cutf_cvm/geometry_utils.h
+++ b/guest/hals/hwcomposer/common/geometry_utils.h
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-#include "hwcomposer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
 
 namespace cvd {
 
-bool LayersOverlap(const vsoc_hwc_layer& layer1, const vsoc_hwc_layer& layer2);
+bool LayersOverlap(const cvd_hwc_layer& layer1, const cvd_hwc_layer& layer2);
 
 }  // namespace cvd
diff --git a/guest/hals/hwcomposer/common/hwcomposer.cpp b/guest/hals/hwcomposer/common/hwcomposer.cpp
index 56b2315..84de82d 100644
--- a/guest/hals/hwcomposer/common/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/common/hwcomposer.cpp
@@ -14,18 +14,67 @@
  * limitations under the License.
  */
 
+// Versions of hwcomposer we implement:
+// JB: 0.3
+// JB-MR1 to N : 1.1
+// N-MR1 to ... : We report 1.1 but SurfaceFlinger has the option to use an
+// adapter to treat our 1.1 hwcomposer as a 2.0. If SF stops using that adapter
+// to support 1.1 implementations it can be copied into cuttlefish from
+// frameworks/native/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.*
+
 #define LOG_TAG "hwc.cf_x86"
 #define HWC_REMOVE_DEPRECATED_VERSIONS 1
 
-#include "hwcomposer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
 
 #include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <poll.h>
+#include <pthread.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <sync/sync.h>
 #include <sys/resource.h>
 #include <sys/time.h>
+
 #include <string>
 
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
 #include <log/log.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+#include "guest/libs/platform_support/api_level_fixes.h"
+
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/cpu_composer.h"
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
+
+#ifdef USE_OLD_HWCOMPOSER
+typedef cvd::BaseComposer InnerComposerType;
+#else
+typedef cvd::CpuComposer InnerComposerType;
+#endif
+
+#ifdef GATHER_STATS
+typedef cvd::StatsKeepingComposer<InnerComposerType> ComposerType;
+#else
+typedef InnerComposerType ComposerType;
+#endif
+
+struct cvd_hwc_composer_device_1_t {
+  cvd_hwc_device base;
+  cvd::hwc_composer_device_data_t vsync_data;
+  ComposerType* composer;
+};
 
 namespace cvd {
 
@@ -45,7 +94,7 @@
     struct timespec rt;
     if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
       LOG_ALWAYS_FATAL("%s:%d error in vsync thread clock_gettime: %s",
-        __FILE__, __LINE__, strerror(errno));
+                       __FILE__, __LINE__, strerror(errno));
     }
 
     int64_t timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
@@ -90,3 +139,401 @@
 }
 
 }  // namespace cvd
+
+namespace {
+
+std::string CompositionString(int type) {
+  switch (type) {
+    case HWC_FRAMEBUFFER:
+      return "Framebuffer";
+    case HWC_OVERLAY:
+      return "Overlay";
+    case HWC_BACKGROUND:
+      return "Background";
+    case HWC_FRAMEBUFFER_TARGET:
+      return "FramebufferTarget";
+#if VSOC_PLATFORM_SDK_AFTER(K)
+    case HWC_SIDEBAND:
+      return "Sideband";
+    case HWC_CURSOR_OVERLAY:
+      return "CursorOverlay";
+#endif
+    default:
+      return std::string("Unknown (") + std::to_string(type) + ")";
+  }
+}
+
+void LogLayers(int num_layers, cvd_hwc_layer* layers, int invalid) {
+  ALOGE("Layers:");
+  for (int idx = 0; idx < num_layers; ++idx) {
+    std::string log_line;
+    if (idx == invalid) {
+      log_line = "Invalid layer: ";
+    }
+    log_line +=
+        "Composition Type: " + CompositionString(layers[idx].compositionType);
+    ALOGE("%s", log_line.c_str());
+  }
+}
+
+// Ensures that the layer does not include any inconsistencies
+bool IsValidLayer(const cvd_hwc_layer& layer) {
+  if (layer.flags & HWC_SKIP_LAYER) {
+    // A layer we are asked to skip validate should not be marked as skip
+    ALOGE("%s: Layer is marked as skip", __FUNCTION__);
+    return false;
+  }
+  // Check displayFrame
+  if (layer.displayFrame.left > layer.displayFrame.right ||
+      layer.displayFrame.top > layer.displayFrame.bottom) {
+    ALOGE(
+        "%s: Malformed rectangle (displayFrame): [left = %d, right = %d, top = "
+        "%d, bottom = %d]",
+        __FUNCTION__, layer.displayFrame.left, layer.displayFrame.right,
+        layer.displayFrame.top, layer.displayFrame.bottom);
+    return false;
+  }
+  // Validate the handle
+  if (private_handle_t::validate(layer.handle) != 0) {
+    ALOGE("%s: Layer contains an invalid gralloc handle.", __FUNCTION__);
+    return false;
+  }
+  const private_handle_t* p_handle =
+      reinterpret_cast<const private_handle_t*>(layer.handle);
+  // Check sourceCrop
+  if (layer.sourceCrop.left > layer.sourceCrop.right ||
+      layer.sourceCrop.top > layer.sourceCrop.bottom) {
+    ALOGE(
+        "%s: Malformed rectangle (sourceCrop): [left = %d, right = %d, top = "
+        "%d, bottom = %d]",
+        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
+        layer.sourceCrop.top, layer.sourceCrop.bottom);
+    return false;
+  }
+  if (layer.sourceCrop.left < 0 || layer.sourceCrop.top < 0 ||
+      layer.sourceCrop.right > p_handle->x_res ||
+      layer.sourceCrop.bottom > p_handle->y_res) {
+    ALOGE(
+        "%s: Invalid sourceCrop for buffer handle: sourceCrop = [left = %d, "
+        "right = %d, top = %d, bottom = %d], handle = [width = %d, height = "
+        "%d]",
+        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
+        layer.sourceCrop.top, layer.sourceCrop.bottom, p_handle->x_res,
+        p_handle->y_res);
+    return false;
+  }
+  return true;
+}
+
+bool IsValidComposition(int num_layers, cvd_hwc_layer* layers, bool on_set) {
+  if (num_layers == 0) {
+    ALOGE("Composition requested with 0 layers");
+    return false;
+  }
+  // Sometimes the hwcomposer receives a prepare and set calls with no other
+  // layer than the FRAMEBUFFER_TARGET with a null handler. We treat this case
+  // independently as a valid composition, but issue a warning about it.
+  if (num_layers == 1 && layers[0].compositionType == HWC_FRAMEBUFFER_TARGET &&
+      layers[0].handle == NULL) {
+    ALOGW("Received request for empty composition, treating as valid noop");
+    return true;
+  }
+  // The FRAMEBUFFER_TARGET layer needs to be sane only if
+  // there is at least one layer marked HWC_FRAMEBUFFER or if there is no layer
+  // marked HWC_OVERLAY (i.e some layers where composed with OpenGL, no layer
+  // marked overlay or framebuffer means that surfaceflinger decided to go for
+  // OpenGL without asking the hwcomposer first)
+  bool check_fb_target = true;
+  for (int idx = 0; idx < num_layers; ++idx) {
+    if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
+      // There is at least one, so it needs to be checked.
+      // It may have been set to false before, so ensure it's set to true.
+      check_fb_target = true;
+      break;
+    }
+    if (layers[idx].compositionType == HWC_OVERLAY) {
+      // At least one overlay, we may not need to.
+      check_fb_target = false;
+    }
+  }
+
+  for (int idx = 0; idx < num_layers; ++idx) {
+    switch (layers[idx].compositionType) {
+      case HWC_FRAMEBUFFER_TARGET:
+        // In the call to prepare() the framebuffer target does not have a valid
+        // buffer_handle, so we don't validate it yet.
+        if (on_set && check_fb_target && !IsValidLayer(layers[idx])) {
+          ALOGE("%s: Invalid layer found", __FUNCTION__);
+          LogLayers(num_layers, layers, idx);
+          return false;
+        }
+        break;
+      case HWC_OVERLAY:
+        if (!(layers[idx].flags & HWC_SKIP_LAYER) &&
+            !IsValidLayer(layers[idx])) {
+          ALOGE("%s: Invalid layer found", __FUNCTION__);
+          LogLayers(num_layers, layers, idx);
+          return false;
+        }
+        break;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
+static int cvd_hwc_prepare(cvd_hwc_device* dev, hwc_layer_list_t* list) {
+#else
+static int cvd_hwc_prepare(cvd_hwc_device* dev, size_t numDisplays,
+                           hwc_display_contents_1_t** displays) {
+  if (!numDisplays || !displays) return 0;
+
+  hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY];
+
+  if (!list) return 0;
+#endif
+  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], false)) {
+    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+    return -1;
+  }
+  reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->PrepareLayers(
+      list->numHwLayers, &list->hwLayers[0]);
+  return 0;
+}
+
+#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
+int cvd_hwc_set(struct hwc_composer_device* dev, hwc_display_t dpy,
+                hwc_surface_t sur, hwc_layer_list_t* list) {
+  if (list->numHwLayers == 1 &&
+      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
+    ALOGW("Received request for empty composition, treating as valid noop");
+    return 0;
+  }
+  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], true)) {
+    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+    return -1;
+  }
+  return reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)
+      ->composer->SetLayers(list->numHwLayers, &list->hwLayers[0]);
+}
+#else
+static int cvd_hwc_set(cvd_hwc_device* dev, size_t numDisplays,
+                       hwc_display_contents_1_t** displays) {
+  if (!numDisplays || !displays) return 0;
+
+  hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
+  if (!contents) return 0;
+
+  cvd_hwc_layer* layers = &contents->hwLayers[0];
+  if (contents->numHwLayers == 1 &&
+      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
+    ALOGW("Received request for empty composition, treating as valid noop");
+    return 0;
+  }
+  if (!IsValidComposition(contents->numHwLayers, layers, true)) {
+    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+    return -1;
+  }
+  int retval =
+      reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
+          contents->numHwLayers, layers);
+
+  int closedFds = 0;
+  for (size_t index = 0; index < contents->numHwLayers; ++index) {
+    if (layers[index].acquireFenceFd != -1) {
+      close(layers[index].acquireFenceFd);
+      layers[index].acquireFenceFd = -1;
+      ++closedFds;
+    }
+  }
+  if (closedFds) {
+    ALOGI("Saw %zu layers, closed=%d", contents->numHwLayers, closedFds);
+  }
+
+  // TODO(ghartman): This should be set before returning. On the next set it
+  // should be signalled when we load the new frame.
+  contents->retireFenceFd = -1;
+  return retval;
+}
+#endif
+
+static void cvd_hwc_register_procs(cvd_hwc_device* dev,
+                                   const hwc_procs_t* procs) {
+  struct cvd_hwc_composer_device_1_t* pdev =
+      (struct cvd_hwc_composer_device_1_t*)dev;
+  pdev->vsync_data.procs = procs;
+}
+
+static int cvd_hwc_query(cvd_hwc_device* dev, int what, int* value) {
+  struct cvd_hwc_composer_device_1_t* pdev =
+      (struct cvd_hwc_composer_device_1_t*)dev;
+
+  switch (what) {
+    case HWC_BACKGROUND_LAYER_SUPPORTED:
+      // we support the background layer
+      value[0] = 0;
+      break;
+    case HWC_VSYNC_PERIOD:
+      value[0] = pdev->vsync_data.vsync_period_ns;
+      break;
+    default:
+      // unsupported query
+      ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static int cvd_hwc_event_control(
+#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
+    cvd_hwc_device* /*dev*/, int event, int /*enabled*/) {
+#else
+    cvd_hwc_device* /*dev*/, int /*dpy*/, int event, int /*enabled*/) {
+#endif
+
+  if (event == HWC_EVENT_VSYNC) {
+    return 0;
+  }
+  return -EINVAL;
+}
+
+static int cvd_hwc_blank(cvd_hwc_device* /*dev*/, int disp, int /*blank*/) {
+  if (!IS_PRIMARY_DISPLAY(disp)) return -EINVAL;
+  return 0;
+}
+
+static void cvd_hwc_dump(cvd_hwc_device* dev, char* buff, int buff_len) {
+  reinterpret_cast<cvd_hwc_composer_device_1_t*>(dev)->composer->Dump(buff,
+                                                                      buff_len);
+}
+
+static int cvd_hwc_get_display_configs(cvd_hwc_device* /*dev*/, int disp,
+                                       uint32_t* configs, size_t* numConfigs) {
+  if (*numConfigs == 0) return 0;
+
+  if (IS_PRIMARY_DISPLAY(disp)) {
+    configs[0] = 0;
+    *numConfigs = 1;
+    return 0;
+  }
+
+  return -EINVAL;
+}
+
+#if VSOC_PLATFORM_SDK_AFTER(J)
+static int32_t cvd_hwc_attribute(struct cvd_hwc_composer_device_1_t* pdev,
+                                 const uint32_t attribute) {
+  switch (attribute) {
+    case HWC_DISPLAY_VSYNC_PERIOD:
+      return pdev->vsync_data.vsync_period_ns;
+    case HWC_DISPLAY_WIDTH:
+      return pdev->composer->x_res();
+    case HWC_DISPLAY_HEIGHT:
+      return pdev->composer->y_res();
+    case HWC_DISPLAY_DPI_X:
+      ALOGI("Reporting DPI_X of %d", pdev->composer->dpi());
+      // The number of pixels per thousand inches
+      return pdev->composer->dpi() * 1000;
+    case HWC_DISPLAY_DPI_Y:
+      ALOGI("Reporting DPI_Y of %d", pdev->composer->dpi());
+      // The number of pixels per thousand inches
+      return pdev->composer->dpi() * 1000;
+    default:
+      ALOGE("unknown display attribute %u", attribute);
+      return -EINVAL;
+  }
+}
+
+static int cvd_hwc_get_display_attributes(cvd_hwc_device* dev, int disp,
+                                          uint32_t config __unused,
+                                          const uint32_t* attributes,
+                                          int32_t* values) {
+  struct cvd_hwc_composer_device_1_t* pdev =
+      (struct cvd_hwc_composer_device_1_t*)dev;
+
+  if (!IS_PRIMARY_DISPLAY(disp)) {
+    ALOGE("unknown display type %u", disp);
+    return -EINVAL;
+  }
+
+  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+    values[i] = cvd_hwc_attribute(pdev, attributes[i]);
+  }
+
+  return 0;
+}
+#endif
+
+static int cvd_hwc_close(hw_device_t* device) {
+  struct cvd_hwc_composer_device_1_t* dev =
+      (struct cvd_hwc_composer_device_1_t*)device;
+  ALOGE("cvd_hwc_close");
+  pthread_kill(dev->vsync_data.vsync_thread, SIGTERM);
+  pthread_join(dev->vsync_data.vsync_thread, NULL);
+  delete dev->composer;
+  delete dev;
+  return 0;
+}
+
+namespace cvd {
+
+int cvd_hwc_open(std::unique_ptr<ScreenView> screen_view,
+                 const struct hw_module_t* module, const char* name,
+                 struct hw_device_t** device) {
+  ALOGI("%s", __FUNCTION__);
+  if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
+    ALOGE("%s called with bad name %s", __FUNCTION__, name);
+    return -EINVAL;
+  }
+
+  cvd_hwc_composer_device_1_t* dev = new cvd_hwc_composer_device_1_t();
+  if (!dev) {
+    ALOGE("%s failed to allocate dev", __FUNCTION__);
+    return -ENOMEM;
+  }
+
+  struct timespec rt;
+  if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
+    ALOGE("%s:%d error in vsync thread clock_gettime: %s", __FILE__, __LINE__,
+          strerror(errno));
+  }
+  dev->vsync_data.vsync_base_timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
+  dev->vsync_data.vsync_period_ns = 1e9 / screen_view->refresh_rate();
+
+  dev->base.common.tag = HARDWARE_DEVICE_TAG;
+  dev->base.common.version = VSOC_HWC_DEVICE_API_VERSION;
+  dev->base.common.module = const_cast<hw_module_t*>(module);
+  dev->base.common.close = cvd_hwc_close;
+
+  dev->base.prepare = cvd_hwc_prepare;
+  dev->base.set = cvd_hwc_set;
+  dev->base.query = cvd_hwc_query;
+  dev->base.registerProcs = cvd_hwc_register_procs;
+  dev->base.dump = cvd_hwc_dump;
+#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
+  static hwc_methods_t hwc_methods = {cvd_hwc_event_control};
+  dev->base.methods = &hwc_methods;
+#else
+  dev->base.blank = cvd_hwc_blank;
+  dev->base.eventControl = cvd_hwc_event_control;
+  dev->base.getDisplayConfigs = cvd_hwc_get_display_configs;
+  dev->base.getDisplayAttributes = cvd_hwc_get_display_attributes;
+#endif
+  dev->composer = new ComposerType(dev->vsync_data.vsync_base_timestamp,
+                                   std::move(screen_view));
+  int ret = pthread_create(&dev->vsync_data.vsync_thread, NULL,
+                           cvd::hwc_vsync_thread, &dev->vsync_data);
+  if (ret) {
+    ALOGE("failed to start vsync thread: %s", strerror(ret));
+    ret = -ret;
+    delete dev;
+  } else {
+    *device = &dev->base.common;
+  }
+
+  return ret;
+}
+
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/common/hwcomposer.h b/guest/hals/hwcomposer/common/hwcomposer.h
index 8c57e71..e326376 100644
--- a/guest/hals/hwcomposer/common/hwcomposer.h
+++ b/guest/hals/hwcomposer/common/hwcomposer.h
@@ -15,15 +15,40 @@
  * limitations under the License.
  */
 
+#include <memory>
+
 #include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+
+#include "guest/libs/platform_support/api_level_fixes.h"
+
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
+typedef hwc_composer_device_t cvd_hwc_device;
+typedef hwc_layer_t cvd_hwc_layer;
+#define IS_TARGET_FRAMEBUFFER(x) false
+#define IS_PRIMARY_DISPLAY(x) true
+#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_3
+#else
+typedef hwc_composer_device_1_t cvd_hwc_device;
+typedef hwc_layer_1_t cvd_hwc_layer;
+#define IS_TARGET_FRAMEBUFFER(x) ((x) == HWC_FRAMEBUFFER_TARGET)
+#define IS_PRIMARY_DISPLAY(x) ((x) == HWC_DISPLAY_PRIMARY)
+#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_1_1
+#endif
 
 namespace cvd {
-  struct hwc_composer_device_data_t {
-    const hwc_procs_t* procs;
-    pthread_t vsync_thread;
-    int64_t vsync_base_timestamp;
-    int32_t vsync_period_ns;
-  };
+struct hwc_composer_device_data_t {
+  const hwc_procs_t* procs;
+  pthread_t vsync_thread;
+  int64_t vsync_base_timestamp;
+  int32_t vsync_period_ns;
+};
 
-  void* hwc_vsync_thread(void* data);
+void* hwc_vsync_thread(void* data);
+
+int cvd_hwc_open(std::unique_ptr<ScreenView> screen_view,
+                 const struct hw_module_t* module, const char* name,
+                 struct hw_device_t** device);
 }  // namespace cvd
diff --git a/guest/hals/hwcomposer/common/screen_view.cpp b/guest/hals/hwcomposer/common/screen_view.cpp
new file mode 100644
index 0000000..48f9fa6
--- /dev/null
+++ b/guest/hals/hwcomposer/common/screen_view.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+#include "common/libs/utils/size_utils.h"
+
+namespace cvd {
+
+int ScreenView::NextBuffer() {
+  int num_buffers = this->num_buffers();
+  last_buffer_ = num_buffers > 0 ? (last_buffer_ + 1) % num_buffers : -1;
+  return last_buffer_;
+}
+
+size_t ScreenView::buffer_size() const {
+  return line_length() * y_res() + 4 /* swiftshader padding */;
+}
+
+size_t ScreenView::line_length() const {
+  return cvd::AlignToPowerOf2(x_res() * bytes_per_pixel(), 4);
+}
+
+int ScreenView::bytes_per_pixel() const { return 4; }
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/common/screen_view.h b/guest/hals/hwcomposer/common/screen_view.h
new file mode 100644
index 0000000..b985f8f
--- /dev/null
+++ b/guest/hals/hwcomposer/common/screen_view.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/time.h>
+
+namespace cvd {
+
+struct CompositionStats {
+  uint32_t num_prepare_calls;
+  uint16_t num_layers;
+  uint16_t num_hwcomposited_layers;
+  timespec last_vsync;
+  timespec prepare_start;
+  timespec prepare_end;
+  timespec set_start;
+  timespec set_end;
+};
+
+class ScreenView {
+ public:
+  ScreenView() = default;
+  ScreenView(const ScreenView&) = delete;
+  virtual ~ScreenView() = default;
+
+  ScreenView& operator=(const ScreenView&) = delete;
+
+  virtual void Broadcast(int buffer_id,
+                         const CompositionStats* stats = nullptr) = 0;
+  virtual int NextBuffer();
+  virtual void* GetBuffer(int buffer_id) = 0;
+
+  virtual int32_t x_res() const = 0;
+  virtual int32_t y_res() const = 0;
+  virtual int32_t dpi() const = 0;
+  virtual int32_t refresh_rate() const = 0;
+
+  size_t buffer_size() const;
+  size_t line_length() const;
+  int bytes_per_pixel() const;
+
+  virtual int num_buffers() const = 0;
+
+ private:
+  int last_buffer_ = 0;
+};
+}  // namespace cvd
\ No newline at end of file
diff --git a/guest/hals/hwcomposer/vsoc/stats_keeper.cpp b/guest/hals/hwcomposer/common/stats_keeper.cpp
similarity index 96%
rename from guest/hals/hwcomposer/vsoc/stats_keeper.cpp
rename to guest/hals/hwcomposer/common/stats_keeper.cpp
index 5d87cd4..efff1d8 100644
--- a/guest/hals/hwcomposer/vsoc/stats_keeper.cpp
+++ b/guest/hals/hwcomposer/common/stats_keeper.cpp
@@ -14,15 +14,20 @@
  * limitations under the License.
  */
 
-#include <log/log.h>
+#include "guest/hals/hwcomposer/common/stats_keeper.h"
+
+#include <inttypes.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+
 #include <algorithm>
 #include <utility>
 #include <vector>
 
-#include "geometry_utils.h"
-#include "stats_keeper.h"
+#include <log/log.h>
+
+#include "guest/hals/hwcomposer/common/geometry_utils.h"
 
 using cvd::LockGuard;
 using cvd::Mutex;
@@ -31,8 +36,6 @@
 using cvd::time::Nanoseconds;
 using cvd::time::Seconds;
 using cvd::time::TimeDifference;
-using vsoc::layout::screen::TimeSpec;
-using vsoc::layout::screen::CompositionStats;
 
 namespace cvd {
 
@@ -53,9 +56,9 @@
   return *mset.rbegin();
 }
 
-void TimeDifferenceToTimeSpec(const TimeDifference& td, TimeSpec* ts) {
-  ts->ts_sec = td.seconds();
-  ts->ts_nsec = td.subseconds_in_ns();
+void TimeDifferenceToTimeSpec(const TimeDifference& td, timespec* ts) {
+  ts->tv_sec = td.seconds();
+  ts->tv_nsec = td.subseconds_in_ns();
 }
 
 }  // namespace
diff --git a/guest/hals/hwcomposer/vsoc/stats_keeper.h b/guest/hals/hwcomposer/common/stats_keeper.h
similarity index 75%
rename from guest/hals/hwcomposer/vsoc/stats_keeper.h
rename to guest/hals/hwcomposer/common/stats_keeper.h
index e1dd330..8eb0e49 100644
--- a/guest/hals/hwcomposer/vsoc/stats_keeper.h
+++ b/guest/hals/hwcomposer/common/stats_keeper.h
@@ -22,9 +22,9 @@
 
 #include "common/libs/threads/cuttlefish_thread.h"
 #include "common/libs/time/monotonic_time.h"
-#include "common/vsoc/lib/screen_region_view.h"
 
-#include "hwcomposer.h"
+#include "guest/hals/hwcomposer/common/base_composer.h"
+#include "guest/hals/hwcomposer/common/hwcomposer.h"
 
 namespace cvd {
 
@@ -94,7 +94,7 @@
   void RecordSetStart();
   void RecordSetEnd() EXCLUDES(mutex_);
 
-  void GetLastCompositionStats(vsoc::layout::screen::CompositionStats* stats_p);
+  void GetLastCompositionStats(CompositionStats* stats_p);
 
   // Calls to this function are synchronized with calls to 'RecordSetEnd' with a
   // mutex. The other Record* functions do not need such synchronization because
@@ -146,38 +146,62 @@
   mutable cvd::Mutex mutex_;
 };
 
+class WrappedScreenView : public ScreenView {
+ public:
+  WrappedScreenView(std::unique_ptr<ScreenView> screen_view,
+                    std::function<void(CompositionStats*)> stats_getter)
+      : screen_view_(std::move(screen_view)), stats_getter_(stats_getter) {}
+  virtual ~WrappedScreenView() = default;
+
+  void Broadcast(int buffer_id, const CompositionStats*) override {
+    // The composer object in stats_keeper produces null stats, use the ones
+    // provided by the stats_keeper instead.
+    CompositionStats stats;
+    stats_getter_(&stats);
+    return screen_view_->Broadcast(buffer_id, &stats);
+  }
+
+  void* GetBuffer(int buffer_id) override {
+    return screen_view_->GetBuffer(buffer_id);
+  }
+
+  int32_t x_res() const override { return screen_view_->x_res(); }
+
+  int32_t y_res() const override { return screen_view_->y_res(); }
+
+  int32_t dpi() const override { return screen_view_->dpi(); }
+
+  int32_t refresh_rate() const override { return screen_view_->refresh_rate(); }
+
+  int num_buffers() const override { return screen_view_->num_buffers(); }
+
+ private:
+  std::unique_ptr<ScreenView> screen_view_;
+  std::function<void(CompositionStats*)> stats_getter_;
+};
+
 template <class Composer>
-class StatsKeepingComposer {
+class StatsKeepingComposer : public BaseComposer {
  public:
   // Keep stats from the last 10 seconds.
-  StatsKeepingComposer(int64_t vsync_base_timestamp, int32_t vsync_period_ns)
-      : stats_keeper_(cvd::time::TimeDifference(cvd::time::Seconds(10), 1),
-                      vsync_base_timestamp, vsync_period_ns),
-        composer_(vsync_base_timestamp, vsync_period_ns) {
-    // Don't let the composer broadcast by itself, allow it to return to collect
-    // the timings and broadcast then.
-    composer_.ReplaceFbBroadcaster([this](int buffer_index){
-        BroadcastWithStats(buffer_index);
-      });
-  }
+  StatsKeepingComposer(int64_t vsync_base_timestamp,
+                       std::unique_ptr<ScreenView> screen_view)
+      : composer_(vsync_base_timestamp,
+                  std::unique_ptr<ScreenView>(new WrappedScreenView(
+                      std::move(screen_view),
+                      [this](CompositionStats* stats) { FinalizeStatsAndGet(stats); }))),
+        stats_keeper_(cvd::time::TimeDifference(cvd::time::Seconds(10), 1),
+                      vsync_base_timestamp, 1e9 / composer_.refresh_rate()) {}
   ~StatsKeepingComposer() = default;
 
-  int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+  int PrepareLayers(size_t num_layers, cvd_hwc_layer* layers) {
     stats_keeper_.RecordPrepareStart(num_layers);
     int num_hwc_layers = composer_.PrepareLayers(num_layers, layers);
     stats_keeper_.RecordPrepareEnd(num_hwc_layers);
     return num_hwc_layers;
   }
 
-  void BroadcastWithStats(int buffer_idx) {
-    stats_keeper_.RecordSetEnd();
-    vsoc::layout::screen::CompositionStats stats;
-    stats_keeper_.GetLastCompositionStats(&stats);
-    vsoc::screen::ScreenRegionView::GetInstance()
-      ->BroadcastNewFrame(static_cast<uint32_t>(buffer_idx), &stats);
-  }
-
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+  int SetLayers(size_t num_layers, cvd_hwc_layer* layers) {
     stats_keeper_.RecordSetStart();
     return composer_.SetLayers(num_layers, layers);
   }
@@ -186,9 +210,14 @@
     stats_keeper_.SynchronizedDump(buff, buff_len);
   }
 
+  void FinalizeStatsAndGet(CompositionStats* stats) {
+    stats_keeper_.RecordSetEnd();
+    stats_keeper_.GetLastCompositionStats(&stats);
+  }
+
  private:
-  StatsKeeper stats_keeper_;
   Composer composer_;
+  StatsKeeper stats_keeper_;
 };
 
 }  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/Android.bp b/guest/hals/hwcomposer/cutf_cvm/Android.bp
index f77486b..3835765 100644
--- a/guest/hals/hwcomposer/cutf_cvm/Android.bp
+++ b/guest/hals/hwcomposer/cutf_cvm/Android.bp
@@ -19,16 +19,17 @@
     defaults: ["cuttlefish_guest_only"],
     vendor: true,
     srcs: [
+        "vsocket_screen_view.cpp",
         "hwcomposer.cpp",
-        "geometry_utils.cpp",
-        "vsoc_composer.cpp",
-        "base_composer.cpp",
     ],
     include_dirs: [
         "device/google/cuttlefish_common",
     ],
     export_include_dirs: ["."],
-    static_libs: ["libyuv_static", "hwcomposer_common"],
+    static_libs: [
+        "libyuv_static", 
+        "hwcomposer_common"
+    ],
     shared_libs: [
         "cuttlefish_auto_resources",
         "liblog",
@@ -37,7 +38,6 @@
         "libcutils",
         "libutils",
         "libsync",
-        "libhardware",
         "libjpeg",
         "libcuttlefish_utils",
         "libcuttlefish_fs",
diff --git a/guest/hals/hwcomposer/cutf_cvm/base_composer.cpp b/guest/hals/hwcomposer/cutf_cvm/base_composer.cpp
deleted file mode 100644
index da55a95..0000000
--- a/guest/hals/hwcomposer/cutf_cvm/base_composer.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "base_composer.h"
-
-#include <string.h>
-
-#include <cutils/properties.h>
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-#include <common/libs/device_config/device_config.h>
-#include <common/libs/utils/size_utils.h>
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
-
-namespace cvd {
-
-BaseComposer::BaseComposer(int64_t vsync_base_timestamp)
-    : vsync_base_timestamp_(vsync_base_timestamp) {
-  vsync_period_ns_ = 1000000000 / frame_buffer_.refresh_rate();
-  hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
-                reinterpret_cast<const hw_module_t**>(&gralloc_module_));
-}
-
-BaseComposer::~BaseComposer() {}
-
-void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
-
-int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
-  int fb_index = frame_buffer_.NextScreenBuffer();
-  void* frame_buffer = frame_buffer_.GetBuffer(fb_index);
-  const private_handle_t* p_handle =
-      reinterpret_cast<const private_handle_t*>(buffer_handle);
-  void* buffer;
-  int retval = gralloc_module_->lock(gralloc_module_, buffer_handle,
-                                     GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
-                                     p_handle->x_res, p_handle->y_res, &buffer);
-  if (retval != 0) {
-    ALOGE("Got error code %d from lock function", retval);
-    return -1;
-  }
-  memcpy(frame_buffer, buffer, frame_buffer_.buffer_size());
-  frame_buffer_.Broadcast(fb_index);
-  return 0;
-}  // namespace cvd
-
-int BaseComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  // find unsupported overlays
-  for (size_t i = 0; i < num_layers; i++) {
-    if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) {
-      continue;
-    }
-    layers[i].compositionType = HWC_FRAMEBUFFER;
-  }
-  return 0;
-}
-
-int BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  for (size_t idx = 0; idx < num_layers; idx++) {
-    if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
-      return PostFrameBufferTarget(layers[idx].handle);
-    }
-  }
-  return -1;
-}
-
-FrameBuffer::FrameBuffer()
-    : broadcast_thread_([this]() { BroadcastLoop(); }) {
-  GetScreenParameters();
-  // inner_buffer needs to be initialized after the final values of the screen
-  // parameters are set (either from the config server or default).
-  inner_buffer_ = std::vector<char>(buffer_size() * 8);
-}
-
-FrameBuffer::~FrameBuffer() {
-  running_ = false;
-  broadcast_thread_.join();
-}
-
-int FrameBuffer::NextScreenBuffer() {
-  int num_buffers = inner_buffer_.size() / buffer_size();
-  last_frame_buffer_ =
-      num_buffers > 0 ? (last_frame_buffer_ + 1) % num_buffers : -1;
-  return last_frame_buffer_;
-}
-
-void FrameBuffer::GetScreenParameters() {
-  auto device_config = cvd::DeviceConfig::Get();
-  if (!device_config) {
-    LOG(INFO) << "Failed to obtain device configuration from server, running in"
-              << " headless mode";
-    // It is impossible to ensure host and guest agree on the screen parameters
-    // if these could not be read from the host configuration server. It's best
-    // to not attempt to send frames in this case.
-    running_ = false;
-    // Do a phony Broadcast to ensure the broadcaster thread exits.
-    Broadcast(-1);
-    return;
-  }
-  x_res_ = device_config->screen_x_res();
-  y_res_ = device_config->screen_y_res();
-  dpi_ = device_config->screen_dpi();
-  refresh_rate_ = device_config->screen_refresh_rate();
-}
-
-bool FrameBuffer::ConnectToScreenServer() {
-  auto vsock_frames_port = property_get_int32("ro.boot.vsock_frames_port", -1);
-  if (vsock_frames_port <= 0) {
-    LOG(INFO) << "No screen server configured, operating on headless mode";
-    return false;
-  }
-
-  screen_server_ = cvd::SharedFD::VsockClient(2, vsock_frames_port,
-                                              SOCK_STREAM);
-  if (!screen_server_->IsOpen()) {
-    LOG(ERROR) << "Unable to connect to screen server: "
-               << screen_server_->StrError();
-    return false;
-  }
-
-  return true;
-}
-
-void FrameBuffer::BroadcastLoop() {
-  auto connected = ConnectToScreenServer();
-  if (!connected) {
-    LOG(ERROR) << "Broadcaster thread exiting due to no connection to screen"
-               << " server. Compositions will occur, but frames won't be sent"
-               << " anywhere";
-    return;
-  }
-  int32_t current_seq = 0;
-  int32_t current_offset;
-  LOG(INFO) << "Broadcaster thread loop starting";
-  while (true) {
-    {
-      std::unique_lock<std::mutex> lock(mutex_);
-      while (running_ && current_seq == current_seq_) {
-        cond_var_.wait(lock);
-      }
-      if (!running_) {
-        LOG(INFO) << "Broadcaster thread exiting";
-        return;
-      }
-      current_offset = current_offset_;
-      current_seq = current_seq_;
-    }
-    int32_t size = buffer_size();
-    screen_server_->Write(&size, sizeof(size));
-    auto buff = static_cast<char*>(GetBuffer(current_offset));
-    while (size > 0) {
-      auto written = screen_server_->Write(buff, size);
-      size -= written;
-      buff += written;
-    }
-  }
-}
-
-void FrameBuffer::Broadcast(int32_t offset) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  current_offset_ = offset;
-  current_seq_++;
-  cond_var_.notify_all();
-}
-void* FrameBuffer::GetBuffer(int fb_index) {
-  return &inner_buffer_[buffer_size() * fb_index];
-}
-size_t FrameBuffer::buffer_size() {
-  return (line_length() * y_res()) + 4;
-}
-int32_t FrameBuffer::x_res() { return x_res_; }
-int32_t FrameBuffer::y_res() { return y_res_; }
-int32_t FrameBuffer::line_length() {
-  return cvd::AlignToPowerOf2(x_res() * bytes_per_pixel(), 4);
-}
-int32_t FrameBuffer::bytes_per_pixel() { return 4; }
-int32_t FrameBuffer::dpi() { return dpi_; }
-int32_t FrameBuffer::refresh_rate() { return refresh_rate_; }
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/base_composer.h b/guest/hals/hwcomposer/cutf_cvm/base_composer.h
deleted file mode 100644
index fef1eee..0000000
--- a/guest/hals/hwcomposer/cutf_cvm/base_composer.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <functional>
-#include <mutex>
-#include <thread>
-#include <vector>
-
-#include <hardware/gralloc.h>
-#include <common/libs/fs/shared_fd.h>
-#include "hwcomposer.h"
-
-namespace cvd {
-
-class FrameBuffer{
- public:
-  FrameBuffer();
-  ~FrameBuffer();
-
-  void Broadcast(int32_t offset);
-  int NextScreenBuffer();
-  void* GetBuffer(int fb_index);
-  size_t buffer_size();
-  int32_t x_res();
-  int32_t y_res();
-  int32_t line_length();
-  int32_t bytes_per_pixel();
-  int32_t dpi();
-  int32_t refresh_rate();
- private:
-  bool ConnectToScreenServer();
-  void GetScreenParameters();
-  void BroadcastLoop();
-
-  std::vector<char> inner_buffer_;
-  int last_frame_buffer_ = 0;
-  cvd::SharedFD screen_server_;
-  std::thread broadcast_thread_;
-  int32_t current_offset_ = 0;
-  int32_t current_seq_ = 0;
-  std::mutex mutex_;
-  std::condition_variable cond_var_;
-  bool running_ = true;
-  int32_t x_res_{720};
-  int32_t y_res_{1280};
-  int32_t dpi_{160};
-  int32_t refresh_rate_{60};
-};
-
-class BaseComposer {
- public:
-  BaseComposer(int64_t vsync_base_timestamp);
-  ~BaseComposer();
-
-  // Sets the composition type of each layer and returns the number of layers
-  // to be composited by the hwcomposer.
-  int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  // Returns 0 if successful.
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  void Dump(char* buff, int buff_len);
-
-  int32_t x_res() {
-    return frame_buffer_.x_res();
-  }
-  int32_t y_res() {
-    return frame_buffer_.y_res();
-  }
-  int32_t dpi() {
-    return frame_buffer_.dpi();
-  }
-  int32_t refresh_rate() {
-    return frame_buffer_.refresh_rate();
-  }
-
- protected:
-  const gralloc_module_t* gralloc_module_;
-  int64_t vsync_base_timestamp_;
-  int32_t vsync_period_ns_;
-  FrameBuffer frame_buffer_;
-
- private:
-  // Returns buffer offset or negative on error.
-  int PostFrameBufferTarget(buffer_handle_t handle);
-};
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp b/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp
index 3db7f80..976a68c 100644
--- a/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/cutf_cvm/hwcomposer.cpp
@@ -14,470 +14,39 @@
  * limitations under the License.
  */
 
-// Versions of hwcomposer we implement:
-// JB: 0.3
-// JB-MR1 to N : 1.1
-// N-MR1 to ... : We report 1.1 but SurfaceFlinger has the option to use an
-// adapter to treat our 1.1 hwcomposer as a 2.0. If SF stops using that adapter
-// to support 1.1 implementations it can be copied into cuttlefish from
-// frameworks/native/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.*
+#define LOG_TAG "hwc.cutf_cvm"
 
-#define LOG_TAG "hwc.cf_x86"
-
-#include <guest/libs/platform_support/api_level_fixes.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <math.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-
-#include <string>
-
-#define HWC_REMOVE_DEPRECATED_VERSIONS 1
-
-#include <cutils/compiler.h>
-#include <log/log.h>
 #include <cutils/properties.h>
-#include <hardware/gralloc.h>
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 #include <hardware/hwcomposer_defs.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
+#include <log/log.h>
 
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
 #include "guest/hals/hwcomposer/common/hwcomposer.h"
-#include <sync/sync.h>
 
-#include "base_composer.h"
-#include "geometry_utils.h"
-#include "hwcomposer.h"
-#include "vsoc_composer.h"
+#include "guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h"
 
-#ifdef USE_OLD_HWCOMPOSER
-typedef cvd::BaseComposer InnerComposerType;
-#else
-typedef cvd::VSoCComposer InnerComposerType;
-#endif
-
-typedef InnerComposerType ComposerType;
-
-struct vsoc_hwc_composer_device_1_t {
-  vsoc_hwc_device base;
-  cvd::hwc_composer_device_data_t vsync_data;
-  ComposerType* composer;
-};
-
-namespace {
-
-std::string CompositionString(int type) {
-  switch (type) {
-    case HWC_FRAMEBUFFER:
-      return "Framebuffer";
-    case HWC_OVERLAY:
-      return "Overlay";
-    case HWC_BACKGROUND:
-      return "Background";
-    case HWC_FRAMEBUFFER_TARGET:
-      return "FramebufferTarget";
-#if VSOC_PLATFORM_SDK_AFTER(K)
-    case HWC_SIDEBAND:
-      return "Sideband";
-    case HWC_CURSOR_OVERLAY:
-      return "CursorOverlay";
-#endif
-    default:
-      return std::string("Unknown (") + std::to_string(type) + ")";
-  }
-}
-
-void LogLayers(int num_layers, vsoc_hwc_layer* layers, int invalid) {
-  ALOGE("Layers:");
-  for (int idx = 0; idx < num_layers; ++idx) {
-    std::string log_line;
-    if (idx == invalid) {
-      log_line = "Invalid layer: ";
-    }
-    log_line +=
-        "Composition Type: " + CompositionString(layers[idx].compositionType);
-    ALOGE("%s", log_line.c_str());
-  }
-}
-
-// Ensures that the layer does not include any inconsistencies
-bool IsValidLayer(const vsoc_hwc_layer& layer) {
-  if (layer.flags & HWC_SKIP_LAYER) {
-    // A layer we are asked to skip validate should not be marked as skip
-    ALOGE("%s: Layer is marked as skip", __FUNCTION__);
-    return false;
-  }
-  // Check displayFrame
-  if (layer.displayFrame.left > layer.displayFrame.right ||
-      layer.displayFrame.top > layer.displayFrame.bottom) {
-    ALOGE(
-        "%s: Malformed rectangle (displayFrame): [left = %d, right = %d, top = "
-        "%d, bottom = %d]",
-        __FUNCTION__, layer.displayFrame.left, layer.displayFrame.right,
-        layer.displayFrame.top, layer.displayFrame.bottom);
-    return false;
-  }
-  // Validate the handle
-  if (private_handle_t::validate(layer.handle) != 0) {
-    ALOGE("%s: Layer contains an invalid gralloc handle.", __FUNCTION__);
-    return false;
-  }
-  const private_handle_t* p_handle =
-      reinterpret_cast<const private_handle_t*>(layer.handle);
-  // Check sourceCrop
-  if (layer.sourceCrop.left > layer.sourceCrop.right ||
-      layer.sourceCrop.top > layer.sourceCrop.bottom) {
-    ALOGE(
-        "%s: Malformed rectangle (sourceCrop): [left = %d, right = %d, top = "
-        "%d, bottom = %d]",
-        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
-        layer.sourceCrop.top, layer.sourceCrop.bottom);
-    return false;
-  }
-  if (layer.sourceCrop.left < 0 || layer.sourceCrop.top < 0 ||
-      layer.sourceCrop.right > p_handle->x_res ||
-      layer.sourceCrop.bottom > p_handle->y_res) {
-    ALOGE(
-        "%s: Invalid sourceCrop for buffer handle: sourceCrop = [left = %d, "
-        "right = %d, top = %d, bottom = %d], handle = [width = %d, height = "
-        "%d]",
-        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
-        layer.sourceCrop.top, layer.sourceCrop.bottom, p_handle->x_res,
-        p_handle->y_res);
-    return false;
-  }
-  return true;
-}
-
-bool IsValidComposition(int num_layers, vsoc_hwc_layer* layers, bool on_set) {
-  if (num_layers == 0) {
-    ALOGE("Composition requested with 0 layers");
-    return false;
-  }
-  // Sometimes the hwcomposer receives a prepare and set calls with no other
-  // layer than the FRAMEBUFFER_TARGET with a null handler. We treat this case
-  // independently as a valid composition, but issue a warning about it.
-  if (num_layers == 1 && layers[0].compositionType == HWC_FRAMEBUFFER_TARGET &&
-      layers[0].handle == NULL) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return true;
-  }
-  // The FRAMEBUFFER_TARGET layer needs to be sane only if
-  // there is at least one layer marked HWC_FRAMEBUFFER or if there is no layer
-  // marked HWC_OVERLAY (i.e some layers where composed with OpenGL, no layer
-  // marked overlay or framebuffer means that surfaceflinger decided to go for
-  // OpenGL without asking the hwcomposer first)
-  bool check_fb_target = true;
-  for (int idx = 0; idx < num_layers; ++idx) {
-    if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
-      // There is at least one, so it needs to be checked.
-      // It may have been set to false before, so ensure it's set to true.
-      check_fb_target = true;
-      break;
-    }
-    if (layers[idx].compositionType == HWC_OVERLAY) {
-      // At least one overlay, we may not need to.
-      check_fb_target = false;
-    }
-  }
-
-  for (int idx = 0; idx < num_layers; ++idx) {
-    switch (layers[idx].compositionType) {
-    case HWC_FRAMEBUFFER_TARGET:
-      // In the call to prepare() the framebuffer target does not have a valid
-      // buffer_handle, so we don't validate it yet.
-      if (on_set && check_fb_target && !IsValidLayer(layers[idx])) {
-        ALOGE("%s: Invalid layer found", __FUNCTION__);
-        LogLayers(num_layers, layers, idx);
-        return false;
-      }
-      break;
-    case HWC_OVERLAY:
-      if (!(layers[idx].flags & HWC_SKIP_LAYER) &&
-          !IsValidLayer(layers[idx])) {
-        ALOGE("%s: Invalid layer found", __FUNCTION__);
-        LogLayers(num_layers, layers, idx);
-        return false;
-      }
-      break;
-    }
-  }
-  return true;
-}
-
-}
-
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-static int vsoc_hwc_prepare(vsoc_hwc_device* dev, hwc_layer_list_t* list) {
-#else
-static int vsoc_hwc_prepare(vsoc_hwc_device* dev, size_t numDisplays,
-                            hwc_display_contents_1_t** displays) {
-  if (!numDisplays || !displays) return 0;
-
-  hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY];
-
-  if (!list) return 0;
-#endif
-  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], false)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+static int hwc_open(const struct hw_module_t* module, const char* name,
+                    struct hw_device_t** device) {
+  std::unique_ptr<cvd::ScreenView> screen_view(new cvd::VsocketScreenView());
+  if (!screen_view) {
+    ALOGE("Failed to instantiate screen view");
     return -1;
   }
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->PrepareLayers(
-      list->numHwLayers, &list->hwLayers[0]);
-  return 0;
+
+  return cvd::cvd_hwc_open(std::move(screen_view), module, name, device);
 }
 
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-int vsoc_hwc_set(struct hwc_composer_device* dev, hwc_display_t dpy,
-                 hwc_surface_t sur, hwc_layer_list_t* list) {
-  if (list->numHwLayers == 1 &&
-      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return 0;
-  }
-  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], true)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
-    return -1;
-  }
-  return reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)
-      ->composer->SetLayers(list->numHwLayers, &list->hwLayers[0]);
-}
-#else
-static int vsoc_hwc_set(vsoc_hwc_device* dev, size_t numDisplays,
-                        hwc_display_contents_1_t** displays) {
-  if (!numDisplays || !displays) return 0;
-
-  hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
-  if (!contents) return 0;
-
-  vsoc_hwc_layer* layers = &contents->hwLayers[0];
-  if (contents->numHwLayers == 1 &&
-      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return 0;
-  }
-  if (!IsValidComposition(contents->numHwLayers, layers, true)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
-    return -1;
-  }
-  int retval =
-      reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
-          contents->numHwLayers, layers);
-
-  int closedFds = 0;
-  for (size_t index = 0; index < contents->numHwLayers; ++index) {
-    if (layers[index].acquireFenceFd != -1) {
-      close(layers[index].acquireFenceFd);
-      layers[index].acquireFenceFd = -1;
-      ++closedFds;
-    }
-  }
-  if (closedFds) {
-    ALOGI("Saw %zu layers, closed=%d", contents->numHwLayers, closedFds);
-  }
-
-  // TODO(ghartman): This should be set before returning. On the next set it
-  // should be signalled when we load the new frame.
-  contents->retireFenceFd = -1;
-  return retval;
-}
-#endif
-
-static void vsoc_hwc_register_procs(vsoc_hwc_device* dev,
-                                    const hwc_procs_t* procs) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-  pdev->vsync_data.procs = procs;
-}
-
-static int vsoc_hwc_query(vsoc_hwc_device* dev, int what, int* value) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-
-  switch (what) {
-    case HWC_BACKGROUND_LAYER_SUPPORTED:
-      // we support the background layer
-      value[0] = 0;
-      break;
-    case HWC_VSYNC_PERIOD:
-      value[0] = pdev->vsync_data.vsync_period_ns;
-      break;
-    default:
-      // unsupported query
-      ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
-      return -EINVAL;
-  }
-  return 0;
-}
-
-static int vsoc_hwc_event_control(
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-    vsoc_hwc_device* /*dev*/, int event, int /*enabled*/) {
-#else
-    vsoc_hwc_device* /*dev*/, int /*dpy*/, int event, int /*enabled*/) {
-#endif
-
-  if (event == HWC_EVENT_VSYNC) {
-    return 0;
-  }
-  return -EINVAL;
-}
-
-static int vsoc_hwc_blank(vsoc_hwc_device* /*dev*/, int disp, int /*blank*/) {
-  if (!IS_PRIMARY_DISPLAY(disp)) return -EINVAL;
-  return 0;
-}
-
-static void vsoc_hwc_dump(vsoc_hwc_device* dev, char* buff, int buff_len) {
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->Dump(
-      buff, buff_len);
-}
-
-static int vsoc_hwc_get_display_configs(vsoc_hwc_device* /*dev*/, int disp,
-                                        uint32_t* configs, size_t* numConfigs) {
-  if (*numConfigs == 0) return 0;
-
-  if (IS_PRIMARY_DISPLAY(disp)) {
-    configs[0] = 0;
-    *numConfigs = 1;
-    return 0;
-  }
-
-  return -EINVAL;
-}
-
-#if VSOC_PLATFORM_SDK_AFTER(J)
-static int32_t vsoc_hwc_attribute(struct vsoc_hwc_composer_device_1_t* pdev,
-                                  const uint32_t attribute) {
-  switch (attribute) {
-    case HWC_DISPLAY_VSYNC_PERIOD:
-      return pdev->vsync_data.vsync_period_ns;
-    case HWC_DISPLAY_WIDTH:
-      return pdev->composer->x_res();
-    case HWC_DISPLAY_HEIGHT:
-      return pdev->composer->y_res();
-    case HWC_DISPLAY_DPI_X:
-      ALOGI("Reporting DPI_X of %d", pdev->composer->dpi());
-      // The number of pixels per thousand inches
-      return pdev->composer->dpi() * 1000;
-    case HWC_DISPLAY_DPI_Y:
-      ALOGI("Reporting DPI_Y of %d", pdev->composer->dpi());
-      // The number of pixels per thousand inches
-      return pdev->composer->dpi() * 1000;
-    default:
-      ALOGE("unknown display attribute %u", attribute);
-      return -EINVAL;
-  }
-}
-
-static int vsoc_hwc_get_display_attributes(vsoc_hwc_device* dev, int disp,
-                                           uint32_t config __unused,
-                                           const uint32_t* attributes,
-                                           int32_t* values) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-
-  if (!IS_PRIMARY_DISPLAY(disp)) {
-    ALOGE("unknown display type %u", disp);
-    return -EINVAL;
-  }
-
-  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
-    values[i] = vsoc_hwc_attribute(pdev, attributes[i]);
-  }
-
-  return 0;
-}
-#endif
-
-static int vsoc_hwc_close(hw_device_t* device) {
-  struct vsoc_hwc_composer_device_1_t* dev =
-      (struct vsoc_hwc_composer_device_1_t*)device;
-  ALOGE("vsoc_hwc_close");
-  pthread_kill(dev->vsync_data.vsync_thread, SIGTERM);
-  pthread_join(dev->vsync_data.vsync_thread, NULL);
-  delete dev->composer;
-  delete dev;
-  return 0;
-}
-
-static int vsoc_hwc_open(const struct hw_module_t* module, const char* name,
-                         struct hw_device_t** device) {
-  ALOGI("%s", __FUNCTION__);
-  if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
-    ALOGE("%s called with bad name %s", __FUNCTION__, name);
-    return -EINVAL;
-  }
-
-  vsoc_hwc_composer_device_1_t* dev = new vsoc_hwc_composer_device_1_t();
-  if (!dev) {
-    ALOGE("%s failed to allocate dev", __FUNCTION__);
-    return -ENOMEM;
-  }
-
-  struct timespec rt;
-  if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
-    ALOGE("%s:%d error in vsync thread clock_gettime: %s", __FILE__, __LINE__,
-          strerror(errno));
-  }
-  dev->vsync_data.vsync_base_timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
-
-  dev->base.common.tag = HARDWARE_DEVICE_TAG;
-  dev->base.common.version = VSOC_HWC_DEVICE_API_VERSION;
-  dev->base.common.module = const_cast<hw_module_t*>(module);
-  dev->base.common.close = vsoc_hwc_close;
-
-  dev->base.prepare = vsoc_hwc_prepare;
-  dev->base.set = vsoc_hwc_set;
-  dev->base.query = vsoc_hwc_query;
-  dev->base.registerProcs = vsoc_hwc_register_procs;
-  dev->base.dump = vsoc_hwc_dump;
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-  static hwc_methods_t hwc_methods = {vsoc_hwc_event_control};
-  dev->base.methods = &hwc_methods;
-#else
-  dev->base.blank = vsoc_hwc_blank;
-  dev->base.eventControl = vsoc_hwc_event_control;
-  dev->base.getDisplayConfigs = vsoc_hwc_get_display_configs;
-  dev->base.getDisplayAttributes = vsoc_hwc_get_display_attributes;
-#endif
-  dev->composer = new ComposerType(dev->vsync_data.vsync_base_timestamp);
-  dev->vsync_data.vsync_period_ns = 1000000000 / dev->composer->refresh_rate();
-  int ret = pthread_create(&dev->vsync_data.vsync_thread,
-                           NULL, cvd::hwc_vsync_thread, &dev->vsync_data);
-  if (ret) {
-    ALOGE("failed to start vsync thread: %s", strerror(ret));
-    ret = -ret;
-    delete dev;
-  } else {
-    *device = &dev->base.common;
-  }
-
-  return ret;
-}
-
-static struct hw_module_methods_t vsoc_hwc_module_methods = {
-    vsoc_hwc_open,
+static struct hw_module_methods_t hwc_module_methods = {
+    hwc_open,
 };
 
 hwc_module_t HAL_MODULE_INFO_SYM = {{HARDWARE_MODULE_TAG,
                                      HWC_MODULE_API_VERSION_0_1,
                                      HARDWARE_HAL_API_VERSION,
                                      HWC_HARDWARE_MODULE_ID,
-                                     "VSOC hwcomposer module",
+                                     "VSOCKET hwcomposer module",
                                      "Google",
-                                     &vsoc_hwc_module_methods,
+                                     &hwc_module_methods,
                                      NULL,
                                      {0}}};
diff --git a/guest/hals/hwcomposer/cutf_cvm/hwcomposer.h b/guest/hals/hwcomposer/cutf_cvm/hwcomposer.h
deleted file mode 100644
index a6b8121..0000000
--- a/guest/hals/hwcomposer/cutf_cvm/hwcomposer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <guest/libs/platform_support/api_level_fixes.h>
-
-#include <hardware/hwcomposer.h>
-#include <hardware/hwcomposer_defs.h>
-
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-typedef hwc_composer_device_t vsoc_hwc_device;
-typedef hwc_layer_t vsoc_hwc_layer;
-#define IS_TARGET_FRAMEBUFFER(x) false
-#define IS_PRIMARY_DISPLAY(x) true
-#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_3
-#else
-typedef hwc_composer_device_1_t vsoc_hwc_device;
-typedef hwc_layer_1_t vsoc_hwc_layer;
-#define IS_TARGET_FRAMEBUFFER(x) ((x) == HWC_FRAMEBUFFER_TARGET)
-#define IS_PRIMARY_DISPLAY(x) ((x) == HWC_DISPLAY_PRIMARY)
-#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_1_1
-#endif
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsoc_composer.h b/guest/hals/hwcomposer/cutf_cvm/vsoc_composer.h
deleted file mode 100644
index 7007931..0000000
--- a/guest/hals/hwcomposer/cutf_cvm/vsoc_composer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vector>
-
-#include <hardware/gralloc.h>
-
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
-
-#include "base_composer.h"
-#include "hwcomposer.h"
-
-namespace cvd {
-
-class VSoCComposer : public BaseComposer {
- public:
-  VSoCComposer(int64_t vsync_base_timestamp);
-  ~VSoCComposer();
-
-  // override
-  int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  // override
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
-
- protected:
-  static const int kNumTmpBufferPieces;
-  uint8_t* RotateTmpBuffer(unsigned int order);
-  uint8_t* GetSpecialTmpBuffer(size_t needed_size);
-  void CompositeLayer(vsoc_hwc_layer* src_layer, int32_t fb_offset);
-  std::vector<uint8_t> tmp_buffer_;
-  std::vector<uint8_t> special_tmp_buffer_;
-};
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp
new file mode 100644
index 0000000..2e2683f
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+#include "common/libs/device_config/device_config.h"
+
+namespace cvd {
+
+VsocketScreenView::VsocketScreenView()
+    : broadcast_thread_([this]() { BroadcastLoop(); }) {
+  GetScreenParameters();
+  // inner_buffer needs to be initialized after the final values of the screen
+  // parameters are set (either from the config server or default).
+  inner_buffer_ = std::vector<char>(buffer_size() * 8);
+}
+
+VsocketScreenView::~VsocketScreenView() {
+  running_ = false;
+  broadcast_thread_.join();
+}
+
+void VsocketScreenView::GetScreenParameters() {
+  auto device_config = cvd::DeviceConfig::Get();
+  if (!device_config) {
+    ALOGI(
+        "Failed to obtain device configuration from server, running in "
+        "headless mode");
+    // It is impossible to ensure host and guest agree on the screen parameters
+    // if these could not be read from the host configuration server. It's best
+    // to not attempt to send frames in this case.
+    running_ = false;
+    // Do a phony Broadcast to ensure the broadcaster thread exits.
+    Broadcast(-1);
+    return;
+  }
+  x_res_ = device_config->screen_x_res();
+  y_res_ = device_config->screen_y_res();
+  dpi_ = device_config->screen_dpi();
+  refresh_rate_ = device_config->screen_refresh_rate();
+}
+
+bool VsocketScreenView::ConnectToScreenServer() {
+  auto vsock_frames_port = property_get_int32("ro.boot.vsock_frames_port", -1);
+  if (vsock_frames_port <= 0) {
+    ALOGI("No screen server configured, operating on headless mode");
+    return false;
+  }
+
+  screen_server_ =
+      cvd::SharedFD::VsockClient(2, vsock_frames_port, SOCK_STREAM);
+  if (!screen_server_->IsOpen()) {
+    ALOGE("Unable to connect to screen server: %s", screen_server_->StrError());
+    return false;
+  }
+
+  return true;
+}
+
+void VsocketScreenView::BroadcastLoop() {
+  auto connected = ConnectToScreenServer();
+  if (!connected) {
+    ALOGE(
+        "Broadcaster thread exiting due to no connection to screen server. "
+        "Compositions will occur, but frames won't be sent anywhere");
+    return;
+  }
+  int current_seq = 0;
+  int current_offset;
+  ALOGI("Broadcaster thread loop starting");
+  while (true) {
+    {
+      std::unique_lock<std::mutex> lock(mutex_);
+      while (running_ && current_seq == current_seq_) {
+        cond_var_.wait(lock);
+      }
+      if (!running_) {
+        ALOGI("Broadcaster thread exiting");
+        return;
+      }
+      current_offset = current_offset_;
+      current_seq = current_seq_;
+    }
+    int32_t size = buffer_size();
+    screen_server_->Write(&size, sizeof(size));
+    auto buff = static_cast<char*>(GetBuffer(current_offset));
+    while (size > 0) {
+      auto written = screen_server_->Write(buff, size);
+      size -= written;
+      buff += written;
+    }
+  }
+}
+
+void VsocketScreenView::Broadcast(int offset, const CompositionStats*) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  current_offset_ = offset;
+  current_seq_++;
+  cond_var_.notify_all();
+}
+
+void* VsocketScreenView::GetBuffer(int buffer_id) {
+  return &inner_buffer_[buffer_size() * buffer_id];
+}
+
+int32_t VsocketScreenView::x_res() const { return x_res_; }
+int32_t VsocketScreenView::y_res() const { return y_res_; }
+int32_t VsocketScreenView::dpi() const { return dpi_; }
+int32_t VsocketScreenView::refresh_rate() const { return refresh_rate_; }
+
+int VsocketScreenView::num_buffers() const {
+  return inner_buffer_.size() / buffer_size();
+}
+
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h
new file mode 100644
index 0000000..0d6d90a
--- /dev/null
+++ b/guest/hals/hwcomposer/cutf_cvm/vsocket_screen_view.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "common/libs/fs/shared_fd.h"
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+namespace cvd {
+
+class VsocketScreenView : public ScreenView {
+ public:
+  VsocketScreenView();
+  virtual ~VsocketScreenView();
+
+  void Broadcast(int buffer_id,
+                 const CompositionStats* stats = nullptr) override;
+  void* GetBuffer(int fb_index) override;
+
+  int32_t x_res() const override;
+  int32_t y_res() const override;
+  int32_t dpi() const override;
+  int32_t refresh_rate() const override;
+
+  int num_buffers() const override;
+
+ private:
+  bool ConnectToScreenServer();
+  void GetScreenParameters();
+  void BroadcastLoop();
+
+  std::vector<char> inner_buffer_;
+  cvd::SharedFD screen_server_;
+  std::thread broadcast_thread_;
+  int current_offset_ = 0;
+  int current_seq_ = 0;
+  std::mutex mutex_;
+  std::condition_variable cond_var_;
+  bool running_ = true;
+  int32_t x_res_{720};
+  int32_t y_res_{1280};
+  int32_t dpi_{160};
+  int32_t refresh_rate_{60};
+};
+
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc-future/hwcomposer.cpp b/guest/hals/hwcomposer/vsoc-future/hwcomposer.cpp
index fdeef65..f18712c 100644
--- a/guest/hals/hwcomposer/vsoc-future/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/vsoc-future/hwcomposer.cpp
@@ -181,8 +181,7 @@
       const vsoc_buffer_handle_t* fb_handle =
           reinterpret_cast<const vsoc_buffer_handle_t*>(
               list->hwLayers[i].handle);
-      ScreenRegionView::GetInstance()->BroadcastNewFrame(
-          fb_handle->offset);
+      ScreenRegionView::GetInstance()->BroadcastNewFrame(fb_handle->offset);
       break;
     }
   }
@@ -273,7 +272,6 @@
 int hwc_getDisplayAttributes(struct hwc_composer_device_1* /*dev*/, int disp,
                              uint32_t /*config*/, const uint32_t* attributes,
                              int32_t* values) {
-
   if (disp != HWC_DISPLAY_PRIMARY) {
     ALOGE("Unknown display type %u", disp);
     return -EINVAL;
diff --git a/guest/hals/hwcomposer/vsoc/Android.bp b/guest/hals/hwcomposer/vsoc/Android.bp
new file mode 100644
index 0000000..559a1c1
--- /dev/null
+++ b/guest/hals/hwcomposer/vsoc/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+cc_library_shared {
+    name: "hwcomposer.cutf_ivsh_ashmem",
+    relative_install_path: "hw",
+    defaults: ["cuttlefish_guest_only"],
+    cflags: [
+        "-DGATHER_STATS",
+        // Uncomment the following line to revert to GL compositions
+        // "-DUSE_OLD_HWCOMPOSER",
+    ],
+    srcs: [
+        "vsoc_screen_view.cpp",
+        "hwcomposer.cpp",
+    ],
+    export_include_dirs: ["."],
+    static_libs: [
+        "libyuv_static", 
+        "hwcomposer_common"
+    ],
+    shared_libs: [
+        "cuttlefish_auto_resources",
+        "liblog",
+        "libhardware",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libsync",
+        "libjpeg",
+        "libcuttlefish_utils",
+        "libcuttlefish_fs",
+        "vsoc_lib",
+    ],
+}
diff --git a/guest/hals/hwcomposer/vsoc/Android.mk b/guest/hals/hwcomposer/vsoc/Android.mk
deleted file mode 100644
index b7cb911..0000000
--- a/guest/hals/hwcomposer/vsoc/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# HAL module implemenation stored in
-# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
-
-# Old hwcomposer, relies on GLES composition
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/hwcomposer.mk
-LOCAL_CFLAGS += -DUSE_OLD_HWCOMPOSER -Wall -Werror
-LOCAL_MODULE := hwcomposer.cutf_ivsh-deprecated
-
-# See b/67109557
-ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
-LOCAL_MULTILIB := first
-endif
-
-include $(BUILD_SHARED_LIBRARY)
-
-# New hwcomposer, performs software composition
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/hwcomposer.mk
-LOCAL_MODULE := hwcomposer.cutf_ivsh_ashmem
-LOCAL_VENDOR_MODULE := true
-
-# See b/67109557
-ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
-LOCAL_MULTILIB := first
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/guest/hals/hwcomposer/vsoc/base_composer.cpp b/guest/hals/hwcomposer/vsoc/base_composer.cpp
deleted file mode 100644
index 986d241..0000000
--- a/guest/hals/hwcomposer/vsoc/base_composer.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "base_composer.h"
-
-#include <string.h>
-
-#include <log/log.h>
-#include <hardware/gralloc.h>
-
-#include "common/vsoc/lib/screen_region_view.h"
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
-
-using vsoc::screen::ScreenRegionView;
-
-namespace cvd {
-
-namespace {
-
-void BroadcastFrameBufferChanged(int index) {
-  ScreenRegionView::GetInstance()->BroadcastNewFrame(
-      static_cast<uint32_t>(index));
-}
-
-}  // namespace
-
-BaseComposer::BaseComposer(int64_t vsync_base_timestamp,
-                           int32_t vsync_period_ns)
-    : vsync_base_timestamp_(vsync_base_timestamp),
-      vsync_period_ns_(vsync_period_ns),
-      fb_broadcaster_(BroadcastFrameBufferChanged) {
-  hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
-                reinterpret_cast<const hw_module_t**>(&gralloc_module_));
-}
-
-BaseComposer::~BaseComposer() {}
-
-FbBroadcaster BaseComposer::ReplaceFbBroadcaster(FbBroadcaster fb_broadcaster) {
-  FbBroadcaster tmp = fb_broadcaster_;
-  fb_broadcaster_ = fb_broadcaster;
-  return tmp;
-}
-
-void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
-
-void BaseComposer::Broadcast(int fb_index) {
-  fb_broadcaster_(fb_index);
-}
-
-int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
-  int fb_index = NextScreenBuffer();
-  if (fb_index < 0) {
-    ALOGE("Could not get the next buffer. Is the screen region large enough?");
-    return -1;
-  }
-  auto screen_view = ScreenRegionView::GetInstance();
-  void* frame_buffer = screen_view->GetBuffer(fb_index);
-  const private_handle_t* p_handle =
-      reinterpret_cast<const private_handle_t*>(buffer_handle);
-  void* buffer;
-  int retval = gralloc_module_->lock(gralloc_module_, buffer_handle,
-                                     GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
-                                     p_handle->x_res, p_handle->y_res, &buffer);
-  if (retval != 0) {
-    ALOGE("Got error code %d from lock function", retval);
-    return -1;
-  }
-  memcpy(frame_buffer, buffer, screen_view->buffer_size());
-  Broadcast(fb_index);
-  return 0;
-}  // namespace cvd
-
-int BaseComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  // find unsupported overlays
-  for (size_t i = 0; i < num_layers; i++) {
-    if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) {
-      continue;
-    }
-    layers[i].compositionType = HWC_FRAMEBUFFER;
-  }
-  return 0;
-}
-
-int BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  for (size_t idx = 0; idx < num_layers; idx++) {
-    if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
-      return PostFrameBufferTarget(layers[idx].handle);
-    }
-  }
-  return -1;
-}
-
-int BaseComposer::NextScreenBuffer() {
-  int num_buffers = ScreenRegionView::GetInstance()->number_of_buffers();
-  last_frame_buffer_ =
-      num_buffers > 0 ? (last_frame_buffer_ + 1) % num_buffers : -1;
-  return last_frame_buffer_;
-}
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/base_composer.h b/guest/hals/hwcomposer/vsoc/base_composer.h
deleted file mode 100644
index f3467ef..0000000
--- a/guest/hals/hwcomposer/vsoc/base_composer.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <functional>
-
-#include <hardware/gralloc.h>
-#include "hwcomposer.h"
-
-namespace cvd {
-
-using FbBroadcaster = std::function<void(int)>;
-
-class BaseComposer {
- public:
-  BaseComposer(int64_t vsync_base_timestamp, int32_t vsync_period_ns);
-  ~BaseComposer();
-
-  // Sets the composition type of each layer and returns the number of layers
-  // to be composited by the hwcomposer.
-  int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  // Returns 0 if successful.
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  // Changes the broadcaster, gives the ability to report more than just the
-  // offset by using a wrapper like the StatsKeepingComposer. Returns the old
-  // broadcaster. Passing a NULL pointer will cause the composer to not
-  // broadcast at all.
-  FbBroadcaster ReplaceFbBroadcaster(FbBroadcaster);
-  void Dump(char* buff, int buff_len);
-
- protected:
-  void Broadcast(int32_t offset);
-  int NextScreenBuffer();
-
-  const gralloc_module_t* gralloc_module_;
-  int64_t vsync_base_timestamp_;
-  int32_t vsync_period_ns_;
-  int last_frame_buffer_ = -1; // The first index will be 0
-
- private:
-  // Returns buffer offset or negative on error.
-  int PostFrameBufferTarget(buffer_handle_t handle);
-  FbBroadcaster fb_broadcaster_;
-};
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/geometry_utils.cpp b/guest/hals/hwcomposer/vsoc/geometry_utils.cpp
deleted file mode 100644
index 75b7a61..0000000
--- a/guest/hals/hwcomposer/vsoc/geometry_utils.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "geometry_utils.h"
-#include <algorithm>
-#include <utility>
-
-namespace cvd {
-
-bool LayersOverlap(const vsoc_hwc_layer& layer1, const vsoc_hwc_layer& layer2) {
-  int left1 = layer1.displayFrame.left;
-  int right1 = layer1.displayFrame.right;
-  int top1 = layer1.displayFrame.top;
-  int bottom1 = layer1.displayFrame.bottom;
-
-  int left2 = layer2.displayFrame.left;
-  int right2 = layer2.displayFrame.right;
-  int top2 = layer2.displayFrame.top;
-  int bottom2 = layer2.displayFrame.bottom;
-
-  bool overlap_x = left1 < right2 && left2 < right1;
-  bool overlap_y = top1 < bottom2 && top2 < bottom1;
-
-  return overlap_x && overlap_y;
-}
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/geometry_utils.h b/guest/hals/hwcomposer/vsoc/geometry_utils.h
deleted file mode 100644
index 937283f..0000000
--- a/guest/hals/hwcomposer/vsoc/geometry_utils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "hwcomposer.h"
-
-namespace cvd {
-
-bool LayersOverlap(const vsoc_hwc_layer& layer1, const vsoc_hwc_layer& layer2);
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/hwcomposer.cpp b/guest/hals/hwcomposer/vsoc/hwcomposer.cpp
index 2aaedd9..67713f2 100644
--- a/guest/hals/hwcomposer/vsoc/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/vsoc/hwcomposer.cpp
@@ -14,481 +14,39 @@
  * limitations under the License.
  */
 
-// Versions of hwcomposer we implement:
-// JB: 0.3
-// JB-MR1 to N : 1.1
-// N-MR1 to ... : We report 1.1 but SurfaceFlinger has the option to use an
-// adapter to treat our 1.1 hwcomposer as a 2.0. If SF stops using that adapter
-// to support 1.1 implementations it can be copied into cuttlefish from
-// frameworks/native/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.*
+#define LOG_TAG "hwc.cutf_cvm"
 
-#define LOG_TAG "hwc.cf_x86"
-
-#include <guest/libs/platform_support/api_level_fixes.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <math.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-
-#include <string>
-
-#define HWC_REMOVE_DEPRECATED_VERSIONS 1
-
-#include <cutils/compiler.h>
-#include <log/log.h>
 #include <cutils/properties.h>
-#include <hardware/gralloc.h>
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 #include <hardware/hwcomposer_defs.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
+#include <log/log.h>
 
-#include "common/vsoc/lib/screen_region_view.h"
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
 #include "guest/hals/hwcomposer/common/hwcomposer.h"
-#include <sync/sync.h>
 
-#include "base_composer.h"
-#include "geometry_utils.h"
-#include "hwcomposer.h"
-#include "stats_keeper.h"
-#include "vsoc_composer.h"
+#include "guest/hals/hwcomposer/vsoc/vsoc_screen_view.h"
 
-using vsoc::screen::ScreenRegionView;
-
-#ifdef USE_OLD_HWCOMPOSER
-typedef cvd::BaseComposer InnerComposerType;
-#else
-typedef cvd::VSoCComposer InnerComposerType;
-#endif
-
-#ifdef GATHER_STATS
-typedef cvd::StatsKeepingComposer<InnerComposerType> ComposerType;
-#else
-typedef InnerComposerType ComposerType;
-#endif
-
-struct vsoc_hwc_composer_device_1_t {
-  vsoc_hwc_device base;
-  cvd::hwc_composer_device_data_t vsync_data;
-  ComposerType* composer;
-};
-
-namespace {
-
-std::string CompositionString(int type) {
-  switch (type) {
-    case HWC_FRAMEBUFFER:
-      return "Framebuffer";
-    case HWC_OVERLAY:
-      return "Overlay";
-    case HWC_BACKGROUND:
-      return "Background";
-    case HWC_FRAMEBUFFER_TARGET:
-      return "FramebufferTarget";
-#if VSOC_PLATFORM_SDK_AFTER(K)
-    case HWC_SIDEBAND:
-      return "Sideband";
-    case HWC_CURSOR_OVERLAY:
-      return "CursorOverlay";
-#endif
-    default:
-      return std::string("Unknown (") + std::to_string(type) + ")";
-  }
-}
-
-void LogLayers(int num_layers, vsoc_hwc_layer* layers, int invalid) {
-  ALOGE("Layers:");
-  for (int idx = 0; idx < num_layers; ++idx) {
-    std::string log_line;
-    if (idx == invalid) {
-      log_line = "Invalid layer: ";
-    }
-    log_line +=
-        "Composition Type: " + CompositionString(layers[idx].compositionType);
-    ALOGE("%s", log_line.c_str());
-  }
-}
-
-// Ensures that the layer does not include any inconsistencies
-bool IsValidLayer(const vsoc_hwc_layer& layer) {
-  if (layer.flags & HWC_SKIP_LAYER) {
-    // A layer we are asked to skip validate should not be marked as skip
-    ALOGE("%s: Layer is marked as skip", __FUNCTION__);
-    return false;
-  }
-  // Check displayFrame
-  if (layer.displayFrame.left > layer.displayFrame.right ||
-      layer.displayFrame.top > layer.displayFrame.bottom) {
-    ALOGE(
-        "%s: Malformed rectangle (displayFrame): [left = %d, right = %d, top = "
-        "%d, bottom = %d]",
-        __FUNCTION__, layer.displayFrame.left, layer.displayFrame.right,
-        layer.displayFrame.top, layer.displayFrame.bottom);
-    return false;
-  }
-  // Validate the handle
-  if (private_handle_t::validate(layer.handle) != 0) {
-    ALOGE("%s: Layer contains an invalid gralloc handle.", __FUNCTION__);
-    return false;
-  }
-  const private_handle_t* p_handle =
-      reinterpret_cast<const private_handle_t*>(layer.handle);
-  // Check sourceCrop
-  if (layer.sourceCrop.left > layer.sourceCrop.right ||
-      layer.sourceCrop.top > layer.sourceCrop.bottom) {
-    ALOGE(
-        "%s: Malformed rectangle (sourceCrop): [left = %d, right = %d, top = "
-        "%d, bottom = %d]",
-        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
-        layer.sourceCrop.top, layer.sourceCrop.bottom);
-    return false;
-  }
-  if (layer.sourceCrop.left < 0 || layer.sourceCrop.top < 0 ||
-      layer.sourceCrop.right > p_handle->x_res ||
-      layer.sourceCrop.bottom > p_handle->y_res) {
-    ALOGE(
-        "%s: Invalid sourceCrop for buffer handle: sourceCrop = [left = %d, "
-        "right = %d, top = %d, bottom = %d], handle = [width = %d, height = "
-        "%d]",
-        __FUNCTION__, layer.sourceCrop.left, layer.sourceCrop.right,
-        layer.sourceCrop.top, layer.sourceCrop.bottom, p_handle->x_res,
-        p_handle->y_res);
-    return false;
-  }
-  return true;
-}
-
-bool IsValidComposition(int num_layers, vsoc_hwc_layer* layers, bool on_set) {
-  if (num_layers == 0) {
-    ALOGE("Composition requested with 0 layers");
-    return false;
-  }
-  // Sometimes the hwcomposer receives a prepare and set calls with no other
-  // layer than the FRAMEBUFFER_TARGET with a null handler. We treat this case
-  // independently as a valid composition, but issue a warning about it.
-  if (num_layers == 1 && layers[0].compositionType == HWC_FRAMEBUFFER_TARGET &&
-      layers[0].handle == NULL) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return true;
-  }
-  // The FRAMEBUFFER_TARGET layer needs to be sane only if
-  // there is at least one layer marked HWC_FRAMEBUFFER or if there is no layer
-  // marked HWC_OVERLAY (i.e some layers where composed with OpenGL, no layer
-  // marked overlay or framebuffer means that surfaceflinger decided to go for
-  // OpenGL without asking the hwcomposer first)
-  bool check_fb_target = true;
-  for (int idx = 0; idx < num_layers; ++idx) {
-    if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
-      // There is at least one, so it needs to be checked.
-      // It may have been set to false before, so ensure it's set to true.
-      check_fb_target = true;
-      break;
-    }
-    if (layers[idx].compositionType == HWC_OVERLAY) {
-      // At least one overlay, we may not need to.
-      check_fb_target = false;
-    }
-  }
-
-  for (int idx = 0; idx < num_layers; ++idx) {
-    switch (layers[idx].compositionType) {
-    case HWC_FRAMEBUFFER_TARGET:
-      // In the call to prepare() the framebuffer target does not have a valid
-      // buffer_handle, so we don't validate it yet.
-      if (on_set && check_fb_target && !IsValidLayer(layers[idx])) {
-        ALOGE("%s: Invalid layer found", __FUNCTION__);
-        LogLayers(num_layers, layers, idx);
-        return false;
-      }
-      break;
-    case HWC_OVERLAY:
-      if (!(layers[idx].flags & HWC_SKIP_LAYER) &&
-          !IsValidLayer(layers[idx])) {
-        ALOGE("%s: Invalid layer found", __FUNCTION__);
-        LogLayers(num_layers, layers, idx);
-        return false;
-      }
-      break;
-    }
-  }
-  return true;
-}
-
-}
-
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-static int vsoc_hwc_prepare(vsoc_hwc_device* dev, hwc_layer_list_t* list) {
-#else
-static int vsoc_hwc_prepare(vsoc_hwc_device* dev, size_t numDisplays,
-                            hwc_display_contents_1_t** displays) {
-  if (!numDisplays || !displays) return 0;
-
-  hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY];
-
-  if (!list) return 0;
-#endif
-  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], false)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
+static int hwc_open(const struct hw_module_t* module, const char* name,
+                    struct hw_device_t** device) {
+  std::unique_ptr<cvd::ScreenView> screen_view(new cvd::VSoCScreenView());
+  if (!screen_view) {
+    ALOGE("Failed to instantiate screen view");
     return -1;
   }
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->PrepareLayers(
-      list->numHwLayers, &list->hwLayers[0]);
-  return 0;
+
+  return cvd::cvd_hwc_open(std::move(screen_view), module, name, device);
 }
 
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-int vsoc_hwc_set(struct hwc_composer_device* dev, hwc_display_t dpy,
-                 hwc_surface_t sur, hwc_layer_list_t* list) {
-  if (list->numHwLayers == 1 &&
-      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return 0;
-  }
-  if (!IsValidComposition(list->numHwLayers, &list->hwLayers[0], true)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
-    return -1;
-  }
-  return reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)
-      ->composer->SetLayers(list->numHwLayers, &list->hwLayers[0]);
-}
-#else
-static int vsoc_hwc_set(vsoc_hwc_device* dev, size_t numDisplays,
-                        hwc_display_contents_1_t** displays) {
-  if (!numDisplays || !displays) return 0;
-
-  hwc_display_contents_1_t* contents = displays[HWC_DISPLAY_PRIMARY];
-  if (!contents) return 0;
-
-  vsoc_hwc_layer* layers = &contents->hwLayers[0];
-  if (contents->numHwLayers == 1 &&
-      layers[0].compositionType == HWC_FRAMEBUFFER_TARGET) {
-    ALOGW("Received request for empty composition, treating as valid noop");
-    return 0;
-  }
-  if (!IsValidComposition(contents->numHwLayers, layers, true)) {
-    LOG_ALWAYS_FATAL("%s: Invalid composition requested", __FUNCTION__);
-    return -1;
-  }
-  int retval =
-      reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
-          contents->numHwLayers, layers);
-
-  int closedFds = 0;
-  for (size_t index = 0; index < contents->numHwLayers; ++index) {
-    if (layers[index].acquireFenceFd != -1) {
-      close(layers[index].acquireFenceFd);
-      layers[index].acquireFenceFd = -1;
-      ++closedFds;
-    }
-  }
-  if (closedFds) {
-    ALOGI("Saw %zu layers, closed=%d", contents->numHwLayers, closedFds);
-  }
-
-  // TODO(ghartman): This should be set before returning. On the next set it
-  // should be signalled when we load the new frame.
-  contents->retireFenceFd = -1;
-  return retval;
-}
-#endif
-
-static void vsoc_hwc_register_procs(vsoc_hwc_device* dev,
-                                    const hwc_procs_t* procs) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-  pdev->vsync_data.procs = procs;
-}
-
-static int vsoc_hwc_query(vsoc_hwc_device* dev, int what, int* value) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-
-  switch (what) {
-    case HWC_BACKGROUND_LAYER_SUPPORTED:
-      // we support the background layer
-      value[0] = 0;
-      break;
-    case HWC_VSYNC_PERIOD:
-      value[0] = pdev->vsync_data.vsync_period_ns;
-      break;
-    default:
-      // unsupported query
-      ALOGE("%s badness unsupported query what=%d", __FUNCTION__, what);
-      return -EINVAL;
-  }
-  return 0;
-}
-
-static int vsoc_hwc_event_control(
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-    vsoc_hwc_device* /*dev*/, int event, int /*enabled*/) {
-#else
-    vsoc_hwc_device* /*dev*/, int /*dpy*/, int event, int /*enabled*/) {
-#endif
-
-  if (event == HWC_EVENT_VSYNC) {
-    return 0;
-  }
-  return -EINVAL;
-}
-
-static int vsoc_hwc_blank(vsoc_hwc_device* /*dev*/, int disp, int /*blank*/) {
-  if (!IS_PRIMARY_DISPLAY(disp)) return -EINVAL;
-  return 0;
-}
-
-static void vsoc_hwc_dump(vsoc_hwc_device* dev, char* buff, int buff_len) {
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->Dump(
-      buff, buff_len);
-}
-
-static int vsoc_hwc_get_display_configs(vsoc_hwc_device* /*dev*/, int disp,
-                                        uint32_t* configs, size_t* numConfigs) {
-  if (*numConfigs == 0) return 0;
-
-  if (IS_PRIMARY_DISPLAY(disp)) {
-    configs[0] = 0;
-    *numConfigs = 1;
-    return 0;
-  }
-
-  return -EINVAL;
-}
-
-#if VSOC_PLATFORM_SDK_AFTER(J)
-static int32_t vsoc_hwc_attribute(struct vsoc_hwc_composer_device_1_t* pdev,
-                                  const uint32_t attribute) {
-  auto screen_view = ScreenRegionView::GetInstance();
-  switch (attribute) {
-    case HWC_DISPLAY_VSYNC_PERIOD:
-      return pdev->vsync_data.vsync_period_ns;
-    case HWC_DISPLAY_WIDTH:
-      return screen_view->x_res();
-    case HWC_DISPLAY_HEIGHT:
-      return screen_view->y_res();
-    case HWC_DISPLAY_DPI_X:
-      ALOGI("Reporting DPI_X of %d", screen_view->dpi());
-      // The number of pixels per thousand inches
-      return screen_view->dpi() * 1000;
-    case HWC_DISPLAY_DPI_Y:
-      ALOGI("Reporting DPI_Y of %d", screen_view->dpi());
-      // The number of pixels per thousand inches
-      return screen_view->dpi() * 1000;
-    default:
-      ALOGE("unknown display attribute %u", attribute);
-      return -EINVAL;
-  }
-}
-
-static int vsoc_hwc_get_display_attributes(vsoc_hwc_device* dev, int disp,
-                                           uint32_t config __unused,
-                                           const uint32_t* attributes,
-                                           int32_t* values) {
-  struct vsoc_hwc_composer_device_1_t* pdev =
-      (struct vsoc_hwc_composer_device_1_t*)dev;
-
-  if (!IS_PRIMARY_DISPLAY(disp)) {
-    ALOGE("unknown display type %u", disp);
-    return -EINVAL;
-  }
-
-  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
-    values[i] = vsoc_hwc_attribute(pdev, attributes[i]);
-  }
-
-  return 0;
-}
-#endif
-
-static int vsoc_hwc_close(hw_device_t* device) {
-  struct vsoc_hwc_composer_device_1_t* dev =
-      (struct vsoc_hwc_composer_device_1_t*)device;
-  ALOGE("vsoc_hwc_close");
-  pthread_kill(dev->vsync_data.vsync_thread, SIGTERM);
-  pthread_join(dev->vsync_data.vsync_thread, NULL);
-  delete dev->composer;
-  delete dev;
-  return 0;
-}
-
-static int vsoc_hwc_open(const struct hw_module_t* module, const char* name,
-                         struct hw_device_t** device) {
-  ALOGI("%s", __FUNCTION__);
-  if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
-    ALOGE("%s called with bad name %s", __FUNCTION__, name);
-    return -EINVAL;
-  }
-
-  vsoc_hwc_composer_device_1_t* dev = new vsoc_hwc_composer_device_1_t();
-  if (!dev) {
-    ALOGE("%s failed to allocate dev", __FUNCTION__);
-    return -ENOMEM;
-  }
-
-  int refreshRate = ScreenRegionView::GetInstance()->refresh_rate_hz();
-  dev->vsync_data.vsync_period_ns = 1000000000 / refreshRate;
-  struct timespec rt;
-  if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
-    LOG_ALWAYS_FATAL("%s:%d error in vsync thread clock_gettime: %s", __FILE__,
-      __LINE__, strerror(errno));
-  }
-  dev->vsync_data.vsync_base_timestamp = int64_t(rt.tv_sec) * 1e9 + rt.tv_nsec;
-
-  dev->base.common.tag = HARDWARE_DEVICE_TAG;
-  dev->base.common.version = VSOC_HWC_DEVICE_API_VERSION;
-  dev->base.common.module = const_cast<hw_module_t*>(module);
-  dev->base.common.close = vsoc_hwc_close;
-
-  dev->base.prepare = vsoc_hwc_prepare;
-  dev->base.set = vsoc_hwc_set;
-  dev->base.query = vsoc_hwc_query;
-  dev->base.registerProcs = vsoc_hwc_register_procs;
-  dev->base.dump = vsoc_hwc_dump;
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-  static hwc_methods_t hwc_methods = {vsoc_hwc_event_control};
-  dev->base.methods = &hwc_methods;
-#else
-  dev->base.blank = vsoc_hwc_blank;
-  dev->base.eventControl = vsoc_hwc_event_control;
-  dev->base.getDisplayConfigs = vsoc_hwc_get_display_configs;
-  dev->base.getDisplayAttributes = vsoc_hwc_get_display_attributes;
-#endif
-  dev->composer =
-      new ComposerType(dev->vsync_data.vsync_base_timestamp, dev->vsync_data.vsync_period_ns);
-
-  int ret = pthread_create(&dev->vsync_data.vsync_thread, NULL, cvd::hwc_vsync_thread, &dev->vsync_data);
-  if (ret) {
-    ALOGE("failed to start vsync thread: %s", strerror(ret));
-    ret = -ret;
-    delete dev;
-  } else {
-    *device = &dev->base.common;
-  }
-
-  return ret;
-}
-
-static struct hw_module_methods_t vsoc_hwc_module_methods = {
-    vsoc_hwc_open,
+static struct hw_module_methods_t hwc_module_methods = {
+    hwc_open,
 };
 
 hwc_module_t HAL_MODULE_INFO_SYM = {{HARDWARE_MODULE_TAG,
                                      HWC_MODULE_API_VERSION_0_1,
                                      HARDWARE_HAL_API_VERSION,
                                      HWC_HARDWARE_MODULE_ID,
-                                     "VSOC hwcomposer module",
+                                     "VSoC hwcomposer module",
                                      "Google",
-                                     &vsoc_hwc_module_methods,
+                                     &hwc_module_methods,
                                      NULL,
                                      {0}}};
diff --git a/guest/hals/hwcomposer/vsoc/hwcomposer.h b/guest/hals/hwcomposer/vsoc/hwcomposer.h
deleted file mode 100644
index a6b8121..0000000
--- a/guest/hals/hwcomposer/vsoc/hwcomposer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <guest/libs/platform_support/api_level_fixes.h>
-
-#include <hardware/hwcomposer.h>
-#include <hardware/hwcomposer_defs.h>
-
-#if VSOC_PLATFORM_SDK_BEFORE(J_MR1)
-typedef hwc_composer_device_t vsoc_hwc_device;
-typedef hwc_layer_t vsoc_hwc_layer;
-#define IS_TARGET_FRAMEBUFFER(x) false
-#define IS_PRIMARY_DISPLAY(x) true
-#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_3
-#else
-typedef hwc_composer_device_1_t vsoc_hwc_device;
-typedef hwc_layer_1_t vsoc_hwc_layer;
-#define IS_TARGET_FRAMEBUFFER(x) ((x) == HWC_FRAMEBUFFER_TARGET)
-#define IS_PRIMARY_DISPLAY(x) ((x) == HWC_DISPLAY_PRIMARY)
-#define VSOC_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_1_1
-#endif
diff --git a/guest/hals/hwcomposer/vsoc/hwcomposer.mk b/guest/hals/hwcomposer/vsoc/hwcomposer.mk
deleted file mode 100644
index cb27c95..0000000
--- a/guest/hals/hwcomposer/vsoc/hwcomposer.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -ge 21; echo $$?))
-LOCAL_MODULE_RELATIVE_PATH := hw
-else
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-endif
-LOCAL_MULTILIB := first
-LOCAL_MODULE_TAGS := optional
-LOCAL_VENDOR_MODULE := true
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    liblog \
-    libcutils \
-    libutils \
-    libsync \
-    libhardware \
-    libjpeg \
-    vsoc_lib \
-    $(VSOC_STLPORT_LIBS)
-
-LOCAL_STATIC_LIBRARIES := \
-    libyuv_static \
-    hwcomposer_common \
-
-LOCAL_SRC_FILES := \
-    geometry_utils.cpp \
-    hwcomposer.cpp \
-    vsoc_composer.cpp \
-    stats_keeper.cpp \
-    base_composer.cpp \
-
-LOCAL_CFLAGS += \
-    -DGATHER_STATS \
-    $(VSOC_VERSION_CFLAGS) \
-    -Wall -Werror
-
-LOCAL_C_INCLUDES := \
-    device/google/cuttlefish_common \
-    device/google/cuttlefish_kernel \
-    external/libyuv/files/include \
-    bionic \
-    $(VSOC_STLPORT_INCLUDES)
diff --git a/guest/hals/hwcomposer/vsoc/vsoc_composer.cpp b/guest/hals/hwcomposer/vsoc/vsoc_composer.cpp
deleted file mode 100644
index d77c004..0000000
--- a/guest/hals/hwcomposer/vsoc/vsoc_composer.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "vsoc_composer.h"
-
-#include <algorithm>
-#include <cstdlib>
-#include <utility>
-#include <vector>
-
-#include <log/log.h>
-#include <hardware/hwcomposer.h>
-#include <hardware/hwcomposer_defs.h>
-#include <libyuv.h>
-#include <system/graphics.h>
-
-#include "common/vsoc/lib/screen_region_view.h"
-
-#include "geometry_utils.h"
-
-using vsoc::screen::ScreenRegionView;
-
-namespace cvd {
-
-namespace {
-
-bool LayerNeedsScaling(const vsoc_hwc_layer& layer) {
-  int from_w = layer.sourceCrop.right - layer.sourceCrop.left;
-  int from_h = layer.sourceCrop.bottom - layer.sourceCrop.top;
-  int to_w = layer.displayFrame.right - layer.displayFrame.left;
-  int to_h = layer.displayFrame.bottom - layer.displayFrame.top;
-
-  bool not_rot_scale = from_w != to_w || from_h != to_h;
-  bool rot_scale = from_w != to_h || from_h != to_w;
-
-  bool needs_rot = layer.transform & HAL_TRANSFORM_ROT_90;
-
-  return needs_rot ? rot_scale : not_rot_scale;
-}
-
-bool LayerNeedsBlending(const vsoc_hwc_layer& layer) {
-  return layer.blending != HWC_BLENDING_NONE;
-}
-
-bool LayerNeedsAttenuation(const vsoc_hwc_layer& layer) {
-  return layer.blending == HWC_BLENDING_COVERAGE;
-}
-
-struct BufferSpec;
-typedef int (*ConverterFunction)(const BufferSpec& src, const BufferSpec& dst,
-                                 bool v_flip);
-int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
-int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip);
-ConverterFunction GetConverter(uint32_t format) {
-  switch (format) {
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-    case HAL_PIXEL_FORMAT_RGBX_8888:
-    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-      return &DoCopy;
-
-    case HAL_PIXEL_FORMAT_YV12:
-      return &ConvertFromYV12;
-
-    // Unsupported formats
-    // TODO(jemoreira): Conversion from these formats should be implemented as
-    // we find evidence of its usage.
-    // case HAL_PIXEL_FORMAT_BGRA_8888:
-
-    // case HAL_PIXEL_FORMAT_RGB_888:
-    // case HAL_PIXEL_FORMAT_RGB_565:
-
-    // case HAL_PIXEL_FORMAT_sRGB_A_8888:
-    // case HAL_PIXEL_FORMAT_sRGB_X_8888:
-
-    // case HAL_PIXEL_FORMAT_Y8:
-    // case HAL_PIXEL_FORMAT_Y16:
-
-    // case HAL_PIXEL_FORMAT_RAW_SENSOR:
-    // case HAL_PIXEL_FORMAT_BLOB:
-
-    // case HAL_PIXEL_FORMAT_YCbCr_420_888:
-    // case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-    // case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-    // case HAL_PIXEL_FORMAT_YCbCr_422_I:
-    default:
-      ALOGW("Unsupported format: 0x%04x, returning null converter function",
-            format);
-  }
-  return NULL;
-}
-
-// Whether we support a given format
-bool IsFormatSupported(uint32_t format) { return GetConverter(format) != NULL; }
-
-bool CanCompositeLayer(const vsoc_hwc_layer& layer) {
-  if (layer.handle == NULL) {
-    ALOGW("%s received a layer with a null handler", __FUNCTION__);
-    return false;
-  }
-  int format = reinterpret_cast<const private_handle_t*>(layer.handle)->format;
-  if (!IsFormatSupported(format)) {
-    ALOGD("Unsupported pixel format: 0x%x, doing software composition instead",
-          format);
-    return false;
-  }
-  return true;
-}
-
-/*******************************************************************************
-Libyuv's convert functions only allow the combination of any rotation (multiple
-of 90 degrees) and a vertical flip, but not horizontal flips.
-Surfaceflinger's transformations are expressed in terms of a vertical flip, a
-horizontal flip and/or a single 90 degrees clockwise rotation (see
-NATIVE_WINDOW_TRANSFORM_HINT documentation on system/window.h for more insight).
-The following code allows to turn a horizontal flip into a 180 degrees rotation
-and a vertical flip.
-*******************************************************************************/
-libyuv::RotationMode GetRotationFromTransform(uint32_t transform) {
-  uint32_t rotation =
-      (transform & HAL_TRANSFORM_ROT_90) ? 1 : 0;          // 1 * ROT90 bit
-  rotation += (transform & HAL_TRANSFORM_FLIP_H) ? 2 : 0;  // 2 * VFLIP bit
-  return static_cast<libyuv::RotationMode>(90 * rotation);
-}
-
-bool GetVFlipFromTransform(uint32_t transform) {
-  // vertical flip xor horizontal flip
-  return ((transform & HAL_TRANSFORM_FLIP_V) >> 1) ^
-         (transform & HAL_TRANSFORM_FLIP_H);
-}
-
-struct BufferSpec {
-  uint8_t* buffer;
-  size_t size;
-  int width;
-  int height;
-  int stride;
-  int crop_x;
-  int crop_y;
-  int crop_width;
-  int crop_height;
-  uint32_t format;
-
-  BufferSpec(uint8_t* buffer, size_t size, int width, int height, int stride)
-      : buffer(buffer),
-        size(size),
-        width(width),
-        height(height),
-        stride(stride),
-        crop_x(0),
-        crop_y(0),
-        crop_width(width),
-        crop_height(height),
-        format(HAL_PIXEL_FORMAT_RGBA_8888) {}
-};
-
-int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
-  // use the stride in pixels as the source width
-  int stride_in_pixels = src.stride / formatToBytesPerPixel(src.format);
-
-  // The following calculation of plane offsets and alignments are based on
-  // swiftshader's Sampler::setTextureLevel() implementation
-  // (Renderer/Sampler.cpp:225)
-  uint8_t* src_y = src.buffer;
-  int stride_y = stride_in_pixels;
-  uint8_t* src_v = src_y + stride_y * src.height;
-  int stride_v = ScreenRegionView::align(stride_y / 2);
-  uint8_t* src_u = src_v + stride_v *  src.height / 2;
-  int stride_u = ScreenRegionView::align(stride_y / 2);
-
-  // Adjust for crop
-  src_y += src.crop_y * stride_y + src.crop_x;
-  src_v += (src.crop_y / 2) * stride_v + (src.crop_x / 2);
-  src_u += (src.crop_y / 2) * stride_u + (src.crop_x / 2);
-  uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride +
-                        dst.crop_x * formatToBytesPerPixel(dst.format);
-
-  // YV12 is the same as I420, with the U and V planes swapped
-  return libyuv::I420ToARGB(src_y, stride_y, src_v, stride_v, src_u, stride_u,
-                            dst_buffer, dst.stride, dst.crop_width,
-                            v_flip ? -dst.crop_height : dst.crop_height);
-}
-
-int DoConversion(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
-  return (*GetConverter(src.format))(src, dst, v_flip);
-}
-
-int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
-  // Point to the upper left corner of the crop rectangle
-  uint8_t* src_buffer = src.buffer + src.crop_y * src.stride +
-                        src.crop_x * formatToBytesPerPixel(src.format);
-  uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride +
-                        dst.crop_x * formatToBytesPerPixel(dst.format);
-  int width = src.crop_width;
-  int height = src.crop_height;
-
-  if (v_flip) {
-    height = -height;
-  }
-
-  // HAL formats are named based on the order of the pixel componets on the
-  // byte stream, while libyuv formats are named based on the order of those
-  // pixel components in an integer written from left to right. So
-  // libyuv::FOURCC_ARGB is equivalent to HAL_PIXEL_FORMAT_BGRA_8888.
-  return libyuv::ARGBCopy(src_buffer, src.stride, dst_buffer, dst.stride, width,
-                          height);
-}
-
-int DoRotation(const BufferSpec& src, const BufferSpec& dst,
-               libyuv::RotationMode rotation, bool v_flip) {
-  // Point to the upper left corner of the crop rectangles
-  uint8_t* src_buffer = src.buffer + src.crop_y * src.stride +
-                        src.crop_x * formatToBytesPerPixel(src.format);
-  uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride +
-                        dst.crop_x * formatToBytesPerPixel(dst.format);
-  int width = src.crop_width;
-  int height = src.crop_height;
-
-  if (v_flip) {
-    height = -height;
-  }
-
-  return libyuv::ARGBRotate(src_buffer, src.stride, dst_buffer, dst.stride,
-                            width, height, rotation);
-}
-
-int DoScaling(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
-  // Point to the upper left corner of the crop rectangles
-  uint8_t* src_buffer = src.buffer + src.crop_y * src.stride +
-                        src.crop_x * formatToBytesPerPixel(src.format);
-  uint8_t* dst_buffer = dst.buffer + dst.crop_y * dst.stride +
-                        dst.crop_x * formatToBytesPerPixel(dst.format);
-  int src_width = src.crop_width;
-  int src_height = src.crop_height;
-  int dst_width = dst.crop_width;
-  int dst_height = dst.crop_height;
-
-  if (v_flip) {
-    src_height = -src_height;
-  }
-
-  return libyuv::ARGBScale(src_buffer, src.stride, src_width, src_height,
-                           dst_buffer, dst.stride, dst_width, dst_height,
-                           libyuv::kFilterBilinear);
-}
-
-int DoAttenuation(const BufferSpec& src, const BufferSpec& dest, bool v_flip) {
-  // Point to the upper left corner of the crop rectangles
-  uint8_t* src_buffer = src.buffer + src.crop_y * src.stride +
-                        src.crop_x * formatToBytesPerPixel(src.format);
-  uint8_t* dst_buffer = dest.buffer + dest.crop_y * dest.stride +
-                        dest.crop_x * formatToBytesPerPixel(dest.format);
-  int width = dest.crop_width;
-  int height = dest.crop_height;
-
-  if (v_flip) {
-    height = -height;
-  }
-
-  return libyuv::ARGBAttenuate(src_buffer, src.stride, dst_buffer, dest.stride,
-                               width, height);
-}
-
-int DoBlending(const BufferSpec& src, const BufferSpec& dest, bool v_flip) {
-  // Point to the upper left corner of the crop rectangles
-  uint8_t* src_buffer = src.buffer + src.crop_y * src.stride +
-                        src.crop_x * formatToBytesPerPixel(src.format);
-  uint8_t* dst_buffer = dest.buffer + dest.crop_y * dest.stride +
-                        dest.crop_x * formatToBytesPerPixel(dest.format);
-  int width = dest.crop_width;
-  int height = dest.crop_height;
-
-  if (v_flip) {
-    height = -height;
-  }
-
-  // libyuv's ARGB format is hwcomposer's BGRA format, since blending only cares
-  // for the position of alpha in the pixel and not the position of the colors
-  // this function is perfectly usable.
-  return libyuv::ARGBBlend(src_buffer, src.stride, dst_buffer, dest.stride,
-                           dst_buffer, dest.stride, width, height);
-}
-
-}  // namespace
-
-void VSoCComposer::CompositeLayer(vsoc_hwc_layer* src_layer,
-                                  int buffer_idx) {
-  libyuv::RotationMode rotation =
-      GetRotationFromTransform(src_layer->transform);
-
-  const private_handle_t* src_priv_handle =
-      reinterpret_cast<const private_handle_t*>(src_layer->handle);
-
-  // TODO(jemoreira): Remove the hardcoded fomat.
-  bool needs_conversion = src_priv_handle->format != HAL_PIXEL_FORMAT_RGBX_8888;
-  bool needs_scaling = LayerNeedsScaling(*src_layer);
-  bool needs_rotation = rotation != libyuv::kRotate0;
-  bool needs_transpose = needs_rotation && rotation != libyuv::kRotate180;
-  bool needs_vflip = GetVFlipFromTransform(src_layer->transform);
-  bool needs_attenuation = LayerNeedsAttenuation(*src_layer);
-  bool needs_blending = LayerNeedsBlending(*src_layer);
-  bool needs_copy = !(needs_conversion || needs_scaling || needs_rotation ||
-                      needs_vflip || needs_attenuation || needs_blending);
-
-  uint8_t* src_buffer;
-  uint8_t* dst_buffer = reinterpret_cast<uint8_t*>(
-      ScreenRegionView::GetInstance()->GetBuffer(buffer_idx));
-  int retval = gralloc_module_->lock(
-      gralloc_module_, src_layer->handle, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
-      src_priv_handle->x_res, src_priv_handle->y_res,
-      reinterpret_cast<void**>(&src_buffer));
-  if (retval) {
-    ALOGE("Got error code %d from lock function", retval);
-    return;
-  }
-  if (retval) {
-    ALOGE("Got error code %d from lock function", retval);
-    // TODO(jemoreira): Use a lock_guard-like object.
-    gralloc_module_->unlock(gralloc_module_, src_priv_handle);
-    return;
-  }
-
-  BufferSpec src_layer_spec(src_buffer, src_priv_handle->total_size,
-                            src_priv_handle->x_res, src_priv_handle->y_res,
-                            src_priv_handle->stride_in_pixels *
-                                formatToBytesPerPixel(src_priv_handle->format));
-  src_layer_spec.crop_x = src_layer->sourceCrop.left;
-  src_layer_spec.crop_y = src_layer->sourceCrop.top;
-  src_layer_spec.crop_width =
-      src_layer->sourceCrop.right - src_layer->sourceCrop.left;
-  src_layer_spec.crop_height =
-      src_layer->sourceCrop.bottom - src_layer->sourceCrop.top;
-  src_layer_spec.format = src_priv_handle->format;
-
-  auto screen_view = ScreenRegionView::GetInstance();
-  BufferSpec dst_layer_spec(dst_buffer, screen_view->buffer_size(),
-                            screen_view->x_res(), screen_view->y_res(),
-                            screen_view->line_length());
-  dst_layer_spec.crop_x = src_layer->displayFrame.left;
-  dst_layer_spec.crop_y = src_layer->displayFrame.top;
-  dst_layer_spec.crop_width =
-      src_layer->displayFrame.right - src_layer->displayFrame.left;
-  dst_layer_spec.crop_height =
-      src_layer->displayFrame.bottom - src_layer->displayFrame.top;
-  // TODO(jemoreira): Remove the hardcoded fomat.
-  dst_layer_spec.format = HAL_PIXEL_FORMAT_RGBX_8888;
-
-  // Add the destination layer to the bottom of the buffer stack
-  std::vector<BufferSpec> dest_buffer_stack(1, dst_layer_spec);
-
-  // If more than operation is to be performed, a temporary buffer is needed for
-  // each additional operation
-
-  // N operations need N destination buffers, the destination layer (the
-  // framebuffer) is one of them, so only N-1 temporary buffers are needed.
-  // Vertical flip is not taken into account because it can be done together
-  // with any other operation.
-  int needed_tmp_buffers = (needs_conversion ? 1 : 0) +
-                           (needs_scaling ? 1 : 0) + (needs_rotation ? 1 : 0) +
-                           (needs_attenuation ? 1 : 0) +
-                           (needs_blending ? 1 : 0) + (needs_copy ? 1 : 0) - 1;
-
-  int x_res = src_layer->displayFrame.right - src_layer->displayFrame.left;
-  int y_res = src_layer->displayFrame.bottom - src_layer->displayFrame.top;
-  size_t output_frame_size =
-      x_res *
-    ScreenRegionView::align(y_res * screen_view->bytes_per_pixel());
-  while (needed_tmp_buffers > 0) {
-    BufferSpec tmp(RotateTmpBuffer(needed_tmp_buffers), output_frame_size,
-                   x_res, y_res,
-                   ScreenRegionView::align(
-                       x_res * screen_view->bytes_per_pixel()));
-    dest_buffer_stack.push_back(tmp);
-    needed_tmp_buffers--;
-  }
-
-  // Conversion and scaling should always be the first operations, so that every
-  // other operation works on equally sized frames (garanteed to fit in the tmp
-  // buffers)
-
-  // TODO(jemoreira): We are converting to ARGB as the first step under the
-  // assumption that scaling ARGB is faster than scaling I420 (the most common).
-  // This should be confirmed with testing.
-  if (needs_conversion) {
-    BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
-    if (needs_scaling || needs_transpose) {
-      // If a rotation or a scaling operation are needed the dimensions at the
-      // top of the buffer stack are wrong (wrong sizes for scaling, swapped
-      // width and height for 90 and 270 rotations).
-      // Make width and height match the crop sizes on the source
-      int src_width = src_layer_spec.crop_width;
-      int src_height = src_layer_spec.crop_height;
-      int dst_stride = ScreenRegionView::align(
-          src_width * screen_view->bytes_per_pixel());
-      size_t needed_size = dst_stride * src_height;
-      dst_buffer_spec.width = src_width;
-      dst_buffer_spec.height = src_height;
-      // Ajust the stride accordingly
-      dst_buffer_spec.stride = dst_stride;
-      // Crop sizes also need to be adjusted
-      dst_buffer_spec.crop_width = src_width;
-      dst_buffer_spec.crop_height = src_height;
-      dst_buffer_spec.size = needed_size;
-      // crop_x and y are fine at 0, format is already set to match destination
-
-      // In case of a scale, the source frame may be bigger than the default tmp
-      // buffer size
-      if (needed_size > tmp_buffer_.size() / kNumTmpBufferPieces) {
-        dst_buffer_spec.buffer = GetSpecialTmpBuffer(needed_size);
-      }
-    }
-    retval = DoConversion(src_layer_spec, dst_buffer_spec, needs_vflip);
-    if (retval) {
-      ALOGE("Got error code %d from DoConversion function", retval);
-    }
-    needs_vflip = false;
-    src_layer_spec = dst_buffer_spec;
-    dest_buffer_stack.pop_back();
-  }
-
-  if (needs_scaling) {
-    BufferSpec& dst_buffer_spec = dest_buffer_stack.back();
-    if (needs_transpose) {
-      // If a rotation is needed, the temporary buffer has the correct size but
-      // needs to be transposed and have its stride updated accordingly. The
-      // crop sizes also needs to be transposed, but not the x and y since they
-      // are both zero in a temporary buffer (and it is a temporary buffer
-      // because a rotation will be performed next).
-      std::swap(dst_buffer_spec.width, dst_buffer_spec.height);
-      std::swap(dst_buffer_spec.crop_width, dst_buffer_spec.crop_height);
-      // TODO (jemoreira): Aligment (To align here may cause the needed size to
-      // be bigger than the buffer, so care should be taken)
-      dst_buffer_spec.stride =
-          dst_buffer_spec.width * screen_view->bytes_per_pixel();
-    }
-    retval = DoScaling(src_layer_spec, dst_buffer_spec, needs_vflip);
-    needs_vflip = false;
-    if (retval) {
-      ALOGE("Got error code %d from DoScaling function", retval);
-    }
-    src_layer_spec = dst_buffer_spec;
-    dest_buffer_stack.pop_back();
-  }
-
-  if (needs_rotation) {
-    retval = DoRotation(src_layer_spec, dest_buffer_stack.back(), rotation,
-                        needs_vflip);
-    needs_vflip = false;
-    if (retval) {
-      ALOGE("Got error code %d from DoTransform function", retval);
-    }
-    src_layer_spec = dest_buffer_stack.back();
-    dest_buffer_stack.pop_back();
-  }
-
-  if (needs_attenuation) {
-    retval =
-        DoAttenuation(src_layer_spec, dest_buffer_stack.back(), needs_vflip);
-    needs_vflip = false;
-    if (retval) {
-      ALOGE("Got error code %d from DoBlending function", retval);
-    }
-    src_layer_spec = dest_buffer_stack.back();
-    dest_buffer_stack.pop_back();
-  }
-
-  if (needs_copy) {
-    retval = DoCopy(src_layer_spec, dest_buffer_stack.back(), needs_vflip);
-    needs_vflip = false;
-    if (retval) {
-      ALOGE("Got error code %d from DoBlending function", retval);
-    }
-    src_layer_spec = dest_buffer_stack.back();
-    dest_buffer_stack.pop_back();
-  }
-
-  // Blending (if needed) should always be the last operation, so that it reads
-  // and writes in the destination layer and not some temporary buffer.
-  if (needs_blending) {
-    retval = DoBlending(src_layer_spec, dest_buffer_stack.back(), needs_vflip);
-    needs_vflip = false;
-    if (retval) {
-      ALOGE("Got error code %d from DoBlending function", retval);
-    }
-    // Don't need to assign destination to source in the last one
-    dest_buffer_stack.pop_back();
-  }
-
-  gralloc_module_->unlock(gralloc_module_, src_priv_handle);
-}
-
-/* static */ const int VSoCComposer::kNumTmpBufferPieces = 2;
-
-VSoCComposer::VSoCComposer(int64_t vsync_base_timestamp,
-                           int32_t vsync_period_ns)
-    : BaseComposer(vsync_base_timestamp, vsync_period_ns),
-      tmp_buffer_(kNumTmpBufferPieces *
-                  ScreenRegionView::GetInstance()->buffer_size()) {}
-
-VSoCComposer::~VSoCComposer() {}
-
-int VSoCComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  int composited_layers_count = 0;
-
-  // Loop over layers in inverse order of z-index
-  for (size_t layer_index = num_layers; layer_index > 0;) {
-    // Decrement here to be able to compare unsigned integer with 0 in the
-    // loop condition
-    --layer_index;
-    if (IS_TARGET_FRAMEBUFFER(layers[layer_index].compositionType)) {
-      continue;
-    }
-    if (layers[layer_index].flags & HWC_SKIP_LAYER) {
-      continue;
-    }
-    if (layers[layer_index].compositionType == HWC_BACKGROUND) {
-      layers[layer_index].compositionType = HWC_FRAMEBUFFER;
-      continue;
-    }
-    layers[layer_index].compositionType = HWC_OVERLAY;
-    // Hwcomposer cannot draw below software-composed layers, so we need
-    // to mark those HWC_FRAMEBUFFER as well.
-    for (size_t top_idx = layer_index + 1; top_idx < num_layers; ++top_idx) {
-      // layers marked as skip are in a state that makes them unreliable to
-      // read, so it's best to assume they cover the whole screen
-      if (layers[top_idx].flags & HWC_SKIP_LAYER ||
-          (layers[top_idx].compositionType == HWC_FRAMEBUFFER &&
-           LayersOverlap(layers[layer_index], layers[top_idx]))) {
-        layers[layer_index].compositionType = HWC_FRAMEBUFFER;
-        break;
-      }
-    }
-    if (layers[layer_index].compositionType == HWC_OVERLAY &&
-        !CanCompositeLayer(layers[layer_index])) {
-      layers[layer_index].compositionType = HWC_FRAMEBUFFER;
-    }
-    if (layers[layer_index].compositionType == HWC_OVERLAY) {
-      ++composited_layers_count;
-    }
-  }
-  return composited_layers_count;
-}
-
-int VSoCComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-  int targetFbs = 0;
-  int buffer_idx = NextScreenBuffer();
-
-  // The framebuffer target layer should be composed if at least one layers was
-  // marked HWC_FRAMEBUFFER or if it's the only layer in the composition
-  // (unlikely)
-  bool fb_target = true;
-  for (size_t idx = 0; idx < num_layers; idx++) {
-    if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
-      // At least one was found
-      fb_target = true;
-      break;
-    }
-    if (layers[idx].compositionType == HWC_OVERLAY) {
-      // Not the only layer in the composition
-      fb_target = false;
-    }
-  }
-
-  // When the framebuffer target needs to be composed, it has to go first.
-  if (fb_target) {
-    for (size_t idx = 0; idx < num_layers; idx++) {
-      if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
-        CompositeLayer(&layers[idx], buffer_idx);
-        break;
-      }
-    }
-  }
-
-  for (size_t idx = 0; idx < num_layers; idx++) {
-    if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
-      ++targetFbs;
-    }
-    if (layers[idx].compositionType == HWC_OVERLAY &&
-        !(layers[idx].flags & HWC_SKIP_LAYER)) {
-      CompositeLayer(&layers[idx], buffer_idx);
-    }
-  }
-  if (targetFbs != 1) {
-    ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
-  }
-  Broadcast(buffer_idx);
-  return 0;
-}
-
-uint8_t* VSoCComposer::RotateTmpBuffer(unsigned int order) {
-  return &tmp_buffer_[(order % kNumTmpBufferPieces) * tmp_buffer_.size() /
-                      kNumTmpBufferPieces];
-}
-
-uint8_t* VSoCComposer::GetSpecialTmpBuffer(size_t needed_size) {
-  special_tmp_buffer_.resize(needed_size);
-  return &special_tmp_buffer_[0];
-}
-
-}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/vsoc_screen_view.cpp b/guest/hals/hwcomposer/vsoc/vsoc_screen_view.cpp
new file mode 100644
index 0000000..6ca9ac2
--- /dev/null
+++ b/guest/hals/hwcomposer/vsoc/vsoc_screen_view.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "guest/hals/hwcomposer/vsoc/vsoc_screen_view.h"
+
+#include <sys/time.h>
+
+#include "common/vsoc/lib/screen_region_view.h"
+
+using vsoc::layout::screen::TimeSpec;
+using vsoc::screen::ScreenRegionView;
+
+namespace cvd {
+namespace {
+
+TimeSpec TimeSpecFromSystemStruct(const timespec* spec) {
+  return {static_cast<uint32_t>(spec->tv_sec),
+          static_cast<uint32_t>(spec->tv_nsec), 0};
+}
+
+void VSoCStatsFromCvdStats(vsoc::layout::screen::CompositionStats* vsoc_stats,
+                           const cvd::CompositionStats* stats) {
+  vsoc_stats->num_prepare_calls = stats->num_prepare_calls;
+  vsoc_stats->num_layers = stats->num_layers;
+  vsoc_stats->num_hwcomposited_layers = stats->num_hwcomposited_layers;
+  vsoc_stats->last_vsync = TimeSpecFromSystemStruct(&stats->last_vsync);
+  vsoc_stats->prepare_start = TimeSpecFromSystemStruct(&stats->prepare_start);
+  vsoc_stats->prepare_end = TimeSpecFromSystemStruct(&stats->prepare_end);
+  vsoc_stats->set_start = TimeSpecFromSystemStruct(&stats->set_start);
+  vsoc_stats->set_end = TimeSpecFromSystemStruct(&stats->set_end);
+}
+
+}  // namespace
+
+VSoCScreenView::VSoCScreenView()
+    : region_view_(ScreenRegionView::GetInstance()) {}
+
+VSoCScreenView::~VSoCScreenView() {}
+
+void VSoCScreenView::Broadcast(int buffer_id,
+                               const cvd::CompositionStats* stats) {
+  if (stats) {
+    vsoc::layout::screen::CompositionStats vsoc_stats;
+    VSoCStatsFromCvdStats(&vsoc_stats, stats);
+    region_view_->BroadcastNewFrame(buffer_id, &vsoc_stats);
+  } else {
+    region_view_->BroadcastNewFrame(buffer_id);
+  }
+}
+
+void* VSoCScreenView::GetBuffer(int fb_index) {
+  return region_view_->GetBuffer(fb_index);
+}
+
+int32_t VSoCScreenView::x_res() const { return region_view_->x_res(); }
+
+int32_t VSoCScreenView::y_res() const { return region_view_->y_res(); }
+
+int32_t VSoCScreenView::dpi() const { return region_view_->dpi(); }
+
+int32_t VSoCScreenView::refresh_rate() const {
+  return region_view_->refresh_rate_hz();
+}
+
+int VSoCScreenView::num_buffers() const {
+  return region_view_->number_of_buffers();
+}
+}  // namespace cvd
diff --git a/guest/hals/hwcomposer/vsoc/vsoc_screen_view.h b/guest/hals/hwcomposer/vsoc/vsoc_screen_view.h
new file mode 100644
index 0000000..1ecace6
--- /dev/null
+++ b/guest/hals/hwcomposer/vsoc/vsoc_screen_view.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "common/libs/fs/shared_fd.h"
+#include "common/vsoc/lib/screen_region_view.h"
+#include "guest/hals/hwcomposer/common/screen_view.h"
+
+namespace cvd {
+
+class VSoCScreenView : public ScreenView {
+ public:
+  VSoCScreenView();
+  virtual ~VSoCScreenView();
+
+  void Broadcast(int buffer_id,
+                 const CompositionStats* stats = nullptr) override;
+  void* GetBuffer(int fb_index) override;
+
+  int32_t x_res() const override;
+  int32_t y_res() const override;
+  int32_t dpi() const override;
+  int32_t refresh_rate() const override;
+
+  int num_buffers() const override;
+
+ private:
+  vsoc::screen::ScreenRegionView* region_view_;
+};
+
+}  // namespace cvd