Add dvr_buffer apis

Test: None
Bug: None
Change-Id: I234d7ef4dabb4453cdbc67d3112adf2ffbbadaf4
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 452bad0..e068469 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -15,6 +15,7 @@
 sourceFiles = [
     "buffer_hub_client.cpp",
     "buffer_hub_rpc.cpp",
+    "dvr_buffer.cpp",
     "ion_buffer.cpp",
 ]
 
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 7268b76..2749fd1 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -130,6 +130,13 @@
   return ret;
 }
 
+void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
+                                 size_t max_fds_count) const {
+  size_t numFds = static_cast<size_t>(native_handle()->numFds);
+  *fds_count = std::min(max_fds_count, numFds);
+  std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
+}
+
 BufferConsumer::BufferConsumer(LocalChannelHandle channel)
     : BASE(std::move(channel)) {
   const int ret = ImportBuffer();
diff --git a/libs/vr/libbufferhub/dvr_buffer.cpp b/libs/vr/libbufferhub/dvr_buffer.cpp
new file mode 100644
index 0000000..3eb611f
--- /dev/null
+++ b/libs/vr/libbufferhub/dvr_buffer.cpp
@@ -0,0 +1,124 @@
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/dvr_buffer.h>
+#include <ui/GraphicBuffer.h>
+
+using namespace android;
+
+struct DvrWriteBuffer {
+  std::unique_ptr<dvr::BufferProducer> write_buffer_;
+  sp<GraphicBuffer> graphic_buffer_;
+};
+
+struct DvrReadBuffer {
+  std::unique_ptr<dvr::BufferConsumer> read_buffer_;
+  sp<GraphicBuffer> graphic_buffer_;
+};
+
+namespace android {
+namespace dvr {
+
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+    std::unique_ptr<dvr::BufferProducer> buffer_producer) {
+  DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
+  write_buffer->write_buffer_ = std::move(buffer_producer);
+  return write_buffer;
+}
+
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+    std::unique_ptr<dvr::BufferConsumer> buffer_consumer) {
+  DvrReadBuffer* read_buffer = new DvrReadBuffer;
+  read_buffer->read_buffer_ = std::move(buffer_consumer);
+  return read_buffer;
+}
+
+}  // namespace dvr
+}  // namespace android
+
+namespace {
+
+void InitializeGraphicBuffer(const dvr::BufferHubBuffer* buffer,
+                             sp<GraphicBuffer>* graphic_buffer) {
+  *graphic_buffer = sp<GraphicBuffer>(new GraphicBuffer(
+      buffer->width(), buffer->height(), buffer->format(), 1, /* layer count */
+      buffer->usage(), buffer->stride(), buffer->native_handle(),
+      false /* keep ownership */));
+}
+
+}  // anonymous namespace
+
+extern "C" {
+
+void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
+
+void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
+                              size_t* fds_count, size_t max_fds_count) {
+  client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+                                     AHardwareBuffer** hardware_buffer) {
+  if (!client->graphic_buffer_.get()) {
+    InitializeGraphicBuffer(client->write_buffer_.get(),
+                            &client->graphic_buffer_);
+  }
+  *hardware_buffer =
+      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  return 0;
+}
+
+int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+                       const void* meta, size_t meta_size_bytes) {
+  pdx::LocalHandle fence(ready_fence_fd);
+  int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
+  fence.Release();
+  return result;
+}
+
+int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+  pdx::LocalHandle release_fence;
+  int result = client->write_buffer_->Gain(&release_fence);
+  *release_fence_fd = release_fence.Release();
+  return result;
+}
+
+int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
+  return client->write_buffer_->GainAsync();
+}
+
+void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
+                             size_t max_fds_count) {
+  client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+}
+
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+                                    AHardwareBuffer** hardware_buffer) {
+  if (!client->graphic_buffer_.get()) {
+    InitializeGraphicBuffer(client->read_buffer_.get(),
+                            &client->graphic_buffer_);
+  }
+  *hardware_buffer =
+      reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+  return 0;
+}
+
+int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
+                         size_t meta_size_bytes) {
+  pdx::LocalHandle ready_fence;
+  int result =
+      client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+  *ready_fence_fd = ready_fence.Release();
+  return result;
+}
+
+int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+  pdx::LocalHandle fence(release_fence_fd);
+  int result = client->read_buffer_->Release(fence);
+  fence.Release();
+  return result;
+}
+
+int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
+  return client->read_buffer_->ReleaseAsync();
+}
+
+}  // extern "C"
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 cefde7b..aacc385 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -70,6 +70,10 @@
     return LocalHandle(dup(native_handle()->data[0]));
   }
 
+  // Get up to |max_fds_count| file descriptors for accessing the blob shared
+  // memory. |fds_count| will contain the actual number of file descriptors.
+  void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
+
   using Client::event_fd;
 
   Status<int> GetEventMask(int events) {
diff --git a/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h b/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
new file mode 100644
index 0000000..c14b1a3
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/dvr_buffer.h
@@ -0,0 +1,55 @@
+#ifndef ANDROID_DVR_BUFFER_H_
+#define ANDROID_DVR_BUFFER_H_
+
+#include <memory>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct AHardwareBuffer AHardwareBuffer;
+
+// Write buffer
+void dvrWriteBufferDestroy(DvrWriteBuffer* client);
+void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
+                              size_t* fds_count, size_t max_fds_count);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+                                     AHardwareBuffer** hardware_buffer);
+int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+                       const void* meta, size_t meta_size_bytes);
+int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+
+// Read buffer
+void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
+                             size_t max_fds_count);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+                                    AHardwareBuffer** hardware_buffer);
+int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
+                         size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+namespace android {
+namespace dvr {
+
+class BufferProducer;
+class BufferConsumer;
+
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+    std::unique_ptr<BufferProducer> buffer_producer);
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+    std::unique_ptr<BufferConsumer> buffer_consumer);
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_BUFFER_H_