Uses shared memory regions for framebuffer content and broadcast

Removes the libvsocframebuffer library and replaces its functionality
with the region views.

Bug: 70944937
Bug: 64158705
Test: run locally
Change-Id: I651ea1a676a888b399d7e9b95796147f22168afc
diff --git a/Android.bp b/Android.bp
index e66cfec..c91bc2d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,6 +95,8 @@
         "common/vsoc/lib/e2e_test_region_view.cpp",
         "common/vsoc/lib/fb_bcast_layout.cpp",
         "common/vsoc/lib/fb_bcast_region_view.cpp",
+        "common/vsoc/lib/framebuffer_layout.cpp",
+        "common/vsoc/lib/framebuffer_region_view.cpp",
         "common/vsoc/lib/gralloc_layout.cpp",
         "common/vsoc/lib/input_events_layout.cpp",
         "common/vsoc/lib/input_events_region_view.cpp",
diff --git a/common/vsoc/lib/fb_bcast_region_view.cpp b/common/vsoc/lib/fb_bcast_region_view.cpp
index 0ad526a..a50e06b 100644
--- a/common/vsoc/lib/fb_bcast_region_view.cpp
+++ b/common/vsoc/lib/fb_bcast_region_view.cpp
@@ -20,18 +20,44 @@
 #include "common/vsoc/lib/lock_guard.h"
 
 using vsoc::framebuffer::FBBroadcastRegionView;
+using vsoc::layout::framebuffer::CompositionStats;
+
+uint32_t FBBroadcastRegionView::GetAndSetNextAvailableBufferBit(
+    uint32_t filter) {
+  auto lock_guard(make_lock_guard(&data()->bcast_lock));
+  uint32_t bit = data()->buffer_bits & filter;
+  if (bit == filter) {
+    // All bits from the filter are already set.
+    return 0LU;
+  }
+  // Set available bits to 1
+  bit = (bit ^ filter);
+  // Isolate first available bit
+  bit &= ~bit + 1LU;
+  // Set it on bit set on shared memory
+  data()->buffer_bits |= bit;
+  return bit;
+}
+
+void FBBroadcastRegionView::UnsetBufferBits(uint32_t bits) {
+  auto lock_guard(make_lock_guard(&data()->bcast_lock));
+  data()->buffer_bits &= ~bits;
+}
 
 // We can use a locking protocol because we decided that the streamer should
 // have more priority than the hwcomposer, so it's OK to block the hwcomposer
 // waiting for the streamer to complete, while the streamer will only block on
 // the hwcomposer when it's ran out of work to do and needs to get more from the
 // hwcomposer.
-void FBBroadcastRegionView::BroadcastNewFrame(uint32_t seq_num,
-                                              vsoc_reg_off_t frame_offset) {
+void FBBroadcastRegionView::BroadcastNewFrame(vsoc_reg_off_t frame_offset,
+                                              const CompositionStats* stats) {
   {
     auto lock_guard(make_lock_guard(&data()->bcast_lock));
-    data()->seq_num = seq_num;
+    data()->seq_num++;
     data()->frame_offset = frame_offset;
+    if (stats) {
+      data()->stats = *stats;
+    }
   }
   // Signaling after releasing the lock may cause spurious wake ups.
   // Signaling while holding the lock may cause the just-awaken listener to
@@ -43,7 +69,7 @@
 }
 
 vsoc_reg_off_t FBBroadcastRegionView::WaitForNewFrameSince(
-    uint32_t* last_seq_num) {
+    uint32_t* last_seq_num, CompositionStats* stats) {
   static std::unique_ptr<RegionWorker> worker = StartWorker();
   // It's ok to read seq_num here without holding the lock because the lock will
   // be acquired immediately after so we'll block if necessary to wait for the
@@ -59,6 +85,9 @@
   {
     auto lock_guard(make_lock_guard(&data()->bcast_lock));
     *last_seq_num = data()->seq_num;
+    if (stats) {
+      *stats = data()->stats;
+    }
     return data()->frame_offset;
   }
 }
diff --git a/common/vsoc/lib/fb_bcast_region_view.h b/common/vsoc/lib/fb_bcast_region_view.h
index e92734f..29da4b2 100644
--- a/common/vsoc/lib/fb_bcast_region_view.h
+++ b/common/vsoc/lib/fb_bcast_region_view.h
@@ -25,10 +25,20 @@
 namespace vsoc {
 namespace framebuffer {
 
+// Provides information related to the device's screen. Allows to query screen
+// properties such as resolution and dpi, as well as subscribe/notify to/of
+// changes on the screen contents. It's independent of where the buffer holding
+// the screen contents is. This region will eventually become the display
+// region, which will represent display hardware including the hardware
+// composer.
 class FBBroadcastRegionView
     : public vsoc::TypedRegionView<
           vsoc::layout::framebuffer::FBBroadcastLayout> {
  public:
+  static int align(int input, int alignment = kAlignment) {
+    return (input + alignment - 1) & -alignment;
+  }
+
   // Screen width in pixels
   int x_res() const { return data().x_res; }
 
@@ -39,10 +49,7 @@
   int dpi() const { return data().dpi; }
 
   // Refresh rate in Hertz
-  int refresh_rate_hz() const {
-    // TODO(jemoreira): region_->data()->refresh_rate_hz;
-    return kFbRefreshRateHz;
-  }
+  int refresh_rate_hz() const { return data().refresh_rate_hz; }
 
   uint32_t pixel_format() const { return kFbPixelFormat; }
 
@@ -50,17 +57,38 @@
     return vsoc::PixelFormatProperties<kFbPixelFormat>::bytes_per_pixel;
   }
 
-  // Broadcasts a new frame. Meant to be used exclusively by the hwcomposer.
-  // Zero is an invalid frame_num, used to indicate that there is no frame
-  // available. It's expected that frame_num increases monotonically over time,
-  // but there is no hard requirement for this.
-  // frame_offset is the offset of the current frame in the gralloc region.
-  void BroadcastNewFrame(uint32_t frame_num, vsoc_reg_off_t frame_offset);
+  int line_length() const { return align(x_res() * bytes_per_pixel()); }
+
+  size_t buffer_size() const {
+    return (align(x_res() * bytes_per_pixel()) * y_res()) + kSwiftShaderPadding;
+  }
+
+  // The framebuffer broadcast region mantains a bit set to keep track of the
+  // buffers that have been allocated already. This function atomically finds an
+  // unset (0) bit in the set, sets it to 1 and returns it. The filter parameter
+  // specifies which bits to consider from the set.
+  // TODO(jemoreira): Move frame buffers to the gralloc region and remove this
+  // bitset.
+  uint32_t GetAndSetNextAvailableBufferBit(uint32_t filter);
+  void UnsetBufferBits(uint32_t bits);
+
+  // Broadcasts a new frame.
+  // frame_offset is the offset of the current frame in the framebuffer region.
+  // stats holds performance information of the last composition, can be null.
+  void BroadcastNewFrame(
+      vsoc_reg_off_t frame_offset,
+      const vsoc::layout::framebuffer::CompositionStats* stats = nullptr);
 
   // Waits for a new frame (one with a different seq_num than last one we saw).
   // Returns the offset of the new frame or zero if there was an error, stores
-  // the new sequential number in *last_seq_num.
-  vsoc_reg_off_t WaitForNewFrameSince(uint32_t* last_seq_num);
+  // the new sequential number in *last_seq_num. The frame sequential number are
+  // provided by the hwcomposer and expected to increase monotonically over time
+  // (though it's not a hard requirement), this numbers are guaranteed to be
+  // non-zero when a valid frame is available. Performance statistics are
+  // returned through the stats parameter when it's not null.
+  vsoc_reg_off_t WaitForNewFrameSince(
+      uint32_t* last_seq_num,
+      vsoc::layout::framebuffer::CompositionStats* stats = nullptr);
 
 #if defined(CUTTLEFISH_HOST)
   static std::shared_ptr<FBBroadcastRegionView> GetInstance(const char* domain);
@@ -68,9 +96,16 @@
   static std::shared_ptr<FBBroadcastRegionView> GetInstance();
 #endif
 
- private:
+  using Pixel = uint32_t;
+  static constexpr int kSwiftShaderPadding = 4;
+  static constexpr int kRedShift = 0;
+  static constexpr int kGreenShift = 8;
+  static constexpr int kBlueShift = 16;
+  static constexpr int kRedBits = 8;
+  static constexpr int kGreenBits = 8;
+  static constexpr int kBlueBits = 8;
   static constexpr uint32_t kFbPixelFormat = vsoc::VSOC_PIXEL_FORMAT_RGBA_8888;
-  static constexpr int kFbRefreshRateHz = 60;
+  static constexpr int kAlignment = 8;
 };
 }  // namespace framebuffer
 }  // namespace vsoc
diff --git a/common/vsoc/lib/framebuffer_layout.cpp b/common/vsoc/lib/framebuffer_layout.cpp
new file mode 100644
index 0000000..40e9583
--- /dev/null
+++ b/common/vsoc/lib/framebuffer_layout.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "common/vsoc/shm/framebuffer_layout.h"
+
+namespace vsoc {
+namespace layout {
+
+namespace framebuffer {
+
+const char* FrameBufferLayout::region_name = "framebuffer";
+
+}  // framebuffer
+}  // layout
+}  // vsoc
diff --git a/common/vsoc/lib/framebuffer_region_view.cpp b/common/vsoc/lib/framebuffer_region_view.cpp
new file mode 100644
index 0000000..bc259db
--- /dev/null
+++ b/common/vsoc/lib/framebuffer_region_view.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/vsoc/lib/framebuffer_region_view.h"
+
+using vsoc::framebuffer::FrameBufferRegionView;
+
+size_t FrameBufferRegionView::total_buffer_size() const {
+  return static_cast<size_t>(control_->region_data_size());
+}
+
+uint32_t FrameBufferRegionView::first_buffer_offset() const {
+  return control_->region_size() - control_->region_data_size();
+}
+
+void* FrameBufferRegionView::GetBufferFromOffset(uint32_t offset) {
+  return region_offset_to_pointer<void>(offset);
+}
diff --git a/common/vsoc/lib/framebuffer_region_view.h b/common/vsoc/lib/framebuffer_region_view.h
new file mode 100644
index 0000000..85267d2
--- /dev/null
+++ b/common/vsoc/lib/framebuffer_region_view.h
@@ -0,0 +1,59 @@
+#pragma once
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include "common/vsoc/lib/typed_region_view.h"
+#include "common/vsoc/shm/framebuffer_layout.h"
+
+namespace vsoc {
+namespace framebuffer {
+
+/* Grants access to the framebuffer region. It only knows about the available
+ * buffer space, but not about the distribution of that space, it's up to the
+ * gralloc hal to break it into different buffers.
+ * This region is temporary since the framebuffer should be integrated into the
+ * gralloc buffers region.*/
+class FrameBufferRegionView
+    : public vsoc::TypedRegionView<
+          vsoc::layout::framebuffer::FrameBufferLayout> {
+ public:
+
+#if defined(CUTTLEFISH_HOST)
+  static std::shared_ptr<FrameBufferRegionView> GetInstance(
+      const char* domain) {
+    return RegionView::GetInstanceImpl<FrameBufferRegionView>(
+        [](std::shared_ptr<FrameBufferRegionView> region, const char* domain) {
+          return region->Open(domain);
+        },
+        domain);
+  }
+#else
+  static std::shared_ptr<FrameBufferRegionView> GetInstance() {
+    return RegionView::GetInstanceImpl<FrameBufferRegionView>(
+        std::mem_fn(&FrameBufferRegionView::Open));
+  }
+#endif
+
+  size_t total_buffer_size() const;
+  uint32_t first_buffer_offset() const;
+  // Gets a pointer to an offset of the region.
+  void* GetBufferFromOffset(uint32_t offset);
+};
+
+}  // namespace framebuffer
+}  // namespace vsoc
diff --git a/common/vsoc/lib/region_control.h b/common/vsoc/lib/region_control.h
index 82464aa..fd9377e 100644
--- a/common/vsoc/lib/region_control.h
+++ b/common/vsoc/lib/region_control.h
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include <sys/mman.h>
 #include <stdint.h>
 #include <memory>
 #include "uapi/vsoc_shm.h"
