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/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 54098e8..dcdd994 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -148,18 +148,22 @@
   }
 }
 
-std::shared_ptr<BufferProducer> DisplaySurfaceClient::AllocateBuffer(
-    uint32_t* buffer_index) {
-  auto status = InvokeRemoteMethod<DisplayRPC::AllocateBuffer>();
-  if (!status) {
-    ALOGE("DisplaySurfaceClient::AllocateBuffer: Failed to allocate buffer: %s",
+std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
+  if (producer_queue_ == nullptr) {
+    // Create producer queue through DisplayRPC
+    auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
+    if (!status) {
+      ALOGE(
+          "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
+          "queue: %s",
           status.GetErrorMessage().c_str());
-    return nullptr;
-  }
+      return nullptr;
+    }
 
-  if (buffer_index)
-    *buffer_index = status.get().first;
-  return BufferProducer::Import(status.take().second);
+    producer_queue_ =
+        ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+  }
+  return producer_queue_;
 }
 
 volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 034b7b4..e1471c3 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -5,6 +5,7 @@
 #include <pdx/client.h>
 #include <pdx/file_handle.h>
 #include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
 #include <private/dvr/display_rpc.h>
 
 namespace android {
@@ -62,13 +63,9 @@
   void SetBlurBehind(bool blur_behind);
   void SetAttributes(const DisplaySurfaceAttributes& attributes);
 
-  // |out_buffer_index| will receive a unique index for this buffer within the
-  // surface. The first buffer gets 0, second gets 1, and so on. This index
-  // can be used to deliver metadata for buffers that are queued for display.
-  std::shared_ptr<BufferProducer> AllocateBuffer(uint32_t* out_buffer_index);
-  std::shared_ptr<BufferProducer> AllocateBuffer() {
-    return AllocateBuffer(nullptr);
-  }
+  // Get the producer end of the buffer queue that transports graphics buffer
+  // from the application side to the compositor side.
+  std::shared_ptr<ProducerQueue> GetProducerQueue();
 
   // Get the shared memory metadata buffer for this display surface. If it is
   // not yet allocated, this will allocate it.
@@ -93,6 +90,9 @@
   bool blur_behind_;
   DisplaySurfaceMetadata* mapped_metadata_buffer_;
 
+  // TODO(jwcai) Add support for multiple queues.
+  std::shared_ptr<ProducerQueue> producer_queue_;
+
   DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
   void operator=(const DisplaySurfaceClient&) = delete;
 };
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index d37aed7..465fbae 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -212,7 +212,7 @@
     kOpGetMetrics = 0,
     kOpGetEdsCapture,
     kOpCreateSurface,
-    kOpAllocateBuffer,
+    kOpCreateBufferQueue,
     kOpSetAttributes,
     kOpGetMetadataBuffer,
     kOpCreateVideoMeshSurface,
@@ -233,8 +233,8 @@
   PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
                     int(int width, int height, int format, int usage,
                         DisplaySurfaceFlags flags));
-  PDX_REMOTE_METHOD(AllocateBuffer, kOpAllocateBuffer,
-                    std::pair<std::uint32_t, LocalChannelHandle>(Void));
+  PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
+                    LocalChannelHandle(Void));
   PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
                     int(const DisplaySurfaceAttributes& attributes));
   PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 87e9c9f..4b1fa98 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -14,57 +14,27 @@
 namespace android {
 namespace dvr {
 
-// NativeBufferQueue manages a queue of NativeBufferProducers allocated from a
-// DisplaySurfaceClient. Buffers are automatically re-enqueued when released by
-// the consumer side.
+// A wrapper over dvr::ProducerQueue that caches EGLImage.
 class NativeBufferQueue {
  public:
   // Create a queue with the given number of free buffers.
-  NativeBufferQueue(const std::shared_ptr<DisplaySurfaceClient>& surface,
-                    size_t capacity);
   NativeBufferQueue(EGLDisplay display,
                     const std::shared_ptr<DisplaySurfaceClient>& surface,
                     size_t capacity);
-  ~NativeBufferQueue();
 
-  std::shared_ptr<DisplaySurfaceClient> surface() const { return surface_; }
+  size_t GetQueueCapacity() const { return producer_queue_->capacity(); }
 
   // Dequeue a buffer from the free queue, blocking until one is available.
   NativeBufferProducer* Dequeue();
 
-  // Enqueue a buffer at the end of the free queue.
-  void Enqueue(NativeBufferProducer* buf);
-
-  // Get the number of free buffers in the queue.
-  size_t GetFreeBufferCount() const;
-
-  // Get the total number of buffers managed by this queue.
-  size_t GetQueueCapacity() const;
-
-  // Accessors for display surface buffer attributes.
-  int width() const { return surface_->width(); }
-  int height() const { return surface_->height(); }
-  int format() const { return surface_->format(); }
-  int usage() const { return surface_->usage(); }
+  // An noop here to keep Vulkan path in GraphicsContext happy.
+  // TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
+  void Enqueue(NativeBufferProducer* buffer) {}
 
  private:
-  // Wait for buffers to be released and enqueue them.
-  bool WaitForBuffers();
-
-  std::shared_ptr<DisplaySurfaceClient> surface_;
-
-  // A list of strong pointers to the buffers, used for managing buffer
-  // lifetime.
-  std::vector<android::sp<NativeBufferProducer>> buffers_;
-
-  // Used to implement queue semantics.
-  RingBuffer<NativeBufferProducer*> buffer_queue_;
-
-  // Epoll fd used to wait for BufferHub events.
-  int epoll_fd_;
-
-  NativeBufferQueue(const NativeBufferQueue&) = delete;
-  void operator=(NativeBufferQueue&) = delete;
+  EGLDisplay display_;
+  std::shared_ptr<ProducerQueue> producer_queue_;
+  std::vector<sp<NativeBufferProducer>> buffers_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
index e52d0b9..3a7f125 100644
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
@@ -25,7 +25,7 @@
  private:
   friend BASE;
 
-  std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+  std::shared_ptr<ProducerQueue> producer_queue_;
   VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
 
   explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index 8dd0ee0..d516d63 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -13,138 +13,51 @@
 namespace dvr {
 
 NativeBufferQueue::NativeBufferQueue(
-    const std::shared_ptr<DisplaySurfaceClient>& surface, size_t capacity)
-    : NativeBufferQueue(nullptr, surface, capacity) {}
-
-NativeBufferQueue::NativeBufferQueue(
     EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
     size_t capacity)
-    : surface_(surface),
-      buffers_(capacity),
-      buffer_queue_(capacity) {
-  LOG_ALWAYS_FATAL_IF(!surface);
-
-  epoll_fd_ = epoll_create(64);
-  if (epoll_fd_ < 0) {
-    ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to create epoll fd: %s",
-          strerror(errno));
-    return;
-  }
-
-  // The kSurfaceBufferMaxCount must be >= the capacity so that shader code
-  // can bind surface buffer array data.
-  LOG_ALWAYS_FATAL_IF(kSurfaceBufferMaxCount < capacity);
+    : display_(display), buffers_(capacity) {
+  std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
 
   for (size_t i = 0; i < capacity; i++) {
-    uint32_t buffer_index = 0;
-    auto buffer = surface_->AllocateBuffer(&buffer_index);
-    if (!buffer) {
-      ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer!");
-      return;
-    }
-
-    // TODO(jbates): store an index associated with each buffer so that we can
-    // determine which index in DisplaySurfaceMetadata it is associated
-    // with.
-    buffers_.push_back(new NativeBufferProducer(buffer, display, buffer_index));
-    NativeBufferProducer* native_buffer = buffers_.back().get();
-
-    epoll_event event = {.events = EPOLLIN | EPOLLET,
-                         .data = {.ptr = native_buffer}};
-    if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, buffer->event_fd(), &event) <
-        0) {
+    size_t slot;
+    // TODO(jwcai) Should change to use BufferViewPort's spec to config.
+    int ret =
+        queue->AllocateBuffer(surface->width(), surface->height(),
+                              surface->format(), surface->usage(), 1, &slot);
+    if (ret < 0) {
       ALOGE(
-          "NativeBufferQueue::NativeBufferQueue: Failed to add buffer producer "
-          "to epoll set: %s",
-          strerror(errno));
+          "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
+          "error=%d",
+          ret);
       return;
     }
 
-    Enqueue(native_buffer);
-  }
-}
-
-NativeBufferQueue::~NativeBufferQueue() {
-  if (epoll_fd_ >= 0)
-    close(epoll_fd_);
-}
-
-bool NativeBufferQueue::WaitForBuffers() {
-  ATRACE_NAME("NativeBufferQueue::WaitForBuffers");
-  // Intentionally set this to one so that we don't waste time retrieving too
-  // many buffers.
-  constexpr size_t kMaxEvents = 1;
-  std::array<epoll_event, kMaxEvents> events;
-
-  while (buffer_queue_.IsEmpty()) {
-    int num_events = epoll_wait(epoll_fd_, events.data(), events.size(), -1);
-    if (num_events < 0 && errno != EINTR) {
-      ALOGE("NativeBufferQueue:WaitForBuffers: Failed to wait for buffers: %s",
-            strerror(errno));
-      return false;
-    }
-
-    ALOGD_IF(TRACE, "NativeBufferQueue::WaitForBuffers: num_events=%d",
-             num_events);
-
-    for (int i = 0; i < num_events; i++) {
-      NativeBufferProducer* buffer =
-          static_cast<NativeBufferProducer*>(events[i].data.ptr);
-      ALOGD_IF(TRACE,
-               "NativeBufferQueue::WaitForBuffers: event %d: buffer_id=%d "
-               "events=0x%x",
-               i, buffer->buffer()->id(), events[i].events);
-
-      if (events[i].events & EPOLLIN) {
-        const int ret = buffer->GainAsync();
-        if (ret < 0) {
-          ALOGE("NativeBufferQueue::WaitForBuffers: Failed to gain buffer: %s",
-                strerror(-ret));
-          continue;
-        }
-
-        Enqueue(buffer);
-      }
-    }
+    ALOGD_IF(TRACE,
+             "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
+             "slot=%zu",
+             slot);
   }
 
-  return true;
-}
-
-void NativeBufferQueue::Enqueue(NativeBufferProducer* buf) {
-  ATRACE_NAME("NativeBufferQueue::Enqueue");
-  if (buffer_queue_.IsFull()) {
-    ALOGE("NativeBufferQueue::Enqueue: Queue is full!");
-    return;
-  }
-
-  buffer_queue_.Append(buf);
+  producer_queue_ = std::move(queue);
 }
 
 NativeBufferProducer* NativeBufferQueue::Dequeue() {
   ATRACE_NAME("NativeBufferQueue::Dequeue");
-  ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: count=%zd",
-           buffer_queue_.GetSize());
 
-  if (buffer_queue_.IsEmpty() && !WaitForBuffers())
-    return nullptr;
+  // This never times out.
+  size_t slot;
+  pdx::LocalHandle fence;
+  std::shared_ptr<BufferProducer> buffer =
+      producer_queue_->Dequeue(-1, &slot, &fence);
 
-  NativeBufferProducer* buf = buffer_queue_.Front();
-  buffer_queue_.PopFront();
-  if (buf == nullptr) {
-    ALOGE("NativeBufferQueue::Dequeue: Buffer at tail was nullptr!!!");
-    return nullptr;
+  if (buffers_[slot] == nullptr) {
+    buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
   }
 
-  return buf;
-}
-
-size_t NativeBufferQueue::GetFreeBufferCount() const {
-  return buffer_queue_.GetSize();
-}
-
-size_t NativeBufferQueue::GetQueueCapacity() const {
-  return buffer_queue_.GetCapacity();
+  ALOGD_IF(TRACE,
+           "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
+           slot, buffers_[slot].get());
+  return buffers_[slot].get();
 }
 
 }  // namespace dvr