Makes framebuffer region not allocatable by gralloc hal.

This eliminates the need to keep a bitset of allocated buffers, which
causes trouble when rebooting; causes the framework to no longer have
access to the composed frames, as it happens in physical devices. The
downside is that an extra copy is performed everytime OpenGL
composition is performed.

- Deletes all the code related to having different layers for the
  framebuffer target and other types of gralloc buffers.
- Refactors the composer class hierarchy to accomodate the new
  behavior.

Bug: 72757295
Bug: 72758122
Test: run locally
Change-Id: I8432ebd01564e5d0463ccd3913d1a6d84bbb89d5
diff --git a/common/vsoc/lib/fb_bcast_region_view.cpp b/common/vsoc/lib/fb_bcast_region_view.cpp
index a50e06b..49f2756 100644
--- a/common/vsoc/lib/fb_bcast_region_view.cpp
+++ b/common/vsoc/lib/fb_bcast_region_view.cpp
@@ -22,28 +22,6 @@
 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
diff --git a/common/vsoc/lib/fb_bcast_region_view.h b/common/vsoc/lib/fb_bcast_region_view.h
index 29da4b2..b12c67b 100644
--- a/common/vsoc/lib/fb_bcast_region_view.h
+++ b/common/vsoc/lib/fb_bcast_region_view.h
@@ -63,15 +63,6 @@
     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.
diff --git a/common/vsoc/shm/fb_bcast_layout.h b/common/vsoc/shm/fb_bcast_layout.h
index 711e600..50267cb 100644
--- a/common/vsoc/shm/fb_bcast_layout.h
+++ b/common/vsoc/shm/fb_bcast_layout.h
@@ -51,17 +51,14 @@
   uint16_t dpi;
   uint16_t refresh_rate_hz;
 
-  uint32_t buffer_bits;
-
+  // Protects access to the frame offset, sequential number and stats.
+  // See the region implementation for more details.
+  SpinLock bcast_lock;
   // 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;
   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, fb_broadcast);
 
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index 459fdb2..418cdd2 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -118,9 +118,9 @@
 // Changes to these structures will affect only the framebuffer broadcast region
 namespace fb_broadcast {
 namespace {
-const uint32_t version = 2;
+const uint32_t version = 3;
 }
-static const std::size_t FBBroadcastLayout_size = 120;
+static const std::size_t FBBroadcastLayout_size = 112;
 }  // namespace fb_broadcast
 
 // Versioning information for framebuffer_layout.h