diff --git a/common/vsoc/shm/fb_bcast_layout.h b/common/vsoc/shm/fb_bcast_layout.h
index 21985c0..711e600 100644
--- a/common/vsoc/shm/fb_bcast_layout.h
+++ b/common/vsoc/shm/fb_bcast_layout.h
@@ -25,6 +25,23 @@
 namespace layout {
 
 namespace framebuffer {
+struct TimeSpec {
+  int64_t ts_sec;
+  uint32_t ts_nsec;
+  // Host and guest compilers are giving the structure different sizes without
+  // this field.
+  uint32_t reserved;
+};
+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;
+};
 
 struct FBBroadcastLayout : public RegionLayout {
   static const char* region_name;
@@ -34,15 +51,19 @@
   uint16_t dpi;
   uint16_t refresh_rate_hz;
 
+  uint32_t buffer_bits;
+
   // The frame sequential number
   std::atomic<uint32_t> seq_num;
   // The offset in the gralloc buffer region of the current frame buffer.
   uint32_t frame_offset;
-  // Protects access to the frame offset and sequential number.
+  CompositionStats stats;
+  // Protects access to the frame offset, sequential number and stats.
   // See the region implementation for more details.
   SpinLock bcast_lock;
+  uint32_t reserved;
 };
-ASSERT_SHM_COMPATIBLE(FBBroadcastLayout, framebuffer);
+ASSERT_SHM_COMPATIBLE(FBBroadcastLayout, fb_broadcast);
 
 }  // namespace framebuffer
 
diff --git a/common/vsoc/shm/framebuffer_layout.h b/common/vsoc/shm/framebuffer_layout.h
new file mode 100644
index 0000000..a7af31e
--- /dev/null
+++ b/common/vsoc/shm/framebuffer_layout.h
@@ -0,0 +1,36 @@
+#pragma once
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/vsoc/shm/base.h"
+#include "common/vsoc/shm/version.h"
+
+// Memory for the framebuffer region
+
+namespace vsoc {
+namespace layout {
+
+namespace framebuffer {
+
+struct FrameBufferLayout : public RegionLayout {
+  static const char* region_name;
+};
+ASSERT_SHM_COMPATIBLE(FrameBufferLayout, framebuffer);
+
+}  // namespace framebuffer
+
+}  // namespace layout
+}  // namespace vsoc
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index 7a4e329..459fdb2 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -116,11 +116,20 @@
 
 // Versioning information for fb_bcast_layout.h
 // Changes to these structures will affect only the framebuffer broadcast region
+namespace fb_broadcast {
+namespace {
+const uint32_t version = 2;
+}
+static const std::size_t FBBroadcastLayout_size = 120;
+}  // namespace fb_broadcast
+
+// Versioning information for framebuffer_layout.h
+// Changes to these structures will affect only the framebuffer broadcast region
 namespace framebuffer {
 namespace {
 const uint32_t version = 1;
 }
-static const std::size_t FBBroadcastLayout_size = 24;
+static const std::size_t FrameBufferLayout_size = 1;
 }  // namespace framebuffer
 
 // Versioning information for wifi_layout.h
diff --git a/guest/frontend/vnc_server/Android.mk b/guest/frontend/vnc_server/Android.mk
index e0a4e0d..4b008f3 100644
--- a/guest/frontend/vnc_server/Android.mk
+++ b/guest/frontend/vnc_server/Android.mk
@@ -60,8 +60,7 @@
     cuttlefish_auto_resources \
     cuttlefish_tcp_socket \
     libcuttlefish_fs \
-    vsoc_lib \
-    libvsocframebuffer
+    vsoc_lib
 
 LOCAL_STATIC_LIBRARIES := \
     libjsoncpp
diff --git a/guest/frontend/vnc_server/simulated_hw_composer.cpp b/guest/frontend/vnc_server/simulated_hw_composer.cpp
index 473a6f9..f0e43bd 100644
--- a/guest/frontend/vnc_server/simulated_hw_composer.cpp
+++ b/guest/frontend/vnc_server/simulated_hw_composer.cpp
@@ -16,27 +16,25 @@
 
 #include "simulated_hw_composer.h"
 
+#include "common/vsoc/lib/framebuffer_region_view.h"
+
 using cvd::vnc::SimulatedHWComposer;
+using vsoc::framebuffer::FrameBufferRegionView;
+using vsoc::framebuffer::FBBroadcastRegionView;
 
 SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
     :
 #ifdef FUZZ_TEST_VNC
       engine_{std::random_device{}()},
 #endif
-      control_{VSoCFrameBufferControl::getInstance()},
       bb_{bb},
       stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
-  void* p{};
-  VSoCFrameBuffer::OpenAndMapFrameBuffer(&p, &frame_buffer_fd_);
-  frame_buffer_memory_ = static_cast<char*>(p);
   stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
 }
 
 SimulatedHWComposer::~SimulatedHWComposer() {
   close();
   stripe_maker_.join();
-  VSoCFrameBuffer::UnmapAndCloseFrameBuffer(frame_buffer_memory_,
-                                           frame_buffer_fd_);
 }
 
 cvd::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
@@ -77,12 +75,11 @@
   std::uint64_t stripe_seq_num = 1;
   while (!closed()) {
     bb_->WaitForAtLeastOneClientConnection();
-    int y_offset{};
-    control_.WaitForFrameBufferChangeSince(previous_seq_num, &y_offset,
-                                           &previous_seq_num, nullptr);
-
-    const auto* frame_start =
-        frame_buffer_memory_ + y_offset * ActualScreenWidth() * BytesPerPixel();
+    uint32_t offset =
+        FBBroadcastRegionView::GetInstance()->WaitForNewFrameSince(
+            &previous_seq_num);
+    const char* frame_start = static_cast<char*>(
+        FrameBufferRegionView::GetInstance()->GetBufferFromOffset(offset));
     raw_screen.assign(frame_start, frame_start + ScreenSizeInBytes());
 
     for (int i = 0; i < kNumStripes; ++i) {
diff --git a/guest/frontend/vnc_server/simulated_hw_composer.h b/guest/frontend/vnc_server/simulated_hw_composer.h
index c8a8320..79eeafd 100644
--- a/guest/frontend/vnc_server/simulated_hw_composer.h
+++ b/guest/frontend/vnc_server/simulated_hw_composer.h
@@ -15,12 +15,6 @@
  * limitations under the License.
  */
 
-#include "blackboard.h"
-
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h>
-#include <common/libs/thread_safe_queue/thread_safe_queue.h>
-
 #include <mutex>
 #include <thread>
 
@@ -29,6 +23,11 @@
 #include <random>
 #endif
 
+#include "common/libs/thread_safe_queue/thread_safe_queue.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+
+#include "blackboard.h"
+
 namespace cvd {
 namespace vnc {
 class SimulatedHWComposer {
@@ -58,12 +57,9 @@
   constexpr static std::size_t kMaxQueueElements = 64;
   bool closed_ GUARDED_BY(m_){};
   std::mutex m_;
-  VSoCFrameBufferControl& control_;
   BlackBoard* bb_{};
   ThreadSafeQueue<Stripe> stripes_;
   std::thread stripe_maker_;
-  char* frame_buffer_memory_{};
-  int frame_buffer_fd_{};
 };
 }  // namespace vnc
 }  // namespace cvd
diff --git a/guest/frontend/vnc_server/vnc_client_connection.cpp b/guest/frontend/vnc_server/vnc_client_connection.cpp
index 957e7e7..b3f272e 100644
--- a/guest/frontend/vnc_server/vnc_client_connection.cpp
+++ b/guest/frontend/vnc_server/vnc_client_connection.cpp
@@ -20,8 +20,6 @@
 
 #include "common/libs/tcp_socket/tcp_socket.h"
 
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-
 #include <netinet/in.h>
 #include <sys/time.h>
 
@@ -47,6 +45,7 @@
 using cvd::vnc::Stripe;
 using cvd::vnc::StripePtrVec;
 using cvd::vnc::VncClientConnection;
+using vsoc::framebuffer::FBBroadcastRegionView;
 
 namespace {
 class BigEndianChecker {
@@ -140,18 +139,18 @@
 }
 
 std::uint32_t RedVal(std::uint32_t pixel) {
-  return (pixel >> VSoCFrameBuffer::kRedShift) &
-         ((0x1 << VSoCFrameBuffer::kRedBits) - 1);
+  return (pixel >> FBBroadcastRegionView::kRedShift) &
+         ((0x1 << FBBroadcastRegionView::kRedBits) - 1);
 }
 
 std::uint32_t BlueVal(std::uint32_t pixel) {
-  return (pixel >> VSoCFrameBuffer::kBlueShift) &
-         ((0x1 << VSoCFrameBuffer::kBlueBits) - 1);
+  return (pixel >> FBBroadcastRegionView::kBlueShift) &
+         ((0x1 << FBBroadcastRegionView::kBlueBits) - 1);
 }
 
 std::uint32_t GreenVal(std::uint32_t pixel) {
-  return (pixel >> VSoCFrameBuffer::kGreenShift) &
-         ((0x1 << VSoCFrameBuffer::kGreenBits) - 1);
+  return (pixel >> FBBroadcastRegionView::kGreenShift) &
+         ((0x1 << FBBroadcastRegionView::kGreenBits) - 1);
 }
 }  // namespace
 namespace cvd {
@@ -304,7 +303,7 @@
 
 void VncClientConnection::AppendRawStripe(Message* frame_buffer_update,
                                           const Stripe& stripe) const {
-  using Pixel = VSoCFrameBuffer::Pixel;
+  using Pixel = FBBroadcastRegionView::Pixel;
   auto& fbu = *frame_buffer_update;
   AppendRawStripeHeader(&fbu, stripe);
   auto init_size = fbu.size();
diff --git a/guest/frontend/vnc_server/vnc_utils.h b/guest/frontend/vnc_server/vnc_utils.h
index 3a23d45..e25f860 100644
--- a/guest/frontend/vnc_server/vnc_utils.h
+++ b/guest/frontend/vnc_server/vnc_utils.h
@@ -15,14 +15,13 @@
  * limitations under the License.
  */
 
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-
 #include <vector>
 #include <array>
 #include <utility>
 #include <cstdint>
 
 #include "common/libs/tcp_socket/tcp_socket.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
 
 #undef D
 #ifdef VSOC_VNC_DEBUG
@@ -73,17 +72,17 @@
 };
 
 inline constexpr int BytesPerPixel() {
-  return sizeof(VSoCFrameBuffer::Pixel);
+  return sizeof(vsoc::framebuffer::FBBroadcastRegionView::Pixel);
 }
 
 // The width of the screen regardless of orientation. Does not change.
 inline int ActualScreenWidth() {
-  return VSoCFrameBuffer::getInstance().x_res();
+  return vsoc::framebuffer::FBBroadcastRegionView::GetInstance()->x_res();
 }
 
 // The height of the screen regardless of orientation. Does not change.
 inline int ActualScreenHeight() {
-  return VSoCFrameBuffer::getInstance().y_res();
+  return vsoc::framebuffer::FBBroadcastRegionView::GetInstance()->y_res();
 }
 
 inline int ScreenSizeInBytes() {
diff --git a/guest/hals/gralloc/legacy/Android.mk b/guest/hals/gralloc/legacy/Android.mk
index 030ca35..fe01635 100644
--- a/guest/hals/gralloc/legacy/Android.mk
+++ b/guest/hals/gralloc/legacy/Android.mk
@@ -19,7 +19,8 @@
 VSOC_GRALLOC_COMMON_SRC_FILES := \
     gralloc.cpp \
     framebuffer.cpp \
-    mapper.cpp
+    mapper.cpp \
+    region_registry.cpp
 
 VSOC_GRALLOC_COMMON_CFLAGS:= \
     -DLOG_TAG=\"gralloc_vsoc_legacy\" \
@@ -35,16 +36,19 @@
 LOCAL_SRC_FILES := $(VSOC_GRALLOC_COMMON_SRC_FILES)
 
 LOCAL_CFLAGS := $(VSOC_GRALLOC_COMMON_CFLAGS)
-LOCAL_C_INCLUDES := device/google/cuttlefish_common
+LOCAL_C_INCLUDES := \
+    device/google/cuttlefish_common \
+    device/google/cuttlefish_kernel
 
 LOCAL_HEADER_LIBRARIES := \
     libhardware_headers
 
 LOCAL_SHARED_LIBRARIES := \
+    libbase \
     liblog \
     libutils \
     libcutils \
-    libvsocframebuffer
+    vsoc_lib
 
 LOCAL_VENDOR_MODULE := true
 
diff --git a/guest/hals/gralloc/legacy/framebuffer.cpp b/guest/hals/gralloc/legacy/framebuffer.cpp
index 4251433..8b0f4df 100644
--- a/guest/hals/gralloc/legacy/framebuffer.cpp
+++ b/guest/hals/gralloc/legacy/framebuffer.cpp
@@ -40,12 +40,16 @@
 #endif
 
 #include "gralloc_vsoc_priv.h"
+#include "region_registry.h"
 
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h>
-#include <guest/libs/legacy_framebuffer/RegionRegistry.h>
 #include "common/libs/auto_resources/auto_resources.h"
 #include "common/libs/threads/cuttlefish_thread.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "common/vsoc/lib/framebuffer_region_view.h"
+#include "common/vsoc/shm/framebuffer_layout.h"
+
+using vsoc::framebuffer::FBBroadcastRegionView;
+using vsoc::framebuffer::FrameBufferRegionView;
 
 /*****************************************************************************/
 
@@ -77,17 +81,14 @@
   return 0;
 }
 
-static int fb_post(struct framebuffer_device_t* dev __unused, buffer_handle_t buffer) {
-  const int yoffset = YOffsetFromHandle(buffer);
-  if (yoffset >= 0) {
-    int retval =
-        VSoCFrameBufferControl::getInstance().BroadcastFrameBufferChanged(
-            yoffset);
-    if (retval) ALOGI("Failed to post framebuffer");
-
-    return retval;
+static int fb_post(struct framebuffer_device_t* dev __unused,
+                   buffer_handle_t buffer) {
+  const int offset = OffsetFromHandle(buffer);
+  if (offset < 0 ) {
+    return offset;
   }
-  return -1;
+  FBBroadcastRegionView::GetInstance()->BroadcastNewFrame(offset);
+  return 0;
 }
 
 /*****************************************************************************/
@@ -98,24 +99,28 @@
     return 0;
   }
 
+  // TODO(jemoreira): This assumes the location of the region device nodes, it
+  // should get the path from a more centralized place and have the guest region
+  // control use that as well.
+  std::string fb_file_path = std::string("/dev/").append(
+      vsoc::layout::framebuffer::FrameBufferLayout::region_name);
   int fd;
-  if (!VSoCFrameBuffer::OpenFrameBuffer(&fd)) {
+  if ((fd = open(fb_file_path.c_str(), O_RDWR)) < 0) {
+    ALOGE("Failed to open '%s' (%s)", fb_file_path.c_str(), strerror(errno));
     return -errno;
   }
 
-  const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto framebuffer = FrameBufferRegionView::GetInstance();
 
   /*
-   * map the framebuffer
+   * MAP the framebuffer
    */
-  module->framebuffer =
-      new private_handle_t(fd,
-                           config.total_buffer_size(),
-                           config.hal_format(),
-                           config.x_res(),
-                           config.y_res(),
-                           config.line_length() / (config.bits_per_pixel() / 8),
-                           private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
+  module->framebuffer = new private_handle_t(
+      fd, framebuffer->total_buffer_size(), HAL_PIXEL_FORMAT_RGBX_8888,
+      fb_broadcast->x_res(), fb_broadcast->y_res(),
+      fb_broadcast->line_length() / fb_broadcast->bytes_per_pixel(),
+      private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
   reference_region("framebuffer_init", module->framebuffer);
 
   return 0;
@@ -154,20 +159,21 @@
 
     status = initUserspaceFrameBuffer(m);
 
-    const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
+    auto fb_broadcast = FBBroadcastRegionView::GetInstance();
 
     if (status >= 0) {
-      int stride = config.line_length() / (config.bits_per_pixel() / 8);
-      int format = config.hal_format();
+      int stride =
+          fb_broadcast->line_length() / fb_broadcast->bytes_per_pixel();
+      int format = HAL_PIXEL_FORMAT_RGBX_8888;
       const_cast<uint32_t&>(dev->device.flags) = 0;
-      const_cast<uint32_t&>(dev->device.width) = config.x_res();
-      const_cast<uint32_t&>(dev->device.height) = config.y_res();
+      const_cast<uint32_t&>(dev->device.width) = fb_broadcast->x_res();
+      const_cast<uint32_t&>(dev->device.height) = fb_broadcast->y_res();
       const_cast<int&>(dev->device.stride) = stride;
       const_cast<int&>(dev->device.format) = format;
-      const_cast<float&>(dev->device.xdpi) = config.dpi();
-      const_cast<float&>(dev->device.ydpi) = config.dpi();
-      // TODO (jemoreira): DRY!! Managed by the vsync thread in the hwcomposer
-      const_cast<float&>(dev->device.fps) = (60 * 1000) / 1000.0f;
+      const_cast<float&>(dev->device.xdpi) = fb_broadcast->dpi();
+      const_cast<float&>(dev->device.ydpi) = fb_broadcast->dpi();
+      const_cast<float&>(dev->device.fps) =
+          (fb_broadcast->refresh_rate_hz() * 1000) / 1000.0f;
       const_cast<int&>(dev->device.minSwapInterval) = 1;
       const_cast<int&>(dev->device.maxSwapInterval) = 1;
       *device = &dev->device.common;
diff --git a/guest/hals/gralloc/legacy/gralloc.cpp b/guest/hals/gralloc/legacy/gralloc.cpp
index e2c4104..f90fd4f 100644
--- a/guest/hals/gralloc/legacy/gralloc.cpp
+++ b/guest/hals/gralloc/legacy/gralloc.cpp
@@ -36,14 +36,21 @@
 
 #include <guest/libs/platform_support/api_level_fixes.h>
 
-#include "guest/libs/legacy_framebuffer/vsoc_framebuffer.h"
-#include "guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h"
-#include "guest/libs/legacy_framebuffer/RegionRegistry.h"
-#include "gralloc_vsoc_priv.h"
 #include "common/libs/auto_resources/auto_resources.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "common/vsoc/lib/framebuffer_region_view.h"
+#include "gralloc_vsoc_priv.h"
+#include "region_registry.h"
+
+using vsoc::framebuffer::FBBroadcastRegionView;
+using vsoc::framebuffer::FrameBufferRegionView;
 
 /*****************************************************************************/
 
+static inline size_t roundUpToPageSize(size_t x) {
+  return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
 static int gralloc_alloc_buffer(
     alloc_device_t* /*dev*/, int format, int w, int h,
     buffer_handle_t* pHandle, int* pStrideInPixels) {
@@ -59,9 +66,9 @@
   // a gralloc buffer in this format.
   ALOG_ASSERT(format != HAL_PIXEL_FORMAT_RGB_888);
   if (format == HAL_PIXEL_FORMAT_YV12) {
-    bytes_per_line = VSoCFrameBuffer::align(bytes_per_pixel * w, 16);
+    bytes_per_line = FBBroadcastRegionView::align(bytes_per_pixel * w, 16);
   } else {
-    bytes_per_line = VSoCFrameBuffer::align(bytes_per_pixel * w);
+    bytes_per_line = FBBroadcastRegionView::align(bytes_per_pixel * w);
   }
   size = roundUpToPageSize(size + formatToBytesPerFrame(format, w, h));
   size += PAGE_SIZE;
@@ -108,14 +115,14 @@
 }
 
 static int gralloc_free_framebuffer(private_handle_t const * hnd) {
-    static const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
-    static VSoCFrameBufferControl& fb_control =
-        VSoCFrameBufferControl::getInstance();
-
-    // free this buffer
-    const size_t bufferSize = config.line_length() * config.y_res();
-    int index = hnd->frame_offset / bufferSize;
-    return fb_control.UnsetBufferBits(1LU << index);
+  // free this buffer
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto framebuffer = FrameBufferRegionView::GetInstance();
+  const size_t bufferSize = fb_broadcast->buffer_size();
+  int index =
+    (hnd->frame_offset - framebuffer->first_buffer_offset()) / bufferSize;
+  fb_broadcast->UnsetBufferBits(1LU << index);
+  return 0;
 }
 
 // Allocates a framebuffer taken from the set of buffers given by buffer_mask.
@@ -123,40 +130,39 @@
                                      buffer_handle_t* pHandle,
                                      int* pStrideInPixels,
                                      uint32_t buffer_mask) {
-  static const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
-  static VSoCFrameBufferControl& fb_control =
-      VSoCFrameBufferControl::getInstance();
-
   private_module_t* m = reinterpret_cast<private_module_t*>(
       dev->common.module);
 
   ensure_framebuffer_allocated(m);
 
-  const uint32_t numBuffers = VSoCFrameBuffer::kNumBuffers;
-  const size_t bufferSize = config.bufferSize();
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto framebuffer = FrameBufferRegionView::GetInstance();
+  const size_t buffer_size = fb_broadcast->buffer_size();
+  const uint32_t numBuffers = framebuffer->total_buffer_size() / buffer_size;
 
   // Paranoia: Force the mask to be valid
   buffer_mask &= (1LU << numBuffers) - 1;
 
-  uint32_t bit = fb_control.GetAndSetNextAvailableBufferBit(buffer_mask);
+  uint32_t bit = fb_broadcast->GetAndSetNextAvailableBufferBit(buffer_mask);
   if (!bit) {
     // All buffers in the mask have been allocated already or there was another
     // error
     return -ENOMEM;
   }
 
-  int frame_offset = 0;
+  int frame_offset = framebuffer->first_buffer_offset();
   while (bit != 1LU) {
     bit >>= 1;
-    frame_offset += bufferSize;
+    frame_offset += buffer_size;
   }
 
-  int stride_in_pixels = config.line_length() / (config.bits_per_pixel() / 8);
+  int stride_in_pixels =
+      fb_broadcast->line_length() / fb_broadcast->bytes_per_pixel();
 
   // create a "fake" handle for it
   private_handle_t* hnd = new private_handle_t(
-      dup(m->framebuffer->fd), config.total_buffer_size(),
-      config.hal_format(), config.x_res(), config.y_res(),
+      dup(m->framebuffer->fd), framebuffer->total_buffer_size(),
+      HAL_PIXEL_FORMAT_RGBX_8888, fb_broadcast->x_res(), fb_broadcast->y_res(),
       stride_in_pixels, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, frame_offset);
 
   *pHandle = hnd;
@@ -170,16 +176,28 @@
 static int gralloc_alloc_sf_framebuffer(alloc_device_t* dev,
                                         buffer_handle_t* pHandle,
                                         int* pStrideInPixels) {
-  uint32_t mask = (1LU << VSoCFrameBuffer::kNumSfBuffers) - 1LU;
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto framebuffer = FrameBufferRegionView::GetInstance();
+  int buffer_count =
+      framebuffer->total_buffer_size() / fb_broadcast->buffer_size();
+  int hwc_buffer_count = buffer_count / 2;
+  // This is not buffer_count / 2 if the number of buffer is odd.
+  int sf_buffer_count = buffer_count - hwc_buffer_count;
+  uint32_t mask = (1LU << (sf_buffer_count)) - 1LU;
   // Skip the first buffers since those are for HWC usage
-  mask <<= VSoCFrameBuffer::kNumHwcBuffers;
+  mask <<= hwc_buffer_count;
   return gralloc_alloc_framebuffer(dev, pHandle, pStrideInPixels, mask);
 }
 
 static int gralloc_alloc_hwc_framebuffer(alloc_device_t* dev,
                                          buffer_handle_t* pHandle) {
-  // Use the first kNumHwcBuffers for hwcomposer
-  uint32_t mask = (1LU << VSoCFrameBuffer::kNumHwcBuffers) - 1LU;
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto framebuffer = FrameBufferRegionView::GetInstance();
+  int buffer_count =
+      framebuffer->total_buffer_size() / fb_broadcast->buffer_size();
+  // Use the first buffers for hwcomposer
+  int hwc_buffer_count = buffer_count / 2;
+  uint32_t mask = (1LU << hwc_buffer_count) - 1LU;
   return gralloc_alloc_framebuffer(dev, pHandle, NULL, mask);
 }
 
diff --git a/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
index 579ec79..67ed0ad 100644
--- a/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
+++ b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
@@ -28,7 +28,7 @@
 
 #include <linux/fb.h>
 
-#include "guest/libs/legacy_framebuffer/vsoc_framebuffer.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
 #include "guest/libs/platform_support/api_level_fixes.h"
 
 #ifndef GRALLOC_MODULE_API_VERSION_0_2
@@ -157,6 +157,93 @@
   }
 }
 
+inline const char* pixel_format_to_string(int format) {
+  switch (format) {
+    // Formats that are universal across versions
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+      return "RGBA_8888";
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+      return "RGBX_8888";
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+      return "BGRA_8888";
+    case HAL_PIXEL_FORMAT_RGB_888:
+      return "RGB_888";
+    case HAL_PIXEL_FORMAT_RGB_565:
+      return "RGB_565";
+    case HAL_PIXEL_FORMAT_YV12:
+      return "YV12";
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+      return "YCrCb_420_SP";
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+      return "YCbCr_422_SP";
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+      return "YCbCr_422_I";
+
+#if VSOC_PLATFORM_SDK_AFTER(J)
+    // First supported on JBMR1 (API 17)
+    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+      return "IMPLEMENTATION_DEFINED";
+    case HAL_PIXEL_FORMAT_BLOB:
+      return "BLOB";
+#endif
+#if VSOC_PLATFORM_SDK_AFTER(J_MR1)
+    // First supported on JBMR2 (API 18)
+    case HAL_PIXEL_FORMAT_YCbCr_420_888:
+      return "YCbCr_420_888";
+    case HAL_PIXEL_FORMAT_Y8:
+      return "Y8";
+    case HAL_PIXEL_FORMAT_Y16:
+      return "Y16";
+#endif
+#if VSOC_PLATFORM_SDK_AFTER(K)
+    // Support was added in L (API 21)
+    case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+      return "RAW_OPAQUE";
+    // This is an alias for RAW_SENSOR in L and replaces it in M.
+    case HAL_PIXEL_FORMAT_RAW16:
+      return "RAW16";
+    case HAL_PIXEL_FORMAT_RAW10:
+      return "RAW10";
+#endif
+#if VSOC_PLATFORM_SDK_AFTER(L_MR1)
+    case HAL_PIXEL_FORMAT_YCbCr_444_888:
+      return "YCbCr_444_888";
+    case HAL_PIXEL_FORMAT_YCbCr_422_888:
+      return "YCbCr_422_888";
+    case HAL_PIXEL_FORMAT_RAW12:
+      return "RAW12";
+    case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
+      return "FLEX_RGBA_8888";
+    case HAL_PIXEL_FORMAT_FLEX_RGB_888:
+      return "FLEX_RGB_888";
+#endif
+
+      // Formats that have been removed
+#if VSOC_PLATFORM_SDK_BEFORE(K)
+    // Support was dropped on K (API 19)
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+      return "RGBA_5551";
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+      return "RGBA_4444";
+#endif
+#if VSOC_PLATFORM_SDK_BEFORE(L)
+    // Renamed to RAW_16 in L. Both were present for L, but it was completely
+    // removed in M.
+    case HAL_PIXEL_FORMAT_RAW_SENSOR:
+      return "RAW_SENSOR";
+#endif
+#if VSOC_PLATFORM_SDK_AFTER(J_MR2) && VSOC_PLATFORM_SDK_BEFORE(M)
+    // Supported K, L, and LMR1. Not supported on JBMR0, JBMR1, JBMR2, and M
+    case HAL_PIXEL_FORMAT_sRGB_X_8888:
+      return "sRGB_X_8888";
+    case HAL_PIXEL_FORMAT_sRGB_A_8888:
+      return "sRGB_A_8888";
+#endif
+  }
+  return "UNKNOWN";
+}
+
+
 static inline void formatToYcbcr(
     int format, int width, int height, void* base_v, android_ycbcr* out) {
   char* it = static_cast<char*>(base_v);
@@ -167,8 +254,9 @@
 #ifdef GRALLOC_MODULE_API_VERSION_0_2
     case HAL_PIXEL_FORMAT_YCbCr_420_888:
 #endif
-      out->ystride = VSoCFrameBuffer::align(width, 16);
-      out->cstride = VSoCFrameBuffer::align(out->ystride / 2, 16);
+      out->ystride = vsoc::framebuffer::FBBroadcastRegionView::align(width, 16);
+      out->cstride =
+          vsoc::framebuffer::FBBroadcastRegionView::align(out->ystride / 2, 16);
       out->chroma_step = 1;
       out->y = it;
       it += out->ystride * height;
@@ -204,23 +292,25 @@
       formatToYcbcr(format, w, h, NULL, &strides);
       y_size = strides.ystride * h;
       c_size = strides.cstride * h / 2;
-      return (y_size + 2 * c_size + VSoCFrameBuffer::kSwiftShaderPadding);
+      return (y_size + 2 * c_size +
+              vsoc::framebuffer::FBBroadcastRegionView::kSwiftShaderPadding);
     /*case HAL_PIXEL_FORMAT_RGBA_8888:
     case HAL_PIXEL_FORMAT_RGBX_8888:
     case HAL_PIXEL_FORMAT_BGRA_8888:
     case HAL_PIXEL_FORMAT_RGB_888:
     case HAL_PIXEL_FORMAT_RGB_565:*/
     default:
-      w16 = VSoCFrameBuffer::align(w, 16);
-      h16 = VSoCFrameBuffer::align(h, 16);
-      return bytes_per_pixel * w16 * h16 + VSoCFrameBuffer::kSwiftShaderPadding;
+      w16 = vsoc::framebuffer::FBBroadcastRegionView::align(w, 16);
+      h16 = vsoc::framebuffer::FBBroadcastRegionView::align(h, 16);
+      return bytes_per_pixel * w16 * h16 +
+             vsoc::framebuffer::FBBroadcastRegionView::kSwiftShaderPadding;
   }
 }
 
-// Calculates the yoffset from a framebuffer handle. I checks the given handle
-// for errors first. Returns the yoffset (non negative integer) or -1 if there
+// Calculates the offset from a framebuffer handle. It checks the given handle
+// for errors first. Returns the offset (non negative integer) or -1 if there
 // is an error.
-static inline int YOffsetFromHandle(buffer_handle_t buffer_hnd) {
+static inline int OffsetFromHandle(buffer_handle_t buffer_hnd) {
     if (!buffer_hnd) {
     ALOGE("Attempt to post null buffer");
     return -1;
@@ -236,8 +326,7 @@
     return -1;
   }
 
-  const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
-  return hnd->frame_offset / config.line_length();
+  return hnd->frame_offset;
 }
 
 int fb_device_open(
diff --git a/guest/hals/gralloc/legacy/mapper.cpp b/guest/hals/gralloc/legacy/mapper.cpp
index 8339df9..17effa9 100644
--- a/guest/hals/gralloc/legacy/mapper.cpp
+++ b/guest/hals/gralloc/legacy/mapper.cpp
@@ -31,10 +31,8 @@
 #include <hardware/gralloc.h>
 #include <system/graphics.h>
 
-#include "guest/libs/legacy_framebuffer/RegionRegistry.h"
-
 #include "gralloc_vsoc_priv.h"
-#include "guest/libs/remoter/remoter_framework_pkt.h"
+#include "region_registry.h"
 
 #define DEBUG_REFERENCES 1
 #define DEBUG_MAX_LOCK_LEVEL 20
diff --git a/guest/libs/legacy_framebuffer/RegionRegistry.cpp b/guest/hals/gralloc/legacy/region_registry.cpp
similarity index 98%
rename from guest/libs/legacy_framebuffer/RegionRegistry.cpp
rename to guest/hals/gralloc/legacy/region_registry.cpp
index 24010b0..5207fff 100644
--- a/guest/libs/legacy_framebuffer/RegionRegistry.cpp
+++ b/guest/hals/gralloc/legacy/region_registry.cpp
@@ -13,6 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "VSoCGrallocRegionRegistry"
+
 #include <limits.h>
 #include <errno.h>
 #include <pthread.h>
@@ -24,7 +30,6 @@
 #include <sys/types.h>
 
 #include <cutils/hashmap.h>
-#define LOG_TAG "VSoCGrallocRegionRegistry"
 #include <cutils/log.h>
 #include <cutils/atomic.h>
 
@@ -34,7 +39,7 @@
 #include <hardware/gralloc.h>
 #include <system/graphics.h>
 
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+#include "gralloc_vsoc_priv.h"
 
 // TODO(ghartman): Make the configurable through a property
 static const bool g_log_refs = false;
diff --git a/guest/libs/legacy_framebuffer/RegionRegistry.h b/guest/hals/gralloc/legacy/region_registry.h
similarity index 100%
rename from guest/libs/legacy_framebuffer/RegionRegistry.h
rename to guest/hals/gralloc/legacy/region_registry.h
diff --git a/guest/hals/hwcomposer/hwcomposer.cpp b/guest/hals/hwcomposer/hwcomposer.cpp
index cb59136..0e3374e 100644
--- a/guest/hals/hwcomposer/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/hwcomposer.cpp
@@ -162,12 +162,11 @@
         ALOGW("Skipping layer %zu due to failed sanity check", i);
         continue;
       }
-      vsoc_hwc_device* pdev = reinterpret_cast<vsoc_hwc_device*>(dev);
       const vsoc_buffer_handle_t* fb_handle =
           reinterpret_cast<const vsoc_buffer_handle_t*>(
               list->hwLayers[i].handle);
       FBBroadcastRegionView::GetInstance()->BroadcastNewFrame(
-          pdev->frame_num++, fb_handle->offset);
+          fb_handle->offset);
       break;
     }
   }
diff --git a/guest/hals/hwcomposer/legacy/Android.mk b/guest/hals/hwcomposer/legacy/Android.mk
index 672d139..23faeee 100644
--- a/guest/hals/hwcomposer/legacy/Android.mk
+++ b/guest/hals/hwcomposer/legacy/Android.mk
@@ -51,7 +51,6 @@
 LOCAL_VENDOR_MODULE := true
 
 LOCAL_SHARED_LIBRARIES := \
-    libvsocframebuffer \
     liblog \
     libbase \
     libcutils \
@@ -59,6 +58,7 @@
     libsync \
     libhardware \
     libjpeg \
+    vsoc_lib \
     $(VSOC_STLPORT_LIBS)
 
 LOCAL_STATIC_LIBRARIES := \
@@ -77,6 +77,7 @@
 
 LOCAL_C_INCLUDES := \
     device/google/cuttlefish_common \
+    device/google/cuttlefish_kernel \
     bionic \
     $(VSOC_STLPORT_INCLUDES)
 
diff --git a/guest/hals/hwcomposer/legacy/base_composer.cpp b/guest/hals/hwcomposer/legacy/base_composer.cpp
index f41ed3b..ed50cf4 100644
--- a/guest/hals/hwcomposer/legacy/base_composer.cpp
+++ b/guest/hals/hwcomposer/legacy/base_composer.cpp
@@ -17,16 +17,19 @@
 #include "base_composer.h"
 
 #include <cutils/log.h>
-#include "guest/hals/gralloc//legacy/gralloc_vsoc_priv.h"
-#include "guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h"
+
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+
+using vsoc::framebuffer::FBBroadcastRegionView;
 
 namespace cvd {
 
 namespace {
 
-int BroadcastFrameBufferChanged(int yoffset) {
-  return VSoCFrameBufferControl::getInstance().BroadcastFrameBufferChanged(
-      yoffset);
+void BroadcastFrameBufferChanged(int32_t offset) {
+  FBBroadcastRegionView::GetInstance()->BroadcastNewFrame(
+      static_cast<uint32_t>(offset));
 }
 
 }  // namespace
@@ -51,18 +54,13 @@
 
 void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
 
-int BaseComposer::PostFrameBuffer(buffer_handle_t buffer) {
-  const int yoffset = YOffsetFromHandle(buffer);
-  // If the broadcaster is NULL or could not get a good yoffset just ignore it.
-  if (fb_broadcaster_ && yoffset >= 0) {
-    int retval = fb_broadcaster_(yoffset);
-    if (retval) {
-      ALOGI("Failed to post framebuffer");
-      return -1;
-    }
+int32_t BaseComposer::PostFrameBuffer(buffer_handle_t buffer) {
+  const int32_t offset = OffsetFromHandle(buffer);
+  // If the broadcaster is NULL or could not get a good offset just ignore it.
+  if (fb_broadcaster_ && offset >= 0) {
+    fb_broadcaster_(offset);
   }
-
-  return yoffset;
+  return offset;
 }
 
 int BaseComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
@@ -76,7 +74,7 @@
   return 0;
 }
 
-int BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+int32_t 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 PostFrameBuffer(layers[idx].handle);
diff --git a/guest/hals/hwcomposer/legacy/base_composer.h b/guest/hals/hwcomposer/legacy/base_composer.h
index fd9db9d..3577da3 100644
--- a/guest/hals/hwcomposer/legacy/base_composer.h
+++ b/guest/hals/hwcomposer/legacy/base_composer.h
@@ -20,7 +20,7 @@
 
 namespace cvd {
 
-typedef int (*FbBroadcaster)(int);
+using FbBroadcaster = void (*)(int);
 
 class BaseComposer {
  public:
@@ -30,13 +30,13 @@
   // 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 the yoffset that was broadcasted or a negative number if there was
+  // Returns the offset that was broadcasted or a negative number if there was
   // an error.
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
-  // Returns yoffset of the handle or negative on error.
-  int PostFrameBuffer(buffer_handle_t handle);
+  int32_t SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
+  // Returns buffer offset or negative on error.
+  int32_t PostFrameBuffer(buffer_handle_t handle);
   // Changes the broadcaster, gives the ability to report more than just the
-  // yoffset by using a wrapper like the StatsKeepingComposer. Returns the old
+  // 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);
diff --git a/guest/hals/hwcomposer/legacy/hwcomposer.cpp b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
index 26f7706..693496d 100644
--- a/guest/hals/hwcomposer/legacy/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
@@ -49,10 +49,8 @@
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
-#include <guest/hals/gralloc/legacy/gralloc_vsoc_priv.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h>
-#include <guest/libs/remoter/remoter_framework_pkt.h>
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
 #include <sync/sync.h>
 
 #include "base_composer.h"
@@ -61,6 +59,8 @@
 #include "stats_keeper.h"
 #include "vsoc_composer.h"
 
+using vsoc::framebuffer::FBBroadcastRegionView;
+
 #ifdef USE_OLD_HWCOMPOSER
 typedef cvd::BaseComposer InnerComposerType;
 #else
@@ -245,20 +245,22 @@
 #if VSOC_PLATFORM_SDK_AFTER(J)
 static int32_t vsoc_hwc_attribute(struct vsoc_hwc_composer_device_1_t* pdev,
                                   const uint32_t attribute) {
-  const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
   switch (attribute) {
     case HWC_DISPLAY_VSYNC_PERIOD:
       return pdev->vsync_period_ns;
     case HWC_DISPLAY_WIDTH:
-      return config.x_res();
+      return fb_broadcast->x_res();
     case HWC_DISPLAY_HEIGHT:
-      return config.y_res();
+      return fb_broadcast->y_res();
     case HWC_DISPLAY_DPI_X:
-      ALOGI("Reporting DPI_X of %d", config.dpi());
-      return config.dpi() * 1000;  // The number of pixels per thousand inches
+      ALOGI("Reporting DPI_X of %d", fb_broadcast->dpi());
+      // The number of pixels per thousand inches
+      return fb_broadcast->dpi() * 1000;
     case HWC_DISPLAY_DPI_Y:
-      ALOGI("Reporting DPI_Y of %d", config.dpi());
-      return config.dpi() * 1000;  // The number of pixels per thousand inches
+      ALOGI("Reporting DPI_Y of %d", fb_broadcast->dpi());
+      // The number of pixels per thousand inches
+      return fb_broadcast->dpi() * 1000;
     default:
       ALOGE("unknown display attribute %u", attribute);
       return -EINVAL;
@@ -310,7 +312,7 @@
     return -ENOMEM;
   }
 
-  int refreshRate = 60;
+  int refreshRate = FBBroadcastRegionView::GetInstance()->refresh_rate_hz();
   dev->vsync_period_ns = 1000000000 / refreshRate;
   struct timespec rt;
   if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
diff --git a/guest/hals/hwcomposer/legacy/hwcomposer.mk b/guest/hals/hwcomposer/legacy/hwcomposer.mk
index d2d3832..3913d1d 100644
--- a/guest/hals/hwcomposer/legacy/hwcomposer.mk
+++ b/guest/hals/hwcomposer/legacy/hwcomposer.mk
@@ -18,7 +18,6 @@
 LOCAL_VENDOR_MODULE := true
 
 LOCAL_SHARED_LIBRARIES := \
-    libvsocframebuffer \
     libbase \
     liblog \
     libcutils \
@@ -26,6 +25,7 @@
     libsync \
     libhardware \
     libjpeg \
+    vsoc_lib \
     $(VSOC_STLPORT_LIBS)
 
 LOCAL_STATIC_LIBRARIES := \
@@ -45,6 +45,7 @@
 
 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/legacy/stats_keeper.cpp b/guest/hals/hwcomposer/legacy/stats_keeper.cpp
index 104f1ae..33ca28a 100644
--- a/guest/hals/hwcomposer/legacy/stats_keeper.cpp
+++ b/guest/hals/hwcomposer/legacy/stats_keeper.cpp
@@ -31,6 +31,7 @@
 using cvd::time::Nanoseconds;
 using cvd::time::Seconds;
 using cvd::time::TimeDifference;
+using vsoc::layout::framebuffer::TimeSpec;
 
 namespace cvd {
 
@@ -51,8 +52,33 @@
   return *mset.rbegin();
 }
 
+void TimeDifferenceToTimeSpec(const TimeDifference& td, TimeSpec* ts) {
+  ts->ts_sec = td.seconds();
+  ts->ts_nsec = td.subseconds_in_ns();
+}
+
 }  // namespace
 
+void StatsKeeper::GetLastCompositionStats(
+    vsoc::layout::framebuffer::CompositionStats* stats_p) {
+  if (stats_p) {
+    TimeDifferenceToTimeSpec(last_composition_stats_.prepare_start.SinceEpoch(),
+                             &stats_p->prepare_start);
+    TimeDifferenceToTimeSpec(last_composition_stats_.prepare_end.SinceEpoch(),
+                             &stats_p->prepare_end);
+    TimeDifferenceToTimeSpec(last_composition_stats_.set_start.SinceEpoch(),
+                             &stats_p->set_start);
+    TimeDifferenceToTimeSpec(last_composition_stats_.set_end.SinceEpoch(),
+                             &stats_p->set_end);
+    TimeDifferenceToTimeSpec(last_composition_stats_.last_vsync.SinceEpoch(),
+                             &stats_p->last_vsync);
+
+    stats_p->num_prepare_calls = last_composition_stats_.num_prepare_calls;
+    stats_p->num_layers = last_composition_stats_.num_layers;
+    stats_p->num_hwcomposited_layers = last_composition_stats_.num_hwc_layers;
+  }
+}
+
 StatsKeeper::StatsKeeper(TimeDifference timespan, int64_t vsync_base,
                          int32_t vsync_period)
     : period_length_(timespan, 1),
diff --git a/guest/hals/hwcomposer/legacy/stats_keeper.h b/guest/hals/hwcomposer/legacy/stats_keeper.h
index 14d3602..397728a 100644
--- a/guest/hals/hwcomposer/legacy/stats_keeper.h
+++ b/guest/hals/hwcomposer/legacy/stats_keeper.h
@@ -15,13 +15,15 @@
  * limitations under the License.
  */
 
-#include <android-base/thread_annotations.h>
-#include <common/libs/threads/cuttlefish_thread.h>
-#include <common/libs/time/monotonic_time.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h>
 #include <deque>
 #include <set>
 
+#include <android-base/thread_annotations.h>
+
+#include "common/libs/threads/cuttlefish_thread.h"
+#include "common/libs/time/monotonic_time.h"
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+
 #include "hwcomposer_common.h"
 
 namespace cvd {
@@ -60,6 +62,20 @@
   cvd::time::Nanoseconds set_calls_time_;
 };
 
+struct HWCCompositionStats {
+  cvd::time::MonotonicTimePoint prepare_start;
+  cvd::time::MonotonicTimePoint prepare_end;
+  cvd::time::MonotonicTimePoint set_start;
+  cvd::time::MonotonicTimePoint set_end;
+  cvd::time::MonotonicTimePoint last_vsync;
+  // There may be more than one call to prepare, the timestamps are with regards
+  // to the last one (the one that precedes the set call)
+  int num_prepare_calls;
+  int num_layers;
+  // The number of layers composed by the hwcomposer
+  int num_hwc_layers;
+};
+
 class StatsKeeper {
  public:
   // The timespan parameter indicates for how long we keep stats about the past
@@ -78,9 +94,8 @@
   void RecordSetStart();
   void RecordSetEnd() EXCLUDES(mutex_);
 
-  const CompositionStats& last_composition_stats() {
-    return last_composition_stats_;
-  }
+  void GetLastCompositionStats(
+      vsoc::layout::framebuffer::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
@@ -96,7 +111,7 @@
   int32_t vsync_period_;
   // Data collected about ongoing composition. These variables are not accessed
   // from Dump(), so they don't need to be guarded by a mutex.
-  CompositionStats last_composition_stats_;
+  HWCCompositionStats last_composition_stats_;
 
   // Aggregated performance data collected from past compositions. These
   // variables are modified when a composition is completed and when old
@@ -142,9 +157,9 @@
         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(NULL);
+    composer_.ReplaceFbBroadcaster(nullptr);
   }
-  ~StatsKeepingComposer() {}
+  ~StatsKeepingComposer() = default;
 
   int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
     stats_keeper_.RecordPrepareStart(num_layers);
@@ -153,17 +168,19 @@
     return num_hwc_layers;
   }
 
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+  int32_t SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+    vsoc::layout::framebuffer::CompositionStats stats;
     stats_keeper_.RecordSetStart();
-    int yoffset = composer_.SetLayers(num_layers, layers);
+    int32_t offset = composer_.SetLayers(num_layers, layers);
     stats_keeper_.RecordSetEnd();
-    if (yoffset >= 0) {
-      VSoCFrameBufferControl::getInstance().BroadcastFrameBufferChanged(
-          yoffset, &stats_keeper_.last_composition_stats());
+    if (offset >= 0) {
+      stats_keeper_.GetLastCompositionStats(&stats);
+      vsoc::framebuffer::FBBroadcastRegionView::GetInstance()
+          ->BroadcastNewFrame(static_cast<uint32_t>(offset), &stats);
     } else {
-      ALOGE("%s: Error on SetLayers(), yoffset: %d", __FUNCTION__, yoffset);
+      ALOGE("%s: Error on SetLayers(), offset: %d", __FUNCTION__, offset);
     }
-    return yoffset;
+    return offset;
   }
 
   void Dump(char* buff, int buff_len) {
diff --git a/guest/hals/hwcomposer/legacy/vsoc_composer.cpp b/guest/hals/hwcomposer/legacy/vsoc_composer.cpp
index f538336..e12c7a6 100644
--- a/guest/hals/hwcomposer/legacy/vsoc_composer.cpp
+++ b/guest/hals/hwcomposer/legacy/vsoc_composer.cpp
@@ -15,20 +15,25 @@
  */
 
 #include "vsoc_composer.h"
-#include <cutils/log.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer.h>
-#include <guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h>
-#include <hardware/hwcomposer.h>
-#include <hardware/hwcomposer_defs.h>
-#include <libyuv.h>
-#include <system/graphics.h>
+
 #include <algorithm>
 #include <cstdlib>
 #include <utility>
 #include <vector>
+
+#include <cutils/log.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
+#include <libyuv.h>
+#include <system/graphics.h>
+
+#include "common/vsoc/lib/fb_bcast_region_view.h"
+
 #include "geometry_utils.h"
 #include "hwcomposer_common.h"
 
+using vsoc::framebuffer::FBBroadcastRegionView;
+
 namespace cvd {
 
 namespace {
@@ -215,9 +220,9 @@
   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 = VSoCFrameBuffer::align(stride_y / 2, 16);
+  int stride_v = FBBroadcastRegionView::align(stride_y / 2, 16);
   uint8_t* src_u = src_v + stride_v * src.height / 2;
-  int stride_u = VSoCFrameBuffer::align(stride_y / 2, 16);
+  int stride_u = FBBroadcastRegionView::align(stride_y / 2, 16);
 
   // Adjust for crop
   src_y += src.crop_y * stride_y + src.crop_x;
@@ -453,7 +458,7 @@
         // these sizes are taken from the displayFrame rectangle which is always
         // smaller than the framebuffer, the framebuffer in turn has aligned
         // stride and these buffers are the size of the framebuffer.
-        VSoCFrameBuffer::align(
+        FBBroadcastRegionView::align(
             x_res * formatToBytesPerPixel(dst_priv_handle->format), 16));
     dest_buffer_stack.push_back(tmp);
     needed_tmp_buffers--;
@@ -475,7 +480,7 @@
       // 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 = VSoCFrameBuffer::align(
+      int dst_stride = FBBroadcastRegionView::align(
           src_width * formatToBytesPerPixel(dst_priv_handle->format), 16);
       size_t needed_size = dst_stride * src_height;
       dst_buffer_spec.width = src_width;
@@ -581,17 +586,17 @@
                            int32_t vsync_period_ns)
     : BaseComposer(vsync_base_timestamp, vsync_period_ns),
       tmp_buffer_(kNumTmpBufferPieces *
-                  VSoCFrameBuffer::getInstance().bufferSize()),
+                  FBBroadcastRegionView::GetInstance()->buffer_size()),
       next_hwc_framebuffer_(0) {
   hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
                 reinterpret_cast<const hw_module_t**>(&gralloc_module_));
   gralloc_module_->common.methods->open(
       reinterpret_cast<const hw_module_t*>(gralloc_module_),
       GRALLOC_HARDWARE_GPU0, reinterpret_cast<hw_device_t**>(&gralloc_dev_));
-  for (int i = 0; i < VSoCFrameBuffer::kNumHwcBuffers; ++i) {
-    buffer_handle_t tmp;
-    gralloc_dev_->alloc_hwc_framebuffer(
-        reinterpret_cast<alloc_device_t*>(gralloc_dev_), &tmp);
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  buffer_handle_t tmp;
+  while (gralloc_dev_->alloc_hwc_framebuffer(
+             reinterpret_cast<alloc_device_t*>(gralloc_dev_), &tmp) == 0) {
     hwc_framebuffers_.push_back(tmp);
   }
 }
@@ -650,7 +655,7 @@
   return composited_layers_count;
 }
 
-int VSoCComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+int32_t VSoCComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
   int targetFbs = 0;
   buffer_handle_t fb_handle = FindFrameBuffer(num_layers, layers);
   if (!fb_handle) {
diff --git a/guest/hals/hwcomposer/legacy/vsoc_composer.h b/guest/hals/hwcomposer/legacy/vsoc_composer.h
index 892515c..9abe06c 100644
--- a/guest/hals/hwcomposer/legacy/vsoc_composer.h
+++ b/guest/hals/hwcomposer/legacy/vsoc_composer.h
@@ -15,13 +15,15 @@
  * limitations under the License.
  */
 
-#include <hardware/gralloc.h>
-#include "base_composer.h"
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
-#include "hwcomposer_common.h"
-
 #include <vector>
 
+#include <hardware/gralloc.h>
+
+#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
+
+#include "base_composer.h"
+#include "hwcomposer_common.h"
+
 namespace cvd {
 
 class VSoCComposer : public BaseComposer {
@@ -32,7 +34,7 @@
   // override
   int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
   // override
-  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
+  int32_t SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
 
  protected:
   static const int kNumTmpBufferPieces;
diff --git a/guest/libs/legacy_framebuffer/Android.mk b/guest/libs/legacy_framebuffer/Android.mk
deleted file mode 100644
index 672879d..0000000
--- a/guest/libs/legacy_framebuffer/Android.mk
+++ /dev/null
@@ -1,62 +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.
-
-# Temporary, this library should go away once the new HALS are in place.
-
-vsocframebuffer_common_src_files := \
-    vsoc_framebuffer.cpp \
-    vsoc_framebuffer_control.cpp \
-    RegionRegistry.cpp
-
-vsocframebuffer_common_c_flags := -Wall -Werror $(VSOC_VERSION_CFLAGS)
-
-vsocframebuffer_common_c_includes := \
-    device/google/cuttlefish_common \
-    device/google/cuttlefish_kernel
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libvsocframebuffer
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := ${vsocframebuffer_common_src_files}
-LOCAL_CFLAGS += ${vsocframebuffer_common_c_flags}
-LOCAL_C_INCLUDES := ${vsocframebuffer_common_c_includes} \
-    $(VSOC_STLPORT_INCLUDES)
-
-LOCAL_STATIC_LIBRARIES := \
-    libjsoncpp
-
-LOCAL_HEADER_LIBRARIES := \
-    libhardware_headers
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    liblog \
-    libutils \
-    libcutils \
-    cuttlefish_auto_resources \
-    libcuttlefish_fs \
-    vsoc_lib \
-    $(VSOC_STLPORT_LIBS)
-
-# See b/67109557
-ifeq (true, $(TARGET_TRANSLATE_2ND_ARCH))
-LOCAL_MULTILIB := first
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/guest/libs/legacy_framebuffer/vsoc_framebuffer.cpp b/guest/libs/legacy_framebuffer/vsoc_framebuffer.cpp
deleted file mode 100644
index 1669715..0000000
--- a/guest/libs/legacy_framebuffer/vsoc_framebuffer.cpp
+++ /dev/null
@@ -1,222 +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 <guest/libs/platform_support/api_level_fixes.h>
-
-#define LOG_TAG "VSoCFrameBuffer"
-
-#include "vsoc_framebuffer.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utils/String8.h>
-#include <cutils/log.h>
-#include <system/graphics.h>
-
-#include "common/vsoc/lib/fb_bcast_region_view.h"
-
-const char* const VSoCFrameBuffer::kFrameBufferPath =
-    "/dev/userspace_framebuffer";
-
-const VSoCFrameBuffer & VSoCFrameBuffer::getInstance() {
-  static VSoCFrameBuffer instance;
-  instance.Configure();
-  return instance;
-}
-
-
-VSoCFrameBuffer::VSoCFrameBuffer()
-  : line_length_(-1) { }
-
-
-void VSoCFrameBuffer::Configure() {
-  fb_region_view_ = vsoc::framebuffer::FBBroadcastRegionView::GetInstance();
-  if (!fb_region_view_) {
-    SLOGE("Failed to open broadcaster region");
-  }
-  line_length_ = align(x_res() * sizeof(Pixel));
-}
-
-
-int VSoCFrameBuffer::dpi() const {
-  return fb_region_view_->dpi();
-}
-
-
-int VSoCFrameBuffer::x_res() const {
-  return fb_region_view_->x_res();
-}
-
-
-int VSoCFrameBuffer::y_res() const {
-  return fb_region_view_->y_res();
-}
-
-
-bool VSoCFrameBuffer::OpenFrameBuffer(int* frame_buffer_fd) {
-  int fb_fd;
-  if ((fb_fd = open(VSoCFrameBuffer::kFrameBufferPath, O_RDWR)) < 0) {
-    SLOGE("Failed to open '%s' (%s)",
-          VSoCFrameBuffer::kFrameBufferPath, strerror(errno));
-    return false;
-  }
-
-  const VSoCFrameBuffer& config = VSoCFrameBuffer::getInstance();
-
-  if (ftruncate(fb_fd, config.total_buffer_size()) < 0) {
-    SLOGE("Failed to truncate framebuffer (%s)", strerror(errno));
-    return false;
-  }
-
-  *frame_buffer_fd = fb_fd;
-  return true;
-}
-
-
-bool VSoCFrameBuffer::OpenAndMapFrameBuffer(void** fb_memory,
-					    int* frame_buffer_fd) {
-  int fb_fd;
-  if (!VSoCFrameBuffer::OpenFrameBuffer(&fb_fd)) { return false; }
-
-  size_t fb_size = VSoCFrameBuffer::getInstance().total_buffer_size();
-
-  void* mmap_res = mmap(0, fb_size, PROT_READ, MAP_SHARED, fb_fd, 0);
-  if (mmap_res == MAP_FAILED) {
-    SLOGE("Failed to mmap framebuffer (%s)", strerror(errno));
-    close(fb_fd);
-    return false;
-  }
-
-  // Modify the pointers only after mmap succeeds.
-  *fb_memory = mmap_res;
-  *frame_buffer_fd = fb_fd;
-
-  return true;
-}
-
-bool VSoCFrameBuffer::UnmapAndCloseFrameBuffer(void* fb_memory,
-                                                    int frame_buffer_fd) {
-  size_t fb_size = VSoCFrameBuffer::getInstance().total_buffer_size();
-  return munmap(fb_memory, fb_size) == 0 && close(frame_buffer_fd) == 0;
-}
-
-
-int VSoCFrameBuffer::hal_format() const {
-  switch(bits_per_pixel()) {
-    case 32:
-      if (kRedShift) {
-        return HAL_PIXEL_FORMAT_BGRA_8888;
-      } else {
-        return HAL_PIXEL_FORMAT_RGBX_8888;
-      }
-    default:
-      return HAL_PIXEL_FORMAT_RGB_565;
-  }
-}
-
-const char* pixel_format_to_string(int format) {
-  switch (format) {
-    // Formats that are universal across versions
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-      return "RGBA_8888";
-    case HAL_PIXEL_FORMAT_RGBX_8888:
-      return "RGBX_8888";
-    case HAL_PIXEL_FORMAT_BGRA_8888:
-      return "BGRA_8888";
-    case HAL_PIXEL_FORMAT_RGB_888:
-      return "RGB_888";
-    case HAL_PIXEL_FORMAT_RGB_565:
-      return "RGB_565";
-    case HAL_PIXEL_FORMAT_YV12:
-      return "YV12";
-    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-      return "YCrCb_420_SP";
-    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-      return "YCbCr_422_SP";
-    case HAL_PIXEL_FORMAT_YCbCr_422_I:
-      return "YCbCr_422_I";
-
-#if VSOC_PLATFORM_SDK_AFTER(J)
-    // First supported on JBMR1 (API 17)
-    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-      return "IMPLEMENTATION_DEFINED";
-    case HAL_PIXEL_FORMAT_BLOB:
-      return "BLOB";
-#endif
-#if VSOC_PLATFORM_SDK_AFTER(J_MR1)
-    // First supported on JBMR2 (API 18)
-    case HAL_PIXEL_FORMAT_YCbCr_420_888:
-      return "YCbCr_420_888";
-    case HAL_PIXEL_FORMAT_Y8:
-      return "Y8";
-    case HAL_PIXEL_FORMAT_Y16:
-      return "Y16";
-#endif
-#if VSOC_PLATFORM_SDK_AFTER(K)
-    // Support was added in L (API 21)
-    case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-      return "RAW_OPAQUE";
-    // This is an alias for RAW_SENSOR in L and replaces it in M.
-    case HAL_PIXEL_FORMAT_RAW16:
-      return "RAW16";
-    case HAL_PIXEL_FORMAT_RAW10:
-      return "RAW10";
-#endif
-#if VSOC_PLATFORM_SDK_AFTER(L_MR1)
-    case HAL_PIXEL_FORMAT_YCbCr_444_888:
-      return "YCbCr_444_888";
-    case HAL_PIXEL_FORMAT_YCbCr_422_888:
-      return "YCbCr_422_888";
-    case HAL_PIXEL_FORMAT_RAW12:
-      return "RAW12";
-    case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
-      return "FLEX_RGBA_8888";
-    case HAL_PIXEL_FORMAT_FLEX_RGB_888:
-      return "FLEX_RGB_888";
-#endif
-
-    // Formats that have been removed
-#if VSOC_PLATFORM_SDK_BEFORE(K)
-    // Support was dropped on K (API 19)
-    case HAL_PIXEL_FORMAT_RGBA_5551:
-      return "RGBA_5551";
-    case HAL_PIXEL_FORMAT_RGBA_4444:
-      return "RGBA_4444";
-#endif
-#if VSOC_PLATFORM_SDK_BEFORE(L)
-    // Renamed to RAW_16 in L. Both were present for L, but it was completely
-    // removed in M.
-    case HAL_PIXEL_FORMAT_RAW_SENSOR:
-      return "RAW_SENSOR";
-#endif
-#if VSOC_PLATFORM_SDK_AFTER(J_MR2) && VSOC_PLATFORM_SDK_BEFORE(M)
-    // Supported K, L, and LMR1. Not supported on JBMR0, JBMR1, JBMR2, and M
-    case HAL_PIXEL_FORMAT_sRGB_X_8888:
-      return "sRGB_X_8888";
-    case HAL_PIXEL_FORMAT_sRGB_A_8888:
-      return "sRGB_A_8888";
-#endif
-  }
-  return "UNKNOWN";
-}
diff --git a/guest/libs/legacy_framebuffer/vsoc_framebuffer.h b/guest/libs/legacy_framebuffer/vsoc_framebuffer.h
deleted file mode 100644
index ce3ef6a..0000000
--- a/guest/libs/legacy_framebuffer/vsoc_framebuffer.h
+++ /dev/null
@@ -1,112 +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 <pthread.h>
-#include <sys/mman.h>
-
-#include <climits>
-#include <memory>
-
-struct private_handle_t;
-struct remoter_request_packet;
-
-namespace vsoc {
-namespace framebuffer {
-class FBBroadcastRegionView;
-}
-}
-
-inline size_t roundUpToPageSize(size_t x) {
-  return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
-}
-
-class VSoCFrameBuffer {
-public:
-  static const VSoCFrameBuffer& getInstance();
-  VSoCFrameBuffer(const VSoCFrameBuffer&) = delete;
-  VSoCFrameBuffer& operator=(const VSoCFrameBuffer&) = delete;
-
-  static int align(int input, int alignment = kAlignment) {
-    return (input + alignment - 1) & -alignment;
-  }
-
-  int bits_per_pixel() const {
-    return kBitsPerPixel;
-  }
-
-  size_t bufferSize() const {
-    return line_length_ * y_res();
-  }
-
-  int dpi() const;
-
-  int hal_format() const;
-
-  int line_length() const { return line_length_; }
-
-  int total_buffer_size() const {
-    return roundUpToPageSize(line_length_ * y_res_virtual() +
-                             VSoCFrameBuffer::kSwiftShaderPadding);
-  }
-
-  int x_res() const;
-
-  int y_res() const;
-
-  int y_res_virtual() const {
-    return y_res() * kNumBuffers;
-  }
-
-  static const int kAlignment = 8;
-  static const int kNumHwcBuffers = 3;
-  // Without sync fences enabled surfaceflinger uses only 2 framebuffers,
-  // regardless of how many are available
-  static const int kNumSfBuffers = 3;
-  static const int kNumBuffers = kNumHwcBuffers + kNumSfBuffers;
-  static const char* const kFrameBufferPath;
-
-  static const int kRedShift = 0;
-  static const int kRedBits = 8;
-  static const int kGreenShift = 8;
-  static const int kGreenBits = 8;
-  static const int kBlueShift = 16;
-  static const int kBlueBits = 8;
-  static const int kAlphaShift = 24;
-  static const int kAlphaBits = 8;
-  typedef uint32_t Pixel;
-  static const int kSwiftShaderPadding = 4;
-
-  // Opens the framebuffer file. Ensures the file has the appropriate size by
-  // calling ftruncate.
-  static bool OpenFrameBuffer(int* frame_buffer_fd);
-
-  // Maps the framebuffer into memory. It's the caller's responsibility to
-  // unmap the memory and close the file when done.
-  static bool OpenAndMapFrameBuffer(void** fb_memory, int* frame_buffer_fd);
-  static bool UnmapAndCloseFrameBuffer(void* fb_memory, int frame_buffer_fd);
-
-private:
-  VSoCFrameBuffer();
-  void Configure();
-
-  std::shared_ptr<vsoc::framebuffer::FBBroadcastRegionView> fb_region_view_;
-  static const int kBitsPerPixel = sizeof(Pixel) * CHAR_BIT;
-  // Length of a scan-line in bytes.
-  int line_length_;
-};
-
-const char* pixel_format_to_string(int format);
diff --git a/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.cpp b/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.cpp
deleted file mode 100644
index 83c9b00..0000000
--- a/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.cpp
+++ /dev/null
@@ -1,294 +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 <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include <utils/String8.h>
-
-#define LOG_TAG "VSoCFrameBufferControl"
-#include <cutils/log.h>
-#include <system/graphics.h>
-
-#include "guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h"
-#include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
-
-enum { NOT_YET = 0, IN_PROGRESS, DONE };
-
-struct FrameBufferControl {
-  pthread_mutex_t mutex;
-  pthread_cond_t cond_var;
-  uint32_t seq_num;
-  volatile int yoffset;
-  volatile int initialized;
-  volatile uint32_t buffer_bits;
-  CompositionStats stats;
-};
-
-// __sync_lock_test_and_set is described to work on intel, but not on many other
-// targets.
-#define ATOMICALLY_SET(x, val) __sync_lock_test_and_set(&(x), (val))
-#define ATOMICALLY_COMPARE_AND_SWAP(x, old, val) \
-  __sync_val_compare_and_swap(&(x), (old), (val))
-// fetch the value, don't modify it (or with 0)
-#define ATOMICALLY_GET(x) __sync_or_and_fetch(&(x), 0)
-
-const char* const VSoCFrameBufferControl::kFrameBufferControlPath =
-    "/dev/framebuffer_control";
-
-VSoCFrameBufferControl& VSoCFrameBufferControl::getInstance() {
-  static VSoCFrameBufferControl instance;
-  // If not initialized before and fails to initialize now
-  if (!instance.Initialize()) {
-    LOG_ALWAYS_FATAL(
-        "Unable to initialize the framebuffer control structure (%s)... "
-        "aborting!",
-        strerror(errno));
-  }
-  return instance;
-}
-
-uint32_t VSoCFrameBufferControl::GetAndSetNextAvailableBufferBit(uint32_t filter) {
-  if (pthread_mutex_lock(&control_memory_->mutex)) {
-    ALOGE("Failed to acquire lock on framebuffer control mutex (%s) - %s",
-          strerror(errno), __FUNCTION__);
-    return 0;
-  }
-  uint32_t bit = control_memory_->buffer_bits;
-  bit &= filter;
-  if (bit == filter) {
-    // All bits in the filter are already set in the set
-    bit = 0LU;
-  } else {
-    // Set available bits to 1
-    bit = (bit^filter);
-    // isolate first available bit
-    bit &= ~bit + 1LU;
-    // set it on bit set on shared memory
-    control_memory_->buffer_bits |= bit;
-  }
-
-  pthread_mutex_unlock(&control_memory_->mutex);
-  return bit;
-}
-
-int VSoCFrameBufferControl::UnsetBufferBits(uint32_t bits) {
-  if (pthread_mutex_lock(&control_memory_->mutex)) {
-    ALOGE("Failed to acquire lock on framebuffer control mutex (%s) - %s",
-          strerror(errno), __FUNCTION__);
-    return -1;
-  }
-
-  control_memory_->buffer_bits &= ~bits;
-
-  pthread_mutex_unlock(&control_memory_->mutex);
-  return 0;
-}
-
-VSoCFrameBufferControl::VSoCFrameBufferControl()
-    : control_fd_(-1), control_memory_(NULL) {}
-
-namespace {
-
-bool MapFrameBufferControl(FrameBufferControl** control_memory_ptr,
-                           int* fbc_fd) {
-  size_t control_size = sizeof(FrameBufferControl);
-  mode_t fb_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
-  int control_fd;
-  if ((control_fd = open(VSoCFrameBufferControl::kFrameBufferControlPath, O_RDWR,
-                         fb_mode)) < 0) {
-    ALOGE("Failed to open framebuffer control at %s (%s)",
-          VSoCFrameBufferControl::kFrameBufferControlPath, strerror(errno));
-    return false;
-  }
-
-  if (ftruncate(control_fd, sizeof(FrameBufferControl)) < 0) {
-    ALOGE("Failed to truncate framebuffer control at %s (%s)",
-          VSoCFrameBufferControl::kFrameBufferControlPath, strerror(errno));
-    return false;
-  }
-
-  void* control_memory;
-  control_memory =
-      mmap(0, control_size, PROT_READ | PROT_WRITE, MAP_SHARED, control_fd, 0);
-  if (control_memory == MAP_FAILED) {
-    ALOGE("Failed to mmap framebuffer control (%s)", strerror(errno));
-    close(control_fd);
-    return false;
-  }
-
-  *control_memory_ptr = reinterpret_cast<FrameBufferControl*>(control_memory);
-  *fbc_fd = control_fd;
-
-  return true;
-}
-
-void UnmapFrameBufferControl(FrameBufferControl** control_memory_ptr,
-                             int* fbc_fd) {
-  munmap(*control_memory_ptr, sizeof(FrameBufferControl));
-  *control_memory_ptr = NULL;
-  close(*fbc_fd);
-  *fbc_fd = -1;
-}
-}
-
-bool VSoCFrameBufferControl::Initialize() {
-  if (control_fd_ >= 0) {
-    return true;
-  }
-
-  if (!MapFrameBufferControl(&control_memory_, &control_fd_)) {
-    return false;
-  }
-
-  int initializing_state = ATOMICALLY_COMPARE_AND_SWAP(
-      control_memory_->initialized, NOT_YET, IN_PROGRESS);
-  switch (initializing_state) {
-    case DONE:
-      return true;
-
-    case IN_PROGRESS: {  // wait 1 sec and try again
-      do {
-        sleep(1);
-        initializing_state = ATOMICALLY_GET(control_memory_->initialized);
-        if (initializing_state != DONE) {
-          ALOGW(
-              "Framebuffer control structure has not yet been initialized "
-              "after one second. Value of initialized flag: %d",
-              initializing_state);
-        }
-      } while (initializing_state != DONE);
-      return true;
-    }
-
-    case NOT_YET: {  // flag set to IN_PROGRESS, proceed to initialize
-      pthread_mutexattr_t mutex_attr;
-      pthread_mutexattr_init(&mutex_attr);
-      pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
-      int retval = pthread_mutex_init(&(control_memory_->mutex), &mutex_attr);
-      if (retval) {
-        ALOGE("Failed to acquire lock on framebuffer control mutex (%s) - %s",
-              strerror(errno), __FUNCTION__);
-        UnmapFrameBufferControl(&control_memory_, &control_fd_);
-        return false;
-      }
-      pthread_mutexattr_destroy(&mutex_attr);
-
-      pthread_condattr_t cond_attr;
-      pthread_condattr_init(&cond_attr);
-      pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
-      retval = pthread_cond_init(&(control_memory_->cond_var), &cond_attr);
-      if (retval) {
-        ALOGE("Failed to initialize cond var for framebuffer control (%s)",
-              strerror(errno));
-        pthread_mutex_destroy(&(control_memory_->mutex));
-        UnmapFrameBufferControl(&control_memory_, &control_fd_);
-        return false;
-      }
-      pthread_condattr_destroy(&cond_attr);
-
-      ATOMICALLY_SET(control_memory_->buffer_bits, 0LU);
-      ATOMICALLY_SET(control_memory_->seq_num, 0);
-      ATOMICALLY_SET(control_memory_->initialized, DONE);
-
-      return true;
-    }
-
-    default: {  // unrecognized value
-      ALOGE("Framebuffer control memory is corrupt, initialized = %d",
-            initializing_state);
-      UnmapFrameBufferControl(&control_memory_, &control_fd_);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-int VSoCFrameBufferControl::GetCurrentYOffset() const {
-  if (!control_memory_) return -1;
-  return control_memory_->yoffset;
-}
-
-int VSoCFrameBufferControl::WaitForFrameBufferChangeSince(
-    uint32_t previous_fb_seq,
-    int* yoffset_p,
-    uint32_t* fb_seq_p,
-    CompositionStats* stats_p) {
-  if (pthread_mutex_lock(&control_memory_->mutex)) {
-    ALOGE("Failed to acquire lock on framebuffer control mutex (%s) - %s",
-          strerror(errno), __FUNCTION__);
-    return -1;
-  }
-  int retval = 0;
-
-  while (control_memory_->seq_num == previous_fb_seq) {
-    retval =
-        pthread_cond_wait(&control_memory_->cond_var, &control_memory_->mutex);
-  }
-
-  if (fb_seq_p) {
-    *fb_seq_p = control_memory_->seq_num;
-  }
-  if (yoffset_p) {
-    *yoffset_p = control_memory_->yoffset;
-  }
-  if (stats_p) {
-    *stats_p = control_memory_->stats;
-  }
-
-  pthread_mutex_unlock(&control_memory_->mutex);
-  return retval;
-}
-
-int VSoCFrameBufferControl::WaitForFrameBufferChange(int* yoffset_p) {
-  return WaitForFrameBufferChangeSince(
-      control_memory_->seq_num, yoffset_p, NULL, NULL);
-}
-
-int VSoCFrameBufferControl::BroadcastFrameBufferChanged(int yoffset) {
-  return BroadcastFrameBufferChanged(yoffset, NULL);
-}
-
-// increments the framebuffer sequential number, ensuring it's never zero
-static inline uint32_t seq_inc(uint32_t num) {
-  ++num;
-  return num? num: 1;
-}
-
-int VSoCFrameBufferControl::BroadcastFrameBufferChanged(
-    int yoffset, const CompositionStats* stats) {
-  if (pthread_mutex_lock(&control_memory_->mutex)) {
-    ALOGE("Failed to acquire lock on framebuffer control mutex (%s)",
-          strerror(errno));
-    return -1;
-  }
-  control_memory_->yoffset = yoffset;
-  control_memory_->seq_num = seq_inc(control_memory_->seq_num);
-  if (stats) { control_memory_->stats = *stats; }
-  pthread_cond_broadcast(&control_memory_->cond_var);
-  pthread_mutex_unlock(&control_memory_->mutex);
-
-  return 0;
-}
diff --git a/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h b/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h
deleted file mode 100644
index 5e1ec7e..0000000
--- a/guest/libs/legacy_framebuffer/vsoc_framebuffer_control.h
+++ /dev/null
@@ -1,88 +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 <common/libs/time/monotonic_time.h>
-
-struct FrameBufferControl;
-
-struct CompositionStats {
-  cvd::time::MonotonicTimePoint prepare_start;
-  cvd::time::MonotonicTimePoint prepare_end;
-  cvd::time::MonotonicTimePoint set_start;
-  cvd::time::MonotonicTimePoint set_end;
-  cvd::time::MonotonicTimePoint last_vsync;
-  // There may be more than one call to prepare, the timestamps are with regards to the last one (the one that precedes the set call)
-  int num_prepare_calls;
-  int num_layers;
-  // The number of layers composed by the hwcomposer
-  int num_hwc_layers;
-};
-
-class VSoCFrameBufferControl {
- public:
-  static VSoCFrameBufferControl& getInstance();
-
-  static const char* const kFrameBufferControlPath;
-
-  // The framebuffer control structure mantains a bit set to keep track of the
-  // buffers that have been allocated already. This function atomically finds an
-  // unset (0) bit in the set, sets it to 1 and returns it. It will only
-  // consider bits already set in the filter parameter.
-  uint32_t GetAndSetNextAvailableBufferBit(uint32_t filter);
-  // Returns 0 on success
-  int UnsetBufferBits(uint32_t bits);
-
-  // Returns the yoffset of the last framebuffer update or a negative number on
-  // error.
-  int GetCurrentYOffset() const;
-  // Returns the value returned by the pthread_cond_wait, or -1 if the control
-  // structure has not been initialized by the hwcomposer yet.
-  int WaitForFrameBufferChange(int* yoffset_p);
-  // Uses a sequential number to determine whether the client was notified of
-  // the last framebuffer change and therefore needs to wait for a new one or if
-  // it can just return with the last one. It also provides the timings of the
-  // composition. Any NULL input parameters will be ignored. The sequential
-  // numbers are guaranteed to never be zero, so a value of zero can be used to
-  // get the last frame without waiting (useful when we want to get a frame for
-  // the first time).
-  int WaitForFrameBufferChangeSince(uint32_t previous_fb_seq,
-                                    int* yoffset_p,
-                                    uint32_t* fb_seq_p,
-                                    CompositionStats* stats_p);
-
-  // Returns 0 on success, a negative number on error.
-  int BroadcastFrameBufferChanged(int yoffset);
-
-  // Returns 0 on success, a negative number on error.
-  int BroadcastFrameBufferChanged(int yoffset, const CompositionStats* stats);
-
- private:
-  VSoCFrameBufferControl();
-
-  // Map the control structure to memory and initialize its contents.
-  bool Initialize();
-
-  // FD for the frame buffer control.
-  int control_fd_;
-  // Pointer to the mapped frame buffer control.
-  FrameBufferControl* control_memory_;
-
-  // Disallow copy and assign
-  VSoCFrameBufferControl(const VSoCFrameBufferControl&) {}
-  VSoCFrameBufferControl& operator=(const VSoCFrameBufferControl&) {
-    return *this;
-  }
-};
diff --git a/host/commands/launch/fb_bcast_region_handler.cc b/host/commands/launch/fb_bcast_region_handler.cc
index 03f20b7..047c621 100644
--- a/host/commands/launch/fb_bcast_region_handler.cc
+++ b/host/commands/launch/fb_bcast_region_handler.cc
@@ -24,6 +24,7 @@
 DEFINE_int32(x_res, 720, "Width of the screen in pixels");
 DEFINE_int32(y_res, 1280, "Height of the screen in pixels");
 DEFINE_int32(dpi, 160, "Pixels per inch for the screen");
+DEFINE_int32(refresh_rate_hz, 60, "Screen refresh rate in Hertz");
 
 void InitializeFBBroadcastRegion() {
   std::shared_ptr<vsoc::framebuffer::FBBroadcastRegionView> region =
@@ -37,4 +38,5 @@
   dest->x_res = FLAGS_x_res;
   dest->y_res = FLAGS_y_res;
   dest->dpi = FLAGS_dpi;
+  dest->refresh_rate_hz = FLAGS_refresh_rate_hz;
 }
diff --git a/host/config/vsoc_mem.json b/host/config/vsoc_mem.json
index f9cbc36..36f03ce 100644
--- a/host/config/vsoc_mem.json
+++ b/host/config/vsoc_mem.json
@@ -87,11 +87,29 @@
 
    {
      "device_name" : "gralloc_memory",
-     "__comment" : "Holds the gralloc buffers",
+     "__comment" : "Holds the gralloc buffers. Size is 400 MB minus the size of the framebuffer",
      "managed_by" : "gralloc_manager",
      "current_version" : 0,
      "min_compatible_version" : 0,
-     "region_size" : 419430400,
+     "region_size" : 394850304,
+
+     "guest_to_host_signal_table" : {
+       "__comment" : "sizeof each node is based on common/libs/shm/lock.h",
+       "num_nodes_lg2" : 0
+      },
+
+     "host_to_guest_signal_table" : {
+       "num_nodes_lg2" : 0
+      }
+   },
+
+
+   {
+     "device_name" : "framebuffer",
+     "__comment" : "Holds the frame buffers. Size is enough to accomodate 6 buffers 800x1280 in RGBA format plus an extra page",
+     "current_version" : 0,
+     "min_compatible_version" : 0,
+     "region_size" : 24584192,
 
      "guest_to_host_signal_table" : {
        "__comment" : "sizeof each node is based on common/libs/shm/lock.h",