Add shared memory based buffer metadata

This CLs reduces BufferHub CPU consumption by adding asynchronous
state transition so that out-of-process VR composition can run on 2016
pixel devices smoothly. In addition, this CL addresses a couple corner
cases in the existing bufferhub logic, which fixes various blackscreen
issues.

1/ Tracks buffer transition states (gained, posted, acquired, released)
   from the client side via atomic shared memory and adds
   PostAsync/AcquireAsync/ReleaseAsync/GainAsync with metadata  and
   fence support.
2/ Adds dequeue order guarantee for buffers enqueued with
   dvrWriteBufferQueuePostBuffer.
3/ Synchronous BuffeHub operations are still supported.
4/ Bump up the bufferhubd's soft limit of open file descriptor.
5/ Handle orphaned consumer in acquired state. This is a corner case
   that consumer process goes aways (most likely due to a crash) leaving
   buffer stuck in acquired state with inconsistent buffer state.
6/ Fixes a race condition for released buffer to be Gain'ed and
   Acquire'd when a new consumer is created in released state.
7/ Improve silent consumer queue efficiency: Silent queues no longer
   import buffers or receive signals about new buffers and they are
   limited to only spawning other consumers and notifications about
   producers hanging up.
8/ Modify PDX/UDS channel event signaling to work around epoll
   behavior. PDX UDS uses a combination of an eventfd and an epoll set
   to simulate the original PDX transport channel events. An odd
   behavior discovered in the kernel implementation of epoll was found
   that causes the epoll fd to "unsignal" itself whenever epoll_wait()
   is called on it, regardless of whether it should still be
   pending. This breaks the edge triggerd behavior in nested epoll sets
   that channel events depend on. Since this is unlikely to ever be
   fixed in the kernel we work around the behavior by using the epoll
   set only as a logical OR of two eventfds and never calling
   epoll_wait() on it. When polling is required we use regluar poll()
   with the eventfds and data fd to avoid the bad behavior in
   epoll_wait().
9/ Keep reading data after PDX hangup signal. UDS will signal hangup
   when the other end of the socket closes. However, data could still be
   in the kerenl buffer and should be consumed. Fix an issue where the
   service misses an impulse sent right before the socket is closed.

Bug: 65455724
Bug: 65458354
Bug: 65458312
Bug: 64027135
Bug: 67424527
Test: libpdx_uds_tests
      bufferhub_tests
      buffer_hub_queue-test
      buffer_hub_queue_producer-test
      dvr_api-test

Change-Id: Id07db1f206ccf4e06f7ee3c671193334408971ca
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index be20e72..1186f93 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -11,6 +11,8 @@
 
 #include <private/dvr/ion_buffer.h>
 
+#include "bufferhub_rpc.h"
+
 namespace android {
 namespace dvr {
 
@@ -75,6 +77,14 @@
     }
   }
 
+  std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
+    if (auto* client_channel = GetChannel()) {
+      return client_channel->GetEventSources();
+    } else {
+      return {};
+    }
+  }
+
   native_handle_t* native_handle() const {
     return const_cast<native_handle_t*>(buffer_.handle());
   }
@@ -84,6 +94,10 @@
 
   int id() const { return id_; }
 
+  // A state mask which is unique to a buffer hub client among all its siblings
+  // sharing the same concrete graphic buffer.
+  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
   // The following methods return settings of the first buffer. Currently,
   // it is only possible to create multi-buffer BufferHubBuffers with the same
   // settings.
@@ -98,6 +112,9 @@
   uint64_t producer_usage() const { return buffer_.usage(); }
   uint64_t consumer_usage() const { return buffer_.usage(); }
 
+  uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
+  void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
+
  protected:
   explicit BufferHubBuffer(LocalChannelHandle channel);
   explicit BufferHubBuffer(const std::string& endpoint_path);
@@ -106,6 +123,31 @@
   // Initialization helper.
   int ImportBuffer();
 
+  // Check invalid metadata operation. Returns 0 if requested metadata is valid.
+  int CheckMetadata(size_t user_metadata_size) const;
+
+  // Send out the new fence by updating the shared fence (shared_release_fence
+  // for producer and shared_acquire_fence for consumer). Note that during this
+  // should only be used in LocalPost() or LocalRelease, and the shared fence
+  // shouldn't be poll'ed by the other end.
+  int UpdateSharedFence(const LocalHandle& new_fence,
+                        const LocalHandle& shared_fence);
+
+  // IonBuffer that is shared between bufferhubd, producer, and consumers.
+  size_t metadata_buf_size_{0};
+  size_t user_metadata_size_{0};
+  BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
+  void* user_metadata_ptr_{nullptr};
+  std::atomic<uint64_t>* buffer_state_{nullptr};
+  std::atomic<uint64_t>* fence_state_{nullptr};
+
+  LocalHandle shared_acquire_fence_;
+  LocalHandle shared_release_fence_;
+
+  // A local fence fd that holds the ownership of the fence fd on Post (for
+  // producer) and Release (for consumer).
+  LocalHandle pending_fence_fd_;
+
  private:
   BufferHubBuffer(const BufferHubBuffer&) = delete;
   void operator=(const BufferHubBuffer&) = delete;
@@ -114,8 +156,9 @@
   // for logging and debugging purposes only and should not be used for lookup
   // or any other functional purpose as a security precaution.
   int id_;
-
+  uint64_t buffer_state_bit_{0ULL};
   IonBuffer buffer_;
+  IonBuffer metadata_buffer_;
 };
 
 // This represents a writable buffer. Calling Post notifies all clients and
@@ -136,12 +179,17 @@
   static std::unique_ptr<BufferProducer> Import(
       Status<LocalChannelHandle> status);
 
+  // Asynchronously posts a buffer. The fence and metadata are passed to
+  // consumer via shared fd and shared memory.
+  int PostAsync(const DvrNativeBufferMetadata* meta,
+                const LocalHandle& ready_fence);
+
   // Post this buffer, passing |ready_fence| to the consumers. The bytes in
   // |meta| are passed unaltered to the consumers. The producer must not modify
   // the buffer until it is re-gained.
   // This returns zero or a negative unix error code.
   int Post(const LocalHandle& ready_fence, const void* meta,
-           size_t meta_size_bytes);
+           size_t user_metadata_size);
 
   template <typename Meta,
             typename = typename std::enable_if<std::is_void<Meta>::value>::type>
@@ -160,16 +208,15 @@
   // is in the released state.
   // This returns zero or a negative unix error code.
   int Gain(LocalHandle* release_fence);
+  int GainAsync();
 
   // Asynchronously marks a released buffer as gained. This method is similar to
   // the synchronous version above, except that it does not wait for BufferHub
-  // to acknowledge success or failure, nor does it transfer a release fence to
-  // the client. This version may be used in situations where a release fence is
-  // not needed. Because of the asynchronous nature of the underlying message,
-  // no error is returned if this method is called when the buffer is in an
-  // incorrect state. Returns zero if sending the message succeeded, or a
-  // negative errno code otherwise.
-  int GainAsync();
+  // to acknowledge success or failure. Because of the asynchronous nature of
+  // the underlying message, no error is returned if this method is called when
+  // the buffer is in an incorrect state. Returns zero if sending the message
+  // succeeded, or a negative errno code if local error check fails.
+  int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
 
   // Attaches the producer to |name| so that it becomes a persistent buffer that
   // may be retrieved by name at a later time. This may be used in cases where a
@@ -216,7 +263,7 @@
   BufferProducer(const std::string& name, int user_id, int group_id,
                  uint32_t width, uint32_t height, uint32_t format,
                  uint64_t producer_usage, uint64_t consumer_usage,
-                 size_t meta_size_bytes);
+                 size_t user_metadata_size);
 
   // Constructs a blob (flat) buffer with the given usage flags.
   BufferProducer(uint32_t usage, size_t size);
@@ -234,6 +281,11 @@
 
   // Imports the given file handle to a producer channel, taking ownership.
   explicit BufferProducer(LocalChannelHandle channel);
+
+  // Local state transition helpers.
+  int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+  int LocalPost(const DvrNativeBufferMetadata* meta,
+                const LocalHandle& ready_fence);
 };
 
 // This is a connection to a producer buffer, which can be located in another
@@ -263,7 +315,7 @@
   // are available. This call will only succeed if the buffer is in the posted
   // state.
   // Returns zero on success, or a negative errno code otherwise.
-  int Acquire(LocalHandle* ready_fence, void* meta, size_t meta_size_bytes);
+  int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
 
   // Attempt to retrieve a post event from buffer hub. If successful,
   // |ready_fence| is set to a fence to wait on until the buffer is ready. This
@@ -274,20 +326,22 @@
     return Acquire(ready_fence, meta, sizeof(*meta));
   }
 
+  // Asynchronously acquires a bufer.
+  int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
   // This should be called after a successful Acquire call. If the fence is
   // valid the fence determines the buffer usage, otherwise the buffer is
   // released immediately.
   // This returns zero or a negative unix error code.
   int Release(const LocalHandle& release_fence);
+  int ReleaseAsync();
 
   // Asynchronously releases a buffer. Similar to the synchronous version above,
-  // except that it does not wait for BufferHub to reply with success or error,
-  // nor does it transfer a release fence. This version may be used in
-  // situations where a release fence is not needed. Because of the asynchronous
-  // nature of the underlying message, no error is returned if this method is
-  // called when the buffer is in an incorrect state. Returns zero if sending
-  // the message succeeded, or a negative errno code otherwise.
-  int ReleaseAsync();
+  // except that it does not wait for BufferHub to reply with success or error.
+  // The fence and metadata are passed to consumer via shared fd and shared
+  // memory.
+  int ReleaseAsync(const DvrNativeBufferMetadata* meta,
+                   const LocalHandle& release_fence);
 
   // May be called after or instead of Acquire to indicate that the consumer
   // does not need to access the buffer this cycle. This returns zero or a
@@ -305,6 +359,11 @@
   friend BASE;
 
   explicit BufferConsumer(LocalChannelHandle channel);
+
+  // Local state transition helpers.
+  int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+  int LocalRelease(const DvrNativeBufferMetadata* meta,
+                   const LocalHandle& release_fence);
 };
 
 }  // namespace dvr