Refactor VrFlinger to use BufferHubQueue

1/ Remove DisplayRPC::AllocateBuffer, as individual buffer allocation
is now handled by BufferHubQueue.
2/ Reimplement native_buffer_queue using bufferhubqueue.
3/ Hook up consumer queue in DisplaySurface.
4/ Remove epoll_event_dispatcher as its no longer being used.

Bug: 36033302
Test: Built and ran particles.apk
Change-Id: I38ee1c57195888ede935ebc50119bcb7e4ab4e36
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index d427ea6..66808ca 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,7 +26,7 @@
     : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
                      sizeof(DisplaySurfaceMetadata)),
       process_id_(process_id),
-      posted_buffers_(kMaxPostedBuffers),
+      acquired_buffers_(kMaxPostedBuffers),
       video_mesh_surfaces_updated_(false),
       width_(width),
       height_(height),
@@ -40,7 +40,6 @@
       manager_visible_(false),
       manager_z_order_(0),
       manager_blur_(0.0f),
-      allocated_buffer_index_(0),
       layer_order_(0) {}
 
 DisplaySurface::~DisplaySurface() {
@@ -84,71 +83,107 @@
   client_blur_behind_ = blur_behind;
 }
 
+void DisplaySurface::DequeueBuffersLocked() {
+  if (consumer_queue_ == nullptr) {
+    ALOGE(
+        "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+        "initialized.");
+    return;
+  }
+
+  size_t slot;
+  uint64_t sequence;
+  while (true) {
+    LocalHandle acquire_fence;
+    auto buffer_consumer =
+        consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
+    if (!buffer_consumer) {
+      ALOGD_IF(TRACE,
+               "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
+               "available buffers.");
+      return;
+    }
+
+    if (!IsVisible()) {
+      ATRACE_NAME("DropFrameOnInvisibleSurface");
+      ALOGD_IF(TRACE,
+               "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
+               "on invisible surface.",
+               buffer_consumer->id());
+      buffer_consumer->Discard();
+      continue;
+    }
+
+    if (acquired_buffers_.IsFull()) {
+      ALOGE(
+          "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+          "overwriting.");
+      acquired_buffers_.PopBack();
+    }
+
+    acquired_buffers_.Append(
+        AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+  }
+}
+
+AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+  std::lock_guard<std::mutex> autolock(lock_);
+  DequeueBuffersLocked();
+
+  if (acquired_buffers_.IsEmpty()) {
+    ALOGE(
+        "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
+        "none are posted.");
+    return AcquiredBuffer();
+  }
+  AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
+  acquired_buffers_.PopFront();
+  ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+           buffer.buffer().get());
+  return buffer;
+}
+
 AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
     AcquiredBuffer* skipped_buffer) {
   std::lock_guard<std::mutex> autolock(lock_);
+  DequeueBuffersLocked();
+
   AcquiredBuffer buffer;
   int frames = 0;
   // Basic latency stopgap for when the application misses a frame:
   // If the application recovers on the 2nd or 3rd (etc) frame after
   // missing, this code will skip frames to catch up by checking if
   // the next frame is also available.
-  while (!posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable()) {
+  while (!acquired_buffers_.IsEmpty() &&
+         acquired_buffers_.Front().IsAvailable()) {
     // Capture the skipped buffer into the result parameter.
     // Note that this API only supports skipping one buffer per vsync.
     if (frames > 0 && skipped_buffer)
       *skipped_buffer = std::move(buffer);
     ++frames;
-    buffer = std::move(posted_buffers_.Front());
-    posted_buffers_.PopFront();
+    buffer = std::move(acquired_buffers_.Front());
+    acquired_buffers_.PopFront();
     if (frames == 2)
       break;
   }
+  ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+           buffer.buffer().get());
   return buffer;
 }
 
-bool DisplaySurface::IsBufferAvailable() const {
+bool DisplaySurface::IsBufferAvailable() {
   std::lock_guard<std::mutex> autolock(lock_);
-  return !posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable();
+  DequeueBuffersLocked();
+
+  return !acquired_buffers_.IsEmpty() &&
+         acquired_buffers_.Front().IsAvailable();
 }
 
-bool DisplaySurface::IsBufferPosted() const {
+bool DisplaySurface::IsBufferPosted() {
   std::lock_guard<std::mutex> autolock(lock_);
-  return !posted_buffers_.IsEmpty();
-}
+  DequeueBuffersLocked();
 
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
-  std::lock_guard<std::mutex> autolock(lock_);
-  if (posted_buffers_.IsEmpty()) {
-    ALOGE("Error: attempt to acquire buffer when none are posted.");
-    return AcquiredBuffer();
-  }
-  AcquiredBuffer buffer = std::move(posted_buffers_.Front());
-  posted_buffers_.PopFront();
-  return buffer;
-}
-
-int DisplaySurface::GetConsumers(std::vector<LocalChannelHandle>* consumers) {
-  std::lock_guard<std::mutex> autolock(lock_);
-  std::vector<LocalChannelHandle> items;
-
-  for (auto pair : buffers_) {
-    const auto& buffer = pair.second;
-
-    Status<LocalChannelHandle> consumer_channel = buffer->CreateConsumer();
-    if (!consumer_channel) {
-      ALOGE(
-          "DisplaySurface::GetConsumers: Failed to get a new consumer for "
-          "buffer %d: %s",
-          buffer->id(), consumer_channel.GetErrorMessage().c_str());
-      return -consumer_channel.error();
-    }
-
-    items.push_back(consumer_channel.take());
-  }
-
-  *consumers = std::move(items);
-  return 0;
+  return !acquired_buffers_.IsEmpty();
 }
 
 int DisplaySurface::HandleMessage(pdx::Message& message) {
@@ -158,9 +193,9 @@
           *this, &DisplaySurface::OnClientSetAttributes, message);
       break;
 
-    case DisplayRPC::AllocateBuffer::Opcode:
-      DispatchRemoteMethod<DisplayRPC::AllocateBuffer>(
-          *this, &DisplaySurface::OnAllocateBuffer, message);
+    case DisplayRPC::CreateBufferQueue::Opcode:
+      DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
+          *this, &DisplaySurface::OnCreateBufferQueue, message);
       break;
 
     case DisplayRPC::CreateVideoMeshSurface::Opcode:
@@ -226,58 +261,20 @@
   return 0;
 }
 
-// Allocates a new buffer for the DisplaySurface associated with this channel.
-std::pair<uint32_t, LocalChannelHandle> DisplaySurface::OnAllocateBuffer(
-    pdx::Message& message) {
-  // Inject flag to enable framebuffer compression for the application buffers.
-  // TODO(eieio,jbates): Make this configurable per hardware platform.
-  const int usage = usage_ | GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
-  const int slice_count =
-      (flags_ & static_cast<int>(DisplaySurfaceFlagsEnum::SeparateGeometry))
-          ? 2
-          : 1;
+LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
+  ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
 
-  ALOGI_IF(
-      TRACE,
-      "DisplaySurface::OnAllocateBuffer: width=%d height=%d format=%x usage=%x "
-      "slice_count=%d",
-      width_, height_, format_, usage, slice_count);
-
-  // Create a producer buffer to hand back to the sender.
-  auto producer = BufferProducer::Create(width_, height_, format_, usage,
-                                         sizeof(uint64_t), slice_count);
-  if (!producer)
-    REPLY_ERROR_RETURN(message, EINVAL, {});
-
-  // Create and import a consumer attached to the producer.
-  Status<LocalChannelHandle> consumer_channel = producer->CreateConsumer();
-  if (!consumer_channel)
-    REPLY_ERROR_RETURN(message, consumer_channel.error(), {});
-
-  std::shared_ptr<BufferConsumer> consumer =
-      BufferConsumer::Import(consumer_channel.take());
-  if (!consumer)
-    REPLY_ERROR_RETURN(message, ENOMEM, {});
-
-  // Add the consumer to this surface.
-  int err = AddConsumer(consumer);
-  if (err < 0) {
-    ALOGE("DisplaySurface::OnAllocateBuffer: failed to add consumer: buffer=%d",
-          consumer->id());
-    REPLY_ERROR_RETURN(message, -err, {});
+  if (consumer_queue_ != nullptr) {
+    ALOGE(
+        "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
+        "created and transported to DisplayClient.");
+    REPLY_ERROR_RETURN(message, EALREADY, {});
   }
 
-  // Move the channel handle so that it doesn't get closed when the producer
-  // goes out of scope.
-  std::pair<uint32_t, LocalChannelHandle> return_value(
-      allocated_buffer_index_, std::move(producer->GetChannelHandle()));
+  auto producer = ProducerQueue::Create<uint64_t>();
+  consumer_queue_ = producer->CreateConsumerQueue();
 
-  // Save buffer index, associated with the buffer id so that it can be looked
-  // up later.
-  buffer_id_to_index_[consumer->id()] = allocated_buffer_index_;
-  ++allocated_buffer_index_;
-
-  return return_value;
+  return std::move(producer->GetChannelHandle());
 }
 
 RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
@@ -319,103 +316,6 @@
   return status.take();
 }
 
-int DisplaySurface::AddConsumer(
-    const std::shared_ptr<BufferConsumer>& consumer) {
-  ALOGD_IF(TRACE, "DisplaySurface::AddConsumer: buffer_id=%d", consumer->id());
-  // Add the consumer to the epoll dispatcher, edge-triggered.
-  int err = service()->dispatcher_.AddEventHandler(
-      consumer->event_fd(), EPOLLET | EPOLLIN | EPOLLHUP,
-      std::bind(&DisplaySurface::HandleConsumerEvents,
-                std::static_pointer_cast<DisplaySurface>(shared_from_this()),
-                consumer, std::placeholders::_1));
-  if (err) {
-    ALOGE(
-        "DisplaySurface::AddConsumer: failed to add epoll event handler for "
-        "consumer: %s",
-        strerror(-err));
-    return err;
-  }
-
-  // Add the consumer to the list of buffers for this surface.
-  std::lock_guard<std::mutex> autolock(lock_);
-  buffers_.insert(std::make_pair(consumer->id(), consumer));
-  return 0;
-}
-
-void DisplaySurface::RemoveConsumer(
-    const std::shared_ptr<BufferConsumer>& consumer) {
-  ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumer: buffer_id=%d",
-           consumer->id());
-  service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
-
-  std::lock_guard<std::mutex> autolock(lock_);
-  buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::RemoveConsumerUnlocked(
-    const std::shared_ptr<BufferConsumer>& consumer) {
-  ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumerUnlocked: buffer_id=%d",
-           consumer->id());
-  service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
-  buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::OnPostConsumer(
-    const std::shared_ptr<BufferConsumer>& consumer) {
-  ATRACE_NAME("DisplaySurface::OnPostConsumer");
-  std::lock_guard<std::mutex> autolock(lock_);
-
-  if (!IsVisible()) {
-    ALOGD_IF(TRACE,
-             "DisplaySurface::OnPostConsumer: Discarding buffer_id=%d on "
-             "invisible surface.",
-             consumer->id());
-    consumer->Discard();
-    return;
-  }
-
-  if (posted_buffers_.IsFull()) {
-    ALOGE("Error: posted buffers full, overwriting");
-    posted_buffers_.PopBack();
-  }
-
-  int error;
-  posted_buffers_.Append(AcquiredBuffer(consumer, &error));
-
-  // Remove the consumer if the other end was closed.
-  if (posted_buffers_.Back().IsEmpty() && error == -EPIPE)
-    RemoveConsumerUnlocked(consumer);
-}
-
-void DisplaySurface::HandleConsumerEvents(
-    const std::shared_ptr<BufferConsumer>& consumer, int events) {
-  auto status = consumer->GetEventMask(events);
-  if (!status) {
-    ALOGW(
-        "DisplaySurface::HandleConsumerEvents: Failed to get event mask for "
-        "consumer: %s",
-        status.GetErrorMessage().c_str());
-    return;
-  }
-
-  events = status.get();
-  if (events & EPOLLHUP) {
-    ALOGD_IF(TRACE,
-             "DisplaySurface::HandleConsumerEvents: removing event handler for "
-             "buffer=%d",
-             consumer->id());
-    RemoveConsumer(consumer);
-  } else if (events & EPOLLIN) {
-    // BufferHub uses EPOLLIN to signal consumer ownership.
-    ALOGD_IF(TRACE,
-             "DisplaySurface::HandleConsumerEvents: posting buffer=%d for "
-             "process=%d",
-             consumer->id(), process_id_);
-
-    OnPostConsumer(consumer);
-  }
-}
-
 std::vector<std::shared_ptr<VideoMeshSurface>>
 DisplaySurface::GetVideoMeshSurfaces() {
   std::lock_guard<std::mutex> autolock(lock_);