Add dvr_buffer_queue C API
Bug: 36401767
Bug: 32213274
Bug: 36266201
Test: build and ran dvr_buffer_queue-test
Change-Id: Icd8d063bd8b7adb15bf67f7e543b87dad1c32a68
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 1c8f2c0..2d96638 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -43,7 +43,7 @@
cc_library {
name: "libbufferhubqueue",
cflags = [
- "-DLOGTAG=\"libbufferhubqueue\"",
+ "-DLOG_TAG=\"libbufferhubqueue\"",
"-DTRACE=0",
],
srcs: sourceFiles,
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index feaf3d7..f786356 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -329,6 +329,9 @@
return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
+ std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
+ size_t meta_size,
+ LocalHandle* acquire_fence);
private:
friend BASE;
@@ -344,13 +347,27 @@
LocalHandle* acquire_fence) override;
int OnBufferAllocated() override;
-
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
- size_t meta_size,
- LocalHandle* acquire_fence);
};
} // namespace dvr
} // namespace android
+// Concrete C type definition for DVR API.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct DvrWriteBufferQueue {
+ std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+};
+
+struct DvrReadBufferQueue {
+ std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue_;
+};
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index b8a0da3..865573c 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -24,6 +24,7 @@
static_libs: static_libraries,
shared_libs: shared_libraries,
cflags: [
+ "-DLOG_TAG=\"buffer_hub_queue-test\"",
"-DTRACE=0",
"-O0",
"-g",
@@ -37,6 +38,7 @@
static_libs: static_libraries,
shared_libs: shared_libraries,
cflags: [
+ "-DLOG_TAG=\"buffer_hub_queue_producer-test\"",
"-DTRACE=0",
"-O0",
"-g",
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index 5a21418..5449cb5 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -32,6 +32,7 @@
display_manager_client.cpp \
dvr_api.cpp \
dvr_buffer.cpp \
+ dvr_buffer_queue.cpp \
dvr_surface.cpp \
vsync_client_api.cpp \
@@ -49,3 +50,5 @@
libbase \
include $(BUILD_STATIC_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index b04b897..4dd49da 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -5,6 +5,7 @@
// Headers from libdvr
#include <dvr/display_manager_client.h>
#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_buffer_queue.h>
#include <dvr/dvr_surface.h>
#include <dvr/vsync_client_api.h>
@@ -53,12 +54,27 @@
dvr_api->write_buffer_gain_ = dvrWriteBufferGain;
dvr_api->write_buffer_gain_async_ = dvrWriteBufferGainAsync;
+ dvr_api->read_buffer_destroy_ = dvrReadBufferDestroy;
dvr_api->read_buffer_get_blob_fds_ = dvrReadBufferGetBlobFds;
dvr_api->read_buffer_get_AHardwareBuffer_ = dvrReadBufferGetAHardwareBuffer;
dvr_api->read_buffer_acquire_ = dvrReadBufferAcquire;
dvr_api->read_buffer_release_ = dvrReadBufferRelease;
dvr_api->read_buffer_release_async_ = dvrReadBufferReleaseAsync;
+ // dvr_buffer_queue.h
+ dvr_api->write_buffer_queue_destroy_ = dvrWriteBufferQueueDestroy;
+ dvr_api->write_buffer_queue_get_capacity_ = dvrWriteBufferQueueGetCapacity;
+ dvr_api->write_buffer_queue_get_external_surface_ =
+ dvrWriteBufferQueueGetExternalSurface;
+ dvr_api->write_buffer_queue_create_read_queue_ =
+ dvrWriteBufferQueueCreateReadQueue;
+ dvr_api->write_buffer_queue_dequeue_ = dvrWriteBufferQueueDequeue;
+ dvr_api->read_buffer_queue_destroy_ = dvrReadBufferQueueDestroy;
+ dvr_api->read_buffer_queue_get_capacity_ = dvrReadBufferQueueGetCapacity;
+ dvr_api->read_buffer_queue_create_read_queue_ =
+ dvrReadBufferQueueCreateReadQueue;
+ dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
+
// dvr_surface.h
dvr_api->get_pose_buffer_ = dvrGetPoseBuffer;
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 43290ba..25128a6 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -6,12 +6,12 @@
using namespace android;
struct DvrWriteBuffer {
- std::unique_ptr<dvr::BufferProducer> write_buffer_;
+ std::shared_ptr<dvr::BufferProducer> write_buffer_;
sp<GraphicBuffer> graphic_buffer_;
};
struct DvrReadBuffer {
- std::unique_ptr<dvr::BufferConsumer> read_buffer_;
+ std::shared_ptr<dvr::BufferConsumer> read_buffer_;
sp<GraphicBuffer> graphic_buffer_;
};
@@ -19,14 +19,14 @@
namespace dvr {
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
- std::unique_ptr<dvr::BufferProducer> buffer_producer) {
+ const std::shared_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) {
+ const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
DvrReadBuffer* read_buffer = new DvrReadBuffer;
read_buffer->read_buffer_ = std::move(buffer_consumer);
return read_buffer;
@@ -86,6 +86,8 @@
return client->write_buffer_->GainAsync();
}
+void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+
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);
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
new file mode 100644
index 0000000..b0b5a2a
--- /dev/null
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -0,0 +1,146 @@
+#include "include/dvr/dvr_buffer_queue.h"
+
+#include <gui/Surface.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_producer.h>
+
+#include <android_runtime/android_view_Surface.h>
+
+#define CHECK_PARAM(param) \
+ LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
+ __FUNCTION__)
+
+using namespace android;
+
+extern "C" {
+
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
+ delete write_queue;
+}
+
+size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
+ CHECK_PARAM(write_queue);
+ return write_queue->producer_queue_->capacity();
+}
+
+void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+ JNIEnv* env) {
+ CHECK_PARAM(env);
+ CHECK_PARAM(write_queue);
+
+ std::shared_ptr<dvr::BufferHubQueueCore> core =
+ dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+
+ return android_view_Surface_createFromIGraphicBufferProducer(
+ env, new dvr::BufferHubQueueProducer(core));
+}
+
+int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
+ DvrReadBufferQueue** out_read_queue) {
+ CHECK_PARAM(write_queue);
+ CHECK_PARAM(write_queue->producer_queue_);
+ CHECK_PARAM(out_read_queue);
+
+ auto read_queue = std::make_unique<DvrReadBufferQueue>();
+ read_queue->consumer_queue_ =
+ write_queue->producer_queue_->CreateConsumerQueue();
+ if (read_queue->consumer_queue_ == nullptr) {
+ ALOGE(
+ "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
+ "from DvrWriteBufferQueue[%p].",
+ write_queue);
+ return -ENOMEM;
+ }
+
+ *out_read_queue = read_queue.release();
+ return 0;
+}
+
+int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer** out_buffer,
+ int* out_fence_fd) {
+ CHECK_PARAM(write_queue);
+ CHECK_PARAM(write_queue->producer_queue_);
+ CHECK_PARAM(out_buffer);
+ CHECK_PARAM(out_fence_fd);
+
+ size_t slot;
+ pdx::LocalHandle release_fence;
+ std::shared_ptr<dvr::BufferProducer> buffer =
+ write_queue->producer_queue_->Dequeue(timeout, &slot, &release_fence);
+ if (buffer == nullptr) {
+ ALOGE("dvrWriteBufferQueueDequeue: Failed to dequeue buffer.");
+ return -ENOMEM;
+ }
+
+ *out_buffer = CreateDvrWriteBufferFromBufferProducer(buffer);
+ *out_fence_fd = release_fence.Release();
+ return 0;
+}
+
+// ReadBufferQueue
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
+ delete read_queue;
+}
+
+size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+ CHECK_PARAM(read_queue);
+
+ return read_queue->consumer_queue_->capacity();
+}
+
+int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
+ DvrReadBufferQueue** out_read_queue) {
+ CHECK_PARAM(read_queue);
+ CHECK_PARAM(read_queue->consumer_queue_);
+ CHECK_PARAM(out_read_queue);
+
+ auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
+ new_read_queue->consumer_queue_ =
+ read_queue->consumer_queue_->CreateConsumerQueue();
+ if (new_read_queue->consumer_queue_ == nullptr) {
+ ALOGE(
+ "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
+ "from DvrReadBufferQueue[%p].",
+ read_queue);
+ return -ENOMEM;
+ }
+
+ *out_read_queue = new_read_queue.release();
+ return 0;
+}
+
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer** out_buffer, int* out_fence_fd,
+ void* out_meta, size_t meta_size_bytes) {
+ CHECK_PARAM(read_queue);
+ CHECK_PARAM(read_queue->consumer_queue_);
+ CHECK_PARAM(out_buffer);
+ CHECK_PARAM(out_fence_fd);
+ CHECK_PARAM(out_meta);
+
+ if (meta_size_bytes != read_queue->consumer_queue_->metadata_size()) {
+ ALOGE(
+ "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
+ "but actual (%zu).",
+ read_queue->consumer_queue_->metadata_size(), meta_size_bytes);
+ return -EINVAL;
+ }
+
+ size_t slot;
+ pdx::LocalHandle acquire_fence;
+ std::shared_ptr<dvr::BufferConsumer> buffer =
+ read_queue->consumer_queue_->Dequeue(timeout, &slot, out_meta,
+ meta_size_bytes, &acquire_fence);
+
+ if (buffer == nullptr) {
+ ALOGE("dvrReadBufferQueueGainBuffer: Failed to dequeue buffer.");
+ return -ENOMEM;
+ }
+
+ *out_buffer = CreateDvrReadBufferFromBufferConsumer(buffer);
+ *out_fence_fd = acquire_fence.Release();
+ return 0;
+}
+
+} // extern "C"
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 3f020a3..6fd50ee 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -5,6 +5,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <jni.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -27,6 +29,9 @@
typedef struct DvrReadBuffer DvrReadBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
// display_manager_client.h
typedef int (*DisplayManagerClientGetSurfaceListPtr)(
DvrDisplayManagerClient* client,
@@ -63,6 +68,7 @@
int* release_fence_fd);
typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
+typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
size_t* fds_count,
size_t max_fds_count);
@@ -75,6 +81,29 @@
int release_fence_fd);
typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+// dvr_buffer_queue.h
+typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
+typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
+ DvrWriteBufferQueue* write_queue);
+typedef void* (*DvrWriteBufferQueueGetExternalSurfacePtr)(
+ DvrWriteBufferQueue* write_queue, JNIEnv* env);
+typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
+ DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
+typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
+ int timeout,
+ DvrWriteBuffer** out_buffer,
+ int* out_fence_fd);
+typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
+typedef size_t (*DvrReadBufferQueueGetCapacityPtr)(
+ DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
+ DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
+typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
+ int timeout,
+ DvrReadBuffer** out_buffer,
+ int* out_fence_fd, void* out_meta,
+ size_t meta_size_bytes);
+
// dvr_surface.h
typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
@@ -137,12 +166,27 @@
DvrWriteBufferGainAsyncPtr write_buffer_gain_async_;
// Read buffer
+ DvrReadBufferDestroyPtr read_buffer_destroy_;
DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds_;
DvrReadBufferGetAHardwareBufferPtr read_buffer_get_AHardwareBuffer_;
DvrReadBufferAcquirePtr read_buffer_acquire_;
DvrReadBufferReleasePtr read_buffer_release_;
DvrReadBufferReleaseAsyncPtr read_buffer_release_async_;
+ // Write buffer queue
+ DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy_;
+ DvrWriteBufferQueueGetCapacityPtr write_buffer_queue_get_capacity_;
+ DvrWriteBufferQueueGetExternalSurfacePtr
+ write_buffer_queue_get_external_surface_;
+ DvrWriteBufferQueueCreateReadQueuePtr write_buffer_queue_create_read_queue_;
+ DvrWriteBufferQueueDequeuePtr write_buffer_queue_dequeue_;
+
+ // Read buffer queue
+ DvrReadBufferQueueDestroyPtr read_buffer_queue_destroy_;
+ DvrReadBufferQueueGetCapacityPtr read_buffer_queue_get_capacity_;
+ DvrReadBufferQueueCreateReadQueuePtr read_buffer_queue_create_read_queue_;
+ DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
+
// V-Sync client
VSyncClientCreatePtr vsync_client_create_;
VSyncClientDestroyPtr vsync_client_destroy_;
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index c14b1a3..bbfbb00 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -25,6 +25,7 @@
int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
// Read buffer
+void dvrReadBufferDestroy(DvrReadBuffer* client);
void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
size_t max_fds_count);
int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
@@ -45,9 +46,9 @@
class BufferConsumer;
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
- std::unique_ptr<BufferProducer> buffer_producer);
+ const std::shared_ptr<BufferProducer>& buffer_producer);
DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
- std::unique_ptr<BufferConsumer> buffer_consumer);
+ const std::shared_ptr<BufferConsumer>& buffer_consumer);
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
new file mode 100644
index 0000000..86b3ae2
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -0,0 +1,41 @@
+#ifndef ANDROID_DVR_BUFFER_QUEUE_H_
+#define ANDROID_DVR_BUFFER_QUEUE_H_
+
+#include <dvr/dvr_buffer.h>
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+// WriteBufferQueue
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+
+// Returns ANativeWindow in the form of jobject. Can be casted to ANativeWindow
+// using ANativeWindow_fromSurface NDK API.
+void* dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
+ JNIEnv* env);
+
+int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
+ DvrReadBufferQueue** out_read_queue);
+int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer** out_buffer, int* out_fence_fd);
+
+// ReadeBufferQueue
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
+ DvrReadBufferQueue** out_read_queue);
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer** out_buffer, int* out_fence_fd,
+ void* out_meta, size_t meta_size_bytes);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
new file mode 100644
index 0000000..158d58f
--- /dev/null
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH := $(call my-dir)
+
+shared_libraries := \
+ libbase \
+ libbinder \
+ libcutils \
+ libgui \
+ liblog \
+ libhardware \
+ libui \
+ libutils \
+
+static_libraries := \
+ libdvr \
+ libbufferhubqueue \
+ libbufferhub \
+ libchrome \
+ libdvrcommon \
+ libpdx_default_transport \
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_STATIC_LIBRARIES := $(static_libraries)
+LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
new file mode 100644
index 0000000..f344a24
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -0,0 +1,149 @@
+#include <dvr/dvr_buffer_queue.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+static constexpr int kBufferWidth = 100;
+static constexpr int kBufferHeight = 1;
+static constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+static constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+static constexpr int kBufferSliceCount = 1; // number of slices in each buffer
+static constexpr size_t kQueueCapacity = 3;
+
+typedef uint64_t TestMeta;
+
+class DvrBufferQueueTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ write_queue_ = new DvrWriteBufferQueue;
+ write_queue_->producer_queue_ = ProducerQueue::Create<TestMeta>(0, 0, 0, 0);
+ ASSERT_NE(nullptr, write_queue_->producer_queue_);
+ }
+
+ void TearDown() override {
+ if (write_queue_ != nullptr) {
+ dvrWriteBufferQueueDestroy(write_queue_);
+ write_queue_ = nullptr;
+ }
+ }
+
+ void AllocateBuffers(size_t buffer_count) {
+ size_t out_slot;
+ for (size_t i = 0; i < buffer_count; i++) {
+ int ret = write_queue_->producer_queue_->AllocateBuffer(
+ kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage,
+ kBufferSliceCount, &out_slot);
+ ASSERT_EQ(0, ret);
+ }
+ }
+
+ DvrWriteBufferQueue* write_queue_{nullptr};
+};
+
+TEST_F(DvrBufferQueueTest, TestWrite_QueueDestroy) {
+ dvrWriteBufferQueueDestroy(write_queue_);
+ write_queue_ = nullptr;
+}
+
+TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
+ AllocateBuffers(kQueueCapacity);
+ size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
+
+ ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity);
+ ASSERT_EQ(kQueueCapacity, capacity);
+}
+
+TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
+ DvrReadBufferQueue* read_queue = nullptr;
+ int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, read_queue);
+
+ dvrReadBufferQueueDestroy(read_queue);
+}
+
+TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
+ DvrReadBufferQueue* read_queue1 = nullptr;
+ DvrReadBufferQueue* read_queue2 = nullptr;
+ int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
+
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, read_queue1);
+
+ ret = dvrReadBufferQueueCreateReadQueue(read_queue1, &read_queue2);
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, read_queue2);
+ ASSERT_NE(read_queue1, read_queue2);
+
+ dvrReadBufferQueueDestroy(read_queue1);
+ dvrReadBufferQueueDestroy(read_queue2);
+}
+
+TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
+ static constexpr int kTimeout = 0;
+ DvrReadBufferQueue* read_queue = nullptr;
+ DvrReadBuffer* rb = nullptr;
+ DvrWriteBuffer* wb = nullptr;
+ int fence_fd = -1;
+
+ int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
+
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, read_queue);
+
+ AllocateBuffers(kQueueCapacity);
+
+ // Gain buffer for writing.
+ ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, &wb, &fence_fd);
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, wb);
+ ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
+ wb, fence_fd);
+ pdx::LocalHandle release_fence(fence_fd);
+
+ // Post buffer to the read_queue.
+ TestMeta seq = 42U;
+ ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq));
+ ASSERT_EQ(0, ret);
+ dvrWriteBufferDestroy(wb);
+ wb = nullptr;
+
+ // Acquire buffer for reading.
+ TestMeta acquired_seq = 0U;
+ ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, &rb, &fence_fd,
+ &acquired_seq, sizeof(acquired_seq));
+ ASSERT_EQ(0, ret);
+ ASSERT_NE(nullptr, rb);
+ ASSERT_EQ(seq, acquired_seq);
+ ALOGD_IF(TRACE,
+ "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
+ fence_fd);
+ pdx::LocalHandle acquire_fence(fence_fd);
+
+ // Release buffer to the write_queue.
+ ret = dvrReadBufferRelease(rb, -1);
+ ASSERT_EQ(0, ret);
+ dvrReadBufferDestroy(rb);
+ rb = nullptr;
+
+ // TODO(b/34387835) Currently buffer allocation has to happen after all queues
+ // are initialized.
+ size_t capacity = dvrReadBufferQueueGetCapacity(read_queue);
+
+ ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity);
+ ASSERT_EQ(kQueueCapacity, capacity);
+
+ dvrReadBufferQueueDestroy(read_queue);
+}
+
+} // namespace
+
+} // namespace dvr
+} // namespace android