diff --git a/guest/hals/gralloc/legacy/framebuffer.cpp b/guest/hals/gralloc/legacy/framebuffer.cpp
index 8b0f4df..a8e397c 100644
--- a/guest/hals/gralloc/legacy/framebuffer.cpp
+++ b/guest/hals/gralloc/legacy/framebuffer.cpp
@@ -82,51 +82,37 @@
 }
 
 static int fb_post(struct framebuffer_device_t* dev __unused,
-                   buffer_handle_t buffer) {
-  const int offset = OffsetFromHandle(buffer);
-  if (offset < 0 ) {
-    return offset;
-  }
-  FBBroadcastRegionView::GetInstance()->BroadcastNewFrame(offset);
-  return 0;
-}
-
-/*****************************************************************************/
-
-int initUserspaceFrameBuffer(struct private_module_t* module) {
-  cvd::LockGuard<pthread_mutex_t> guard(module->lock);
-  if (module->framebuffer) {
-    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 ((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;
-  }
+                   buffer_handle_t buffer_handle) {
+  static int frame_buffer_idx = 0;
 
   auto fb_broadcast = FBBroadcastRegionView::GetInstance();
-  auto framebuffer = FrameBufferRegionView::GetInstance();
+  auto fb_region = FrameBufferRegionView::GetInstance();
 
-  /*
-   * MAP the 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);
+  int32_t fb_offset = fb_region->first_buffer_offset() +
+                      frame_buffer_idx * fb_broadcast->buffer_size();
+  void* frame_buffer = fb_region->GetBufferFromOffset(fb_offset);
+  const private_handle_t* p_handle =
+      reinterpret_cast<const private_handle_t*>(buffer_handle);
+  void* buffer;
+  int retval =
+      reinterpret_cast<gralloc_module_t*>(dev->common.module)
+          ->lock(reinterpret_cast<const gralloc_module_t*>(dev->common.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, fb_broadcast->buffer_size());
+  fb_broadcast->BroadcastNewFrame(fb_offset);
+
+  frame_buffer_idx =
+      (frame_buffer_idx + 1) %
+      (fb_region->total_buffer_size() /fb_broadcast->buffer_size());
 
   return 0;
 }
 
-
 /*****************************************************************************/
 
 static int fb_close(struct hw_device_t *dev) {
@@ -139,45 +125,40 @@
 
 int fb_device_open(
     hw_module_t const* module, const char* name, hw_device_t** device) {
-  int status = -EINVAL;
-  if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
-    /* initialize our state here */
-    fb_context_t* dev = (fb_context_t*) malloc(sizeof(*dev));
-    LOG_FATAL_IF(!dev, "%s: malloc returned NULL.", __FUNCTION__);
-    memset(dev, 0, sizeof(*dev));
-
-    /* initialize the procs */
-    dev->device.common.tag = HARDWARE_DEVICE_TAG;
-    dev->device.common.version = 0;
-    dev->device.common.module = const_cast<hw_module_t*>(module);
-    dev->device.common.close = fb_close;
-    dev->device.setSwapInterval = fb_setSwapInterval;
-    dev->device.post            = fb_post;
-    dev->device.setUpdateRect   = fb_setUpdateRect;
-
-    private_module_t* m = (private_module_t*)module;
-
-    status = initUserspaceFrameBuffer(m);
-
-    auto fb_broadcast = FBBroadcastRegionView::GetInstance();
-
-    if (status >= 0) {
-      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) = 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) = 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;
-    }
+  if (strcmp(name, GRALLOC_HARDWARE_FB0) != 0) {
+    return -EINVAL;
   }
-  return status;
+  /* initialize our state here */
+  fb_context_t* dev = (fb_context_t*) malloc(sizeof(*dev));
+  LOG_FATAL_IF(!dev, "%s: malloc returned NULL.", __FUNCTION__);
+  memset(dev, 0, sizeof(*dev));
+
+  /* initialize the procs */
+  dev->device.common.tag = HARDWARE_DEVICE_TAG;
+  dev->device.common.version = 0;
+  dev->device.common.module = const_cast<hw_module_t*>(module);
+  dev->device.common.close = fb_close;
+  dev->device.setSwapInterval = fb_setSwapInterval;
+  dev->device.post            = fb_post;
+  dev->device.setUpdateRect   = fb_setUpdateRect;
+
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+
+  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) = 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) = 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;
+
+  return 0;
 }
diff --git a/guest/hals/gralloc/legacy/gralloc.cpp b/guest/hals/gralloc/legacy/gralloc.cpp
index f90fd4f..232058c 100644
--- a/guest/hals/gralloc/legacy/gralloc.cpp
+++ b/guest/hals/gralloc/legacy/gralloc.cpp
@@ -101,120 +101,13 @@
 
 /*****************************************************************************/
 
-static int ensure_framebuffer_allocated(private_module_t* m) {
-  // allocate the framebuffer
-  if (m->framebuffer == NULL) {
-    // The framebuffer is mapped once and forever.
-    int err = initUserspaceFrameBuffer(m);
-    if (err < 0) {
-      ALOGE("Failed to map framebuffer (%d)", errno);
-      return err;
-    }
-  }
-  return 0;
-}
-
-static int gralloc_free_framebuffer(private_handle_t const * hnd) {
-  // 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.
-static int gralloc_alloc_framebuffer(alloc_device_t* dev,
-                                     buffer_handle_t* pHandle,
-                                     int* pStrideInPixels,
-                                     uint32_t buffer_mask) {
-  private_module_t* m = reinterpret_cast<private_module_t*>(
-      dev->common.module);
-
-  ensure_framebuffer_allocated(m);
-
-  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_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 = framebuffer->first_buffer_offset();
-  while (bit != 1LU) {
-    bit >>= 1;
-    frame_offset += buffer_size;
-  }
-
-  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), 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;
-  if (pStrideInPixels) {
-    *pStrideInPixels = stride_in_pixels;
-  }
-
-  return 0;
-}
-
-static int gralloc_alloc_sf_framebuffer(alloc_device_t* dev,
-                                        buffer_handle_t* pHandle,
-                                        int* pStrideInPixels) {
-  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 <<= 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) {
-  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);
-}
-
-/*****************************************************************************/
-
-static int gralloc_alloc(
-    alloc_device_t* dev, int w, int h, int format, int usage,
-    buffer_handle_t* pHandle, int* pStrideInPixels) {
+static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
+                         int /*usage*/, buffer_handle_t* pHandle,
+                         int* pStrideInPixels) {
   if (!pHandle || !pStrideInPixels)
     return -EINVAL;
 
-  int err;
-  if (usage & GRALLOC_USAGE_HW_FB) {
-    err = gralloc_alloc_sf_framebuffer(dev, pHandle, pStrideInPixels);
-  } else {
-    err = gralloc_alloc_buffer(dev, format, w, h, pHandle, pStrideInPixels);
-  }
+  int err = gralloc_alloc_buffer(dev, format, w, h, pHandle, pStrideInPixels);
 
   if (err < 0) {
     return err;
@@ -227,15 +120,9 @@
     return -EINVAL;
   }
 
-  int retval = 0;
-
   private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(
     handle);
-  if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
-    retval = gralloc_free_framebuffer(hnd);
-  } else {
-    retval = unreference_region(__FUNCTION__, hnd);
-  }
+  int retval = unreference_region(__FUNCTION__, hnd);
 
   close(hnd->fd);
   delete hnd;
@@ -274,8 +161,6 @@
 
     dev->device.alloc   = gralloc_alloc;
     dev->device.free    = gralloc_free;
-    dev->alloc_hwc_framebuffer = gralloc_alloc_hwc_framebuffer;
-
 
     *device = &dev->device.common;
     status = 0;
@@ -317,6 +202,4 @@
     VSOC_STATIC_INITIALIZER(lock_ycbcr) gralloc_lock_ycbcr,
 #endif
   },
-  VSOC_STATIC_INITIALIZER(framebuffer) 0,
-  VSOC_STATIC_INITIALIZER(lock) PTHREAD_MUTEX_INITIALIZER,
 };
diff --git a/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
index 67ed0ad..816ebc8 100644
--- a/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
+++ b/guest/hals/gralloc/legacy/gralloc_vsoc_priv.h
@@ -51,29 +51,17 @@
 
 struct private_module_t {
   gralloc_module_t base;
-
-  private_handle_t* framebuffer;
-  pthread_mutex_t lock;
 };
 
-int initUserspaceFrameBuffer(struct private_module_t* module);
-
 /*****************************************************************************/
 
 struct priv_alloc_device_t {
   alloc_device_t  device;
-  // Creates handles for the hwcomposer-specific framebuffers
-  int (*alloc_hwc_framebuffer)(alloc_device_t* m,
-                                buffer_handle_t* handle);
 };
 
 /*****************************************************************************/
 
 struct private_handle_t : public native_handle {
-  enum {
-    PRIV_FLAGS_FRAMEBUFFER = 0x00000001
-  };
-
   // file-descriptors
   int     fd;
   // ints
@@ -307,28 +295,6 @@
   }
 }
 
-// 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 OffsetFromHandle(buffer_handle_t buffer_hnd) {
-    if (!buffer_hnd) {
-    ALOGE("Attempt to post null buffer");
-    return -1;
-  }
-  if (private_handle_t::validate(buffer_hnd) < 0) {
-    ALOGE("Attempt to post non-vsoc handle");
-    return -1;
-  }
-  const private_handle_t* hnd =
-      reinterpret_cast<private_handle_t const*>(buffer_hnd);
-  if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
-    ALOGE("Attempt to post non-framebuffer");
-    return -1;
-  }
-
-  return hnd->frame_offset;
-}
-
 int fb_device_open(
     const hw_module_t* module, const char* name, hw_device_t** device);
 
diff --git a/guest/hals/gralloc/legacy/region_registry.cpp b/guest/hals/gralloc/legacy/region_registry.cpp
index 5207fff..dd5fafa 100644
--- a/guest/hals/gralloc/legacy/region_registry.cpp
+++ b/guest/hals/gralloc/legacy/region_registry.cpp
@@ -126,14 +126,12 @@
       unlock_region(region);
       return NULL;
     }
-    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
-      // Set up the guard pages. The last page is always a guard
-      uintptr_t base = uintptr_t(mappedAddress);
-      uintptr_t addr = base + hnd->total_size - PAGE_SIZE;
-      if (mprotect((void*)addr, PAGE_SIZE, PROT_NONE) == -1) {
-        ALOGE("mprotect base=%p, pg=%p failed (%s)",
-              (void*)base, (void*)addr, strerror(errno));
-      }
+    // Set up the guard pages. The last page is always a guard
+    uintptr_t base = uintptr_t(mappedAddress);
+    uintptr_t addr = base + hnd->total_size - PAGE_SIZE;
+    if (mprotect((void*)addr, PAGE_SIZE, PROT_NONE) == -1) {
+      ALOGE("mprotect base=%p, pg=%p failed (%s)", (void*)base, (void*)addr,
+            strerror(errno));
     }
     region->base_ = mappedAddress;
     ALOGI("Mapped %s hnd=%p fd=%d base=%p format=%s(0x%x) width=%d height=%d",
diff --git a/guest/hals/hwcomposer/legacy/base_composer.cpp b/guest/hals/hwcomposer/legacy/base_composer.cpp
index ed50cf4..0f89a99 100644
--- a/guest/hals/hwcomposer/legacy/base_composer.cpp
+++ b/guest/hals/hwcomposer/legacy/base_composer.cpp
@@ -16,12 +16,17 @@
 
 #include "base_composer.h"
 
+#include <string.h>
+
 #include <cutils/log.h>
+#include <hardware/gralloc.h>
 
 #include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "common/vsoc/lib/framebuffer_region_view.h"
 #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
 
 using vsoc::framebuffer::FBBroadcastRegionView;
+using vsoc::framebuffer::FrameBufferRegionView;
 
 namespace cvd {
 
@@ -38,10 +43,14 @@
                            int32_t vsync_period_ns)
     : vsync_base_timestamp_(vsync_base_timestamp),
       vsync_period_ns_(vsync_period_ns),
+      frame_buffer_count_(
+          // TODO(jemoreira): Join this two regions and move the buffer count to
+          // the joined region
+          FrameBufferRegionView::GetInstance()->total_buffer_size() /
+          FBBroadcastRegionView::GetInstance()->buffer_size()),
       fb_broadcaster_(BroadcastFrameBufferChanged) {
-  const gralloc_module_t* gralloc_module;
   hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
-                reinterpret_cast<const hw_module_t**>(&gralloc_module));
+                reinterpret_cast<const hw_module_t**>(&gralloc_module_));
 }
 
 BaseComposer::~BaseComposer() {}
@@ -54,15 +63,30 @@
 
 void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
 
-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 offset;
+void BaseComposer::Broadcast(int32_t offset) {
+  fb_broadcaster_(offset);
 }
 
+int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
+  int32_t fb_offset = NextFrameBufferOffset();
+  auto fb_region = FrameBufferRegionView::GetInstance();
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  void* frame_buffer = fb_region->GetBufferFromOffset(fb_offset);
+  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, fb_broadcast->buffer_size());
+  fb_broadcaster_(fb_offset);
+  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++) {
@@ -74,13 +98,21 @@
   return 0;
 }
 
-int32_t BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+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 PostFrameBuffer(layers[idx].handle);
+      return PostFrameBufferTarget(layers[idx].handle);
     }
   }
   return -1;
 }
 
+uint32_t BaseComposer::NextFrameBufferOffset() {
+  last_frame_buffer_ = (last_frame_buffer_ + 1) % frame_buffer_count_;
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  auto fb_region = FrameBufferRegionView::GetInstance();
+  return fb_region->first_buffer_offset() +
+         last_frame_buffer_ * fb_broadcast->buffer_size();
+}
+
 }  // namespace cvd
diff --git a/guest/hals/hwcomposer/legacy/base_composer.h b/guest/hals/hwcomposer/legacy/base_composer.h
index 3577da3..2f789ac 100644
--- a/guest/hals/hwcomposer/legacy/base_composer.h
+++ b/guest/hals/hwcomposer/legacy/base_composer.h
@@ -15,12 +15,14 @@
  * limitations under the License.
  */
 
+#include <functional>
+
 #include <hardware/gralloc.h>
 #include "hwcomposer_common.h"
 
 namespace cvd {
 
-using FbBroadcaster = void (*)(int);
+using FbBroadcaster = std::function<void(int32_t)>;
 
 class BaseComposer {
  public:
@@ -30,11 +32,8 @@
   // 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 offset that was broadcasted or a negative number if there was
-  // an error.
-  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);
+  // 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
@@ -43,10 +42,18 @@
   void Dump(char* buff, int buff_len);
 
  protected:
+  void Broadcast(int32_t offset);
+  uint32_t NextFrameBufferOffset();
+
+  const gralloc_module_t* gralloc_module_;
   int64_t vsync_base_timestamp_;
   int32_t vsync_period_ns_;
+  int frame_buffer_count_;
+  int last_frame_buffer_ = -1; // The first index whill be 0
 
  private:
+  // Returns buffer offset or negative on error.
+  int PostFrameBufferTarget(buffer_handle_t handle);
   FbBroadcaster fb_broadcaster_;
 };
 
diff --git a/guest/hals/hwcomposer/legacy/hwcomposer.cpp b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
index 693496d..5521907 100644
--- a/guest/hals/hwcomposer/legacy/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
@@ -101,9 +101,8 @@
 #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) {
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
-      list->numHwLayers, &list->hwLayers[0]);
-  return 0;
+  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,
@@ -114,8 +113,9 @@
   if (!contents) return 0;
 
   vsoc_hwc_layer* layers = &contents->hwLayers[0];
-  reinterpret_cast<vsoc_hwc_composer_device_1_t*>(dev)->composer->SetLayers(
-      contents->numHwLayers, layers);
+  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) {
@@ -132,7 +132,7 @@
   // 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 0;
+  return retval;
 }
 #endif
 
diff --git a/guest/hals/hwcomposer/legacy/stats_keeper.h b/guest/hals/hwcomposer/legacy/stats_keeper.h
index 397728a..47d4a13 100644
--- a/guest/hals/hwcomposer/legacy/stats_keeper.h
+++ b/guest/hals/hwcomposer/legacy/stats_keeper.h
@@ -157,7 +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(nullptr);
+    composer_.ReplaceFbBroadcaster([this](int32_t offset){
+        BroadcastWithStats(offset);
+      });
   }
   ~StatsKeepingComposer() = default;
 
@@ -168,19 +170,17 @@
     return num_hwc_layers;
   }
 
-  int32_t SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
-    vsoc::layout::framebuffer::CompositionStats stats;
-    stats_keeper_.RecordSetStart();
-    int32_t offset = composer_.SetLayers(num_layers, layers);
+  void BroadcastWithStats(int32_t offset) {
     stats_keeper_.RecordSetEnd();
-    if (offset >= 0) {
-      stats_keeper_.GetLastCompositionStats(&stats);
-      vsoc::framebuffer::FBBroadcastRegionView::GetInstance()
-          ->BroadcastNewFrame(static_cast<uint32_t>(offset), &stats);
-    } else {
-      ALOGE("%s: Error on SetLayers(), offset: %d", __FUNCTION__, offset);
-    }
-    return offset;
+    vsoc::layout::framebuffer::CompositionStats stats;
+    stats_keeper_.GetLastCompositionStats(&stats);
+    vsoc::framebuffer::FBBroadcastRegionView::GetInstance()
+      ->BroadcastNewFrame(static_cast<uint32_t>(offset), &stats);
+  }
+
+  int SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+    stats_keeper_.RecordSetStart();
+    return composer_.SetLayers(num_layers, layers);
   }
 
   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 e12c7a6..18a6dc2 100644
--- a/guest/hals/hwcomposer/legacy/vsoc_composer.cpp
+++ b/guest/hals/hwcomposer/legacy/vsoc_composer.cpp
@@ -28,11 +28,13 @@
 #include <system/graphics.h>
 
 #include "common/vsoc/lib/fb_bcast_region_view.h"
+#include "common/vsoc/lib/framebuffer_region_view.h"
 
 #include "geometry_utils.h"
 #include "hwcomposer_common.h"
 
 using vsoc::framebuffer::FBBroadcastRegionView;
+using vsoc::framebuffer::FrameBufferRegionView;
 
 namespace cvd {
 
@@ -339,45 +341,16 @@
 
 }  // namespace
 
-// Returns a handle to the appropriate framebuffer to use:
-// - the one provided by surfaceflinger if it is doing any GLES composition
-// - the next hwc-only framebuffer otherwise
-// Takes care of rotating the hwc-only framebuffers
-buffer_handle_t VSoCComposer::FindFrameBuffer(int num_layers,
-                                              vsoc_hwc_layer* layers) {
-  buffer_handle_t* fb_handle = NULL;
-  bool use_hwc_fb = true;
-  // The framebuffer target is usually the last layer in the list, so iterate in
-  // reverse
-  for (int idx = num_layers - 1; idx >= 0; --idx) {
-    if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
-      fb_handle = &layers[idx].handle;
-    } else if (layers[idx].compositionType != HWC_OVERLAY) {
-      use_hwc_fb = false;
-      // Just in case the FB target was not found yet
-      if (fb_handle) break;
-    }
-  }
-  if (use_hwc_fb && !hwc_framebuffers_.empty()) {
-    fb_handle = &hwc_framebuffers_[next_hwc_framebuffer_];
-    next_hwc_framebuffer_ =
-        (next_hwc_framebuffer_ + 1) % hwc_framebuffers_.size();
-  }
-
-  return *fb_handle;
-}
-
 void VSoCComposer::CompositeLayer(vsoc_hwc_layer* src_layer,
-                                  buffer_handle_t dst_handle) {
+                                  int32_t fb_offset) {
   libyuv::RotationMode rotation =
       GetRotationFromTransform(src_layer->transform);
 
   const private_handle_t* src_priv_handle =
       reinterpret_cast<const private_handle_t*>(src_layer->handle);
-  const private_handle_t* dst_priv_handle =
-      reinterpret_cast<const private_handle_t*>(dst_handle);
 
-  bool needs_conversion = src_priv_handle->format != dst_priv_handle->format;
+  // 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;
@@ -388,7 +361,8 @@
                       needs_vflip || needs_attenuation || needs_blending);
 
   uint8_t* src_buffer;
-  uint8_t* dst_buffer;
+  uint8_t* dst_buffer = reinterpret_cast<uint8_t*>(
+      FrameBufferRegionView::GetInstance()->GetBufferFromOffset(fb_offset));
   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,
@@ -397,10 +371,6 @@
     ALOGE("Got error code %d from lock function", retval);
     return;
   }
-  retval = gralloc_module_->lock(gralloc_module_, dst_handle,
-                                 GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0,
-                                 dst_priv_handle->x_res, dst_priv_handle->y_res,
-                                 reinterpret_cast<void**>(&dst_buffer));
   if (retval) {
     ALOGE("Got error code %d from lock function", retval);
     // TODO(jemoreira): Use a lock_guard-like object.
@@ -420,17 +390,18 @@
       src_layer->sourceCrop.bottom - src_layer->sourceCrop.top;
   src_layer_spec.format = src_priv_handle->format;
 
-  BufferSpec dst_layer_spec(dst_buffer, dst_priv_handle->total_size,
-                            dst_priv_handle->x_res, dst_priv_handle->y_res,
-                            dst_priv_handle->stride_in_pixels *
-                                formatToBytesPerPixel(dst_priv_handle->format));
+  auto fb_broadcast = FBBroadcastRegionView::GetInstance();
+  BufferSpec dst_layer_spec(dst_buffer, fb_broadcast->buffer_size(),
+                            fb_broadcast->x_res(), fb_broadcast->y_res(),
+                            fb_broadcast->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;
-  dst_layer_spec.format = dst_priv_handle->format;
+  // 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);
@@ -450,16 +421,13 @@
   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 * y_res * formatToBytesPerPixel(dst_priv_handle->format);
+      x_res *
+    FBBroadcastRegionView::align(y_res * fb_broadcast->bytes_per_pixel(), 16);
   while (needed_tmp_buffers > 0) {
-    BufferSpec tmp(
-        RotateTmpBuffer(needed_tmp_buffers), output_frame_size, x_res, y_res,
-        // There should be no danger of overflow aligning the stride because
-        // 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.
-        FBBroadcastRegionView::align(
-            x_res * formatToBytesPerPixel(dst_priv_handle->format), 16));
+    BufferSpec tmp(RotateTmpBuffer(needed_tmp_buffers), output_frame_size,
+                   x_res, y_res,
+                   FBBroadcastRegionView::align(
+                       x_res * fb_broadcast->bytes_per_pixel(), 16));
     dest_buffer_stack.push_back(tmp);
     needed_tmp_buffers--;
   }
@@ -481,7 +449,7 @@
       int src_width = src_layer_spec.crop_width;
       int src_height = src_layer_spec.crop_height;
       int dst_stride = FBBroadcastRegionView::align(
-          src_width * formatToBytesPerPixel(dst_priv_handle->format), 16);
+          src_width * fb_broadcast->bytes_per_pixel(), 16);
       size_t needed_size = dst_stride * src_height;
       dst_buffer_spec.width = src_width;
       dst_buffer_spec.height = src_height;
@@ -520,8 +488,8 @@
       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 *
-                               formatToBytesPerPixel(dst_priv_handle->format);
+      dst_buffer_spec.stride =
+          dst_buffer_spec.width * fb_broadcast->bytes_per_pixel();
     }
     retval = DoScaling(src_layer_spec, dst_buffer_spec, needs_vflip);
     needs_vflip = false;
@@ -577,7 +545,6 @@
   }
 
   gralloc_module_->unlock(gralloc_module_, src_priv_handle);
-  gralloc_module_->unlock(gralloc_module_, dst_priv_handle);
 }
 
 /* static */ const int VSoCComposer::kNumTmpBufferPieces = 2;
@@ -586,32 +553,9 @@
                            int32_t vsync_period_ns)
     : BaseComposer(vsync_base_timestamp, vsync_period_ns),
       tmp_buffer_(kNumTmpBufferPieces *
-                  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_));
-  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);
-  }
-}
+                  FBBroadcastRegionView::GetInstance()->buffer_size()) {}
 
-VSoCComposer::~VSoCComposer() {
-  // Free the hwc fb handles
-  for (auto buffer : hwc_framebuffers_) {
-    gralloc_dev_->device.free(reinterpret_cast<alloc_device_t*>(gralloc_dev_),
-                              buffer);
-  }
-
-  // close devices
-  gralloc_dev_->device.common.close(
-      reinterpret_cast<hw_device_t*>(gralloc_dev_));
-}
+VSoCComposer::~VSoCComposer() {}
 
 int VSoCComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
   int composited_layers_count = 0;
@@ -655,34 +599,58 @@
   return composited_layers_count;
 }
 
-int32_t VSoCComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
+int 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) {
-    ALOGE("%s: framebuffer handle is null", __FUNCTION__);
-    return -1;
+  int32_t fb_offset = NextFrameBufferOffset();
+
+  // 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 compose_fb_target = true;
+  for (size_t idx = 0; idx < num_layers; idx++) {
+    if (layers[idx].compositionType == HWC_FRAMEBUFFER) {
+      // At least one was found
+      compose_fb_target = true;
+      break;
+    }
+    if (layers[idx].compositionType == HWC_OVERLAY) {
+      // Not the only layer in the composition
+      compose_fb_target = false;
+    }
   }
-  // TODO(jemoreira): Lock all HWC_OVERLAY layers and the framebuffer before
-  // this loop and unlock them after. The way it's done now causes the target
-  // framebuffer to be locked and unlocked many times, if regions are
-  // implemented it will also be true for every layer that covers more than one
-  // region.
+
+  // When the framebuffer target needs to be composed, it has to be go first.
+  if (compose_fb_target) {
+    for (size_t idx = 0; idx < num_layers; idx++) {
+      if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
+        if (SanityCheckLayer(layers[idx]) != 0) {
+          ALOGE("FRAMEBUFFER_TARGET layer (%zu), failed sanity check", idx);
+          return -EINVAL;
+        }
+        CompositeLayer(&layers[idx], fb_offset);
+        break;
+      }
+    }
+  }
+
   for (size_t idx = 0; idx < num_layers; idx++) {
     if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
       ++targetFbs;
-    } else if (layers[idx].compositionType == HWC_OVERLAY &&
-               !(layers[idx].flags & HWC_SKIP_LAYER)) {
-      if (SanityCheckLayer(layers[idx])) {
-        ALOGE("Layer (%zu) failed sanity check", idx);
-        return -EINVAL;
+    }
+    if (layers[idx].compositionType == HWC_OVERLAY &&
+        !(layers[idx].flags & HWC_SKIP_LAYER)) {
+      if (SanityCheckLayer(layers[idx]) != 0) {
+          ALOGE("Layer (%zu) failed sanity check", idx);
+          return -EINVAL;
       }
-      CompositeLayer(&layers[idx], fb_handle);
+      CompositeLayer(&layers[idx], fb_offset);
     }
   }
   if (targetFbs != 1) {
     ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
   }
-  return PostFrameBuffer(fb_handle);
+  Broadcast(fb_offset);
+  return 0;
 }
 
 uint8_t* VSoCComposer::RotateTmpBuffer(unsigned int order) {
diff --git a/guest/hals/hwcomposer/legacy/vsoc_composer.h b/guest/hals/hwcomposer/legacy/vsoc_composer.h
index 9abe06c..48f290f 100644
--- a/guest/hals/hwcomposer/legacy/vsoc_composer.h
+++ b/guest/hals/hwcomposer/legacy/vsoc_composer.h
@@ -34,20 +34,15 @@
   // override
   int PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers);
   // override
-  int32_t SetLayers(size_t num_layers, vsoc_hwc_layer* layers);
+  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);
-  buffer_handle_t FindFrameBuffer(int num_layers, vsoc_hwc_layer* layers);
-  void CompositeLayer(vsoc_hwc_layer* src_layer, buffer_handle_t dst_layer);
+  void CompositeLayer(vsoc_hwc_layer* src_layer, int32_t fb_offset);
   std::vector<uint8_t> tmp_buffer_;
   std::vector<uint8_t> special_tmp_buffer_;
-  const gralloc_module_t* gralloc_module_;
-  priv_alloc_device_t* gralloc_dev_;
-  std::vector<buffer_handle_t> hwc_framebuffers_;
-  int next_hwc_framebuffer_;
 };
 
 }  // namespace cvd
diff --git a/host/config/vsoc_mem.json b/host/config/vsoc_mem.json
index 36f03ce..667200f 100644
--- a/host/config/vsoc_mem.json
+++ b/host/config/vsoc_mem.json
@@ -91,7 +91,7 @@
      "managed_by" : "gralloc_manager",
      "current_version" : 0,
      "min_compatible_version" : 0,
-     "region_size" : 394850304,
+     "region_size" : 407142400,
 
      "guest_to_host_signal_table" : {
        "__comment" : "sizeof each node is based on common/libs/shm/lock.h",
@@ -106,10 +106,10 @@
 
    {
      "device_name" : "framebuffer",
-     "__comment" : "Holds the frame buffers. Size is enough to accomodate 6 buffers 800x1280 in RGBA format plus an extra page",
+     "__comment" : "Holds the frame buffers. Size is enough to accomodate 3 buffers 800x1280 in RGBA format, with 4 bytes of padding, plus an extra page",
      "current_version" : 0,
      "min_compatible_version" : 0,
-     "region_size" : 24584192,
+     "region_size" : 12292096,
 
      "guest_to_host_signal_table" : {
        "__comment" : "sizeof each node is based on common/libs/shm/lock.h",