Adopt the use of shared buffers.

Bug: 37001948
Test: Make system image
Change-Id: I032574f250e0f0fe7768af649730406e24d853db
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index c0c7e2f..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -17,6 +17,7 @@
     "display_manager_client.cpp",
     "display_protocol.cpp",
     "vsync_client.cpp",
+    "shared_buffer_helpers.cpp",
 ]
 
 localIncludeFiles = [
@@ -39,7 +40,7 @@
     "libdvrcommon",
     "libbufferhubqueue",
     "libbufferhub",
-    "libvrsensor",
+    "libbroadcastring",
     "libpdx_default_transport",
 ]
 
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..249f410
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,138 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+  // This constructor will create a display client and get the buffer from it.
+  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+  // If you already have the IonBuffer, use this. It will take ownership.
+  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+  // Use this if you do not want to take ownership.
+  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+  ~CPUMappedBuffer();
+
+  // Getters.
+  size_t Size() const { return size_; }
+  void* Address() const { return address_; }
+  bool IsMapped() const { return Address() != nullptr; }
+
+  // Attempt mapping this buffer to the CPU addressable space.
+  // This will create a display client and see if the buffer exists.
+  // If the buffer has not been setup yet, you will need to try again later.
+  void TryMapping();
+
+ protected:
+  // The memory area if we managed to map it.
+  size_t size_ = 0;
+  void* address_ = nullptr;
+
+  // If we are polling the display client, the buffer key here.
+  DvrGlobalBufferKey buffer_key_;
+
+  // If we just own the IonBuffer outright, it's here.
+  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+  // If we do not own the IonBuffer, it's here
+  IonBuffer* buffer_ = nullptr;
+
+  // The usage mode.
+  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+      : CPUMappedBuffer(key, mode) {}
+
+  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(std::move(buffer), mode) {}
+
+  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+      : CPUMappedBuffer(buffer, mode) {}
+
+  // Helper function for publishing records in the ring.
+  void Publish(const typename RingType::Record& record) {
+    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      ring->Put(record);
+    }
+  }
+
+  // Helper function for getting records from the ring.
+  // Returns true if we were able to retrieve the latest.
+  bool GetNewest(typename RingType::Record* record) {
+    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+           (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+    auto ring = Ring();
+    if (ring) {
+      return ring->GetNewest(&sequence_, record);
+    }
+
+    return false;
+  }
+
+  // Try obtaining the ring. If the named buffer has not been created yet, it
+  // will return nullptr.
+  RingType* Ring() {
+    if (IsMapped() == false) {
+      TryMapping();
+
+      if (IsMapped()) {
+        switch (usage_mode_) {
+          case CPUUsageMode::READ_OFTEN:
+          case CPUUsageMode::READ_RARELY: {
+            RingType ring;
+            bool import_ok;
+            std::tie(ring, import_ok) = RingType::Import(address_, size_);
+            if (import_ok) {
+              ring_ = std::make_unique<RingType>(ring);
+            }
+          } break;
+          case CPUUsageMode::WRITE_OFTEN:
+          case CPUUsageMode::WRITE_RARELY:
+            ring_ =
+                std::make_unique<RingType>(RingType::Create(address_, size_));
+            break;
+        }
+      }
+    }
+
+    return ring_.get();
+  }
+
+ protected:
+  std::unique_ptr<RingType> ring_ = nullptr;
+
+  uint32_t sequence_ = 0;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..00bad88
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,84 @@
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+    : buffer_key_(key), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+                                 CPUUsageMode mode)
+    : owned_buffer_(std::move(buffer)),
+      buffer_(owned_buffer_.get()),
+      usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+    : buffer_(buffer), usage_mode_(mode) {
+  TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+  if (IsMapped()) {
+    buffer_->Unlock();
+  }
+}
+
+void CPUMappedBuffer::TryMapping() {
+  // Do we have an IonBuffer for this shared memory object?
+  if (buffer_ == nullptr) {
+    // Create a display client and get the buffer.
+    // TODO(okana): We might want to throttle this.
+    auto display_client = display::DisplayClient::Create();
+    if (display_client) {
+      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+      if (get_result.ok()) {
+        owned_buffer_ = get_result.take();
+        buffer_ = owned_buffer_.get();
+      } else {
+        ALOGW("Could not get named buffer from pose service : %s(%d)",
+              get_result.GetErrorMessage().c_str(), get_result.error());
+      }
+    } else {
+      ALOGE("Unable to create display client for shared buffer access");
+    }
+  }
+
+  if (buffer_) {
+    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+                 ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+    // Figure out the usage bits.
+    switch (usage_mode_) {
+      case CPUUsageMode::READ_OFTEN:
+        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+        break;
+      case CPUUsageMode::READ_RARELY:
+        usage |= GRALLOC_USAGE_SW_READ_RARELY;
+        break;
+      case CPUUsageMode::WRITE_OFTEN:
+        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+        break;
+      case CPUUsageMode::WRITE_RARELY:
+        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+        break;
+    }
+
+    int width = static_cast<int>(buffer_->width());
+    int height = 1;
+    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+    if (ret < 0 || !address_) {
+      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+      buffer_->Unlock();
+    } else {
+      size_ = width;
+    }
+  }
+}
+
+}  // namespace dvr
+}  // namespace android