Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 597281d8 authored by Jiwen 'Steve' Cai's avatar Jiwen 'Steve' Cai Committed by android-build-merger
Browse files

Merge "Add dvr API to create write queue locally" into oc-mr1-dev

am: 1e35190f

Change-Id: Idf0183a26a45a1cf90d163f9bd974a52fb807869
parents c8a1e48e 1e35190f
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@ using android::dvr::BufferHubQueueProducer;
using android::dvr::BufferProducer;
using android::dvr::ConsumerQueue;
using android::dvr::ProducerQueue;
using android::dvr::ProducerQueueConfigBuilder;
using android::dvr::UsagePolicy;

extern "C" {

@@ -156,6 +158,36 @@ int DvrWriteBufferQueue::ResizeBuffer(uint32_t width, uint32_t height) {
  return 0;
}

int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format,
                              uint32_t layer_count, uint64_t usage,
                              size_t capacity, size_t metadata_size,
                              DvrWriteBufferQueue** out_write_queue) {
  if (!out_write_queue)
    return -EINVAL;

  auto config_builder = ProducerQueueConfigBuilder()
                            .SetDefaultWidth(width)
                            .SetDefaultHeight(height)
                            .SetDefaultFormat(format)
                            .SetMetadataSize(metadata_size);
  std::unique_ptr<ProducerQueue> producer_queue =
      ProducerQueue::Create(config_builder.Build(), UsagePolicy{});
  if (!producer_queue) {
    ALOGE("dvrWriteBufferQueueCreate: Failed to create producer queue.");
    return -ENOMEM;
  }

  auto status = producer_queue->AllocateBuffers(width, height, layer_count,
                                                format, usage, capacity);
  if (!status.ok()) {
    ALOGE("dvrWriteBufferQueueCreate: Failed to allocate buffers.");
    return -ENOMEM;
  }

  *out_write_queue = new DvrWriteBufferQueue(std::move(producer_queue));
  return 0;
}

void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
  delete write_queue;
}
+6 −0
Original line number Diff line number Diff line
@@ -159,6 +159,12 @@ typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
    DvrBuffer* buffer);

// dvr_buffer_queue.h
typedef int (*DvrWriteBufferQueueCreatePtr)(uint32_t width, uint32_t height,
                                            uint32_t format,
                                            uint32_t layer_count,
                                            uint64_t usage, size_t capacity,
                                            size_t metadata_size,
                                            DvrWriteBufferQueue** queue_out);
typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)(
    DvrWriteBufferQueue* write_queue);
+3 −0
Original line number Diff line number Diff line
@@ -160,3 +160,6 @@ DVR_V1_API_ENTRY(PoseClientSensorsEnable);

// Read buffer queue
DVR_V1_API_ENTRY(ReadBufferQueueGetEventFd);

// Create write buffer queue locally
DVR_V1_API_ENTRY(WriteBufferQueueCreate);
+30 −0
Original line number Diff line number Diff line
@@ -12,6 +12,36 @@ typedef struct ANativeWindow ANativeWindow;
typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
typedef struct DvrReadBufferQueue DvrReadBufferQueue;

// Creates a write buffer queue to be used locally.
//
// Note that this API is mostly for testing purpose. For now there is no
// mechanism to send a DvrWriteBufferQueue cross process. Use
// dvrSurfaceCreateWriteBufferQueue if cross-process buffer transport is
// intended.
//
// @param width The width of the buffers that this queue will produce.
// @param height The height of buffers that this queue will produce.
// @param format The format of the buffers that this queue will produce. This
//     must be one of the AHARDWAREBUFFER_FORMAT_XXX enums.
// @param layer_count The number of layers of the buffers that this queue will
//     produce.
// @param usage The usage of the buffers that this queue will produce. This
//     must a combination of the AHARDWAREBUFFER_USAGE_XXX flags.
// @param capacity The number of buffer that this queue will allocate. Note that
//     all buffers will be allocated on create. Currently, the number of buffers
//     is the queue cannot be changed after creation though DVR API. However,
//     ANativeWindow can choose to reallocate, attach, or detach buffers from
//     a DvrWriteBufferQueue through Android platform logic.
// @param metadata_size The size of metadata in bytes.
// @param out_write_queue The pointer of a DvrWriteBufferQueue will be filled
//      here if the method call succeeds. The metadata size must match
//      the metadata size in dvrWriteBufferPost/dvrReadBufferAcquire.
// @return Zero on success, or negative error code.
int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format,
                              uint32_t layer_count, uint64_t usage,
                              size_t capacity, size_t metadata_size,
                              DvrWriteBufferQueue** out_write_queue);

// Destroy a write buffer queue.
//
// @param write_queue The DvrWriteBufferQueue of interest.
+92 −77
Original line number Diff line number Diff line
#include <android/log.h>
#include <android/native_window.h>
#include <android-base/unique_fd.h>
#include <dvr/dvr_api.h>
#include <dvr/dvr_buffer_queue.h>
#include <gui/Surface.h>
#include <private/dvr/buffer_hub_queue_client.h>

#include <base/logging.h>
#include <gtest/gtest.h>

#include "../dvr_internal.h"
#include "../dvr_buffer_queue_internal.h"
#include <array>
#include <unordered_map>

namespace android {
namespace dvr {
#ifndef ALOGD
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#endif

#ifndef ALOGD_IF
#define ALOGD_IF(cond, ...) \
  ((__predict_false(cond)) ? ((void)ALOGD(__VA_ARGS__)) : (void)0)
#endif

namespace {

static constexpr uint32_t kBufferWidth = 100;
static constexpr uint32_t kBufferHeight = 1;
static constexpr uint32_t kLayerCount = 1;
static constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
static constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB;
static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
static constexpr size_t kQueueCapacity = 3;

typedef uint64_t TestMeta;
@@ -36,14 +42,6 @@ class DvrBufferQueueTest : public ::testing::Test {
  }

 protected:
  void SetUp() override {
    config_builder_ = ProducerQueueConfigBuilder()
                          .SetDefaultWidth(kBufferWidth)
                          .SetDefaultHeight(kBufferHeight)
                          .SetDefaultFormat(kBufferFormat)
                          .SetMetadata<TestMeta>();
  }

  void TearDown() override {
    if (write_queue_ != nullptr) {
      dvrWriteBufferQueueDestroy(write_queue_);
@@ -51,19 +49,6 @@ class DvrBufferQueueTest : public ::testing::Test {
    }
  }

  void CreateWriteBufferQueue() {
    write_queue_ = new DvrWriteBufferQueue(
        ProducerQueue::Create(config_builder_.Build(), UsagePolicy{}));
    ASSERT_NE(nullptr, write_queue_);
  }

  void AllocateBuffers(size_t buffer_count) {
    auto status = write_queue_->producer_queue()->AllocateBuffers(
        kBufferWidth, kBufferHeight, kLayerCount, kBufferFormat, kBufferUsage,
        buffer_count);
    ASSERT_TRUE(status.ok());
  }

  void HandleBufferAvailable() {
    buffer_available_count_ += 1;
    ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_);
@@ -75,22 +60,26 @@ class DvrBufferQueueTest : public ::testing::Test {
             buffer_removed_count_);
  }

  ProducerQueueConfigBuilder config_builder_;
  DvrWriteBufferQueue* write_queue_{nullptr};
  int buffer_available_count_{0};
  int buffer_removed_count_{0};
};

TEST_F(DvrBufferQueueTest, TestWrite_QueueCreateDestroy) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/0, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  dvrWriteBufferQueueDestroy(write_queue_);
  write_queue_ = nullptr;
}

TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);

@@ -99,10 +88,13 @@ TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
}

TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/0, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBufferQueue* read_queue = nullptr;
  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);

  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, read_queue);
@@ -111,11 +103,14 @@ TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
}

TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/0, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBufferQueue* read_queue1 = nullptr;
  DvrReadBufferQueue* read_queue2 = nullptr;
  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);
  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue1);

  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, read_queue1);
@@ -130,8 +125,10 @@ TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
}

TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(3));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBuffer* read_buffer = nullptr;
  DvrWriteBuffer* write_buffer = nullptr;
@@ -164,8 +161,10 @@ TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
}

TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  static constexpr int kTimeout = 0;
  DvrReadBufferQueue* read_queue = nullptr;
@@ -173,7 +172,7 @@ TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
  DvrWriteBuffer* wb = nullptr;
  int fence_fd = -1;

  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);

  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, read_queue);
@@ -193,7 +192,7 @@ TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
  ASSERT_TRUE(dvrWriteBufferIsValid(wb));
  ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
           wb, fence_fd);
  pdx::LocalHandle release_fence(fence_fd);
  android::base::unique_fd release_fence(fence_fd);

  // Post buffer to the read_queue.
  TestMeta seq = 42U;
@@ -215,7 +214,7 @@ TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
  ALOGD_IF(TRACE,
           "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
           fence_fd);
  pdx::LocalHandle acquire_fence(fence_fd);
  android::base::unique_fd acquire_fence(fence_fd);

  // Release buffer to the write_queue.
  ret = dvrReadBufferRelease(rb, -1);
@@ -234,40 +233,52 @@ TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
}

TEST_F(DvrBufferQueueTest, TestGetExternalSurface) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/0, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  ANativeWindow* window = nullptr;

  // The |write_queue_| doesn't have proper metadata (must be
  // DvrNativeBufferMetadata) configured during creation.
  int ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
  ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
  ASSERT_EQ(-EINVAL, ret);
  ASSERT_EQ(nullptr, window);
  dvrWriteBufferQueueDestroy(write_queue_);
  write_queue_ = nullptr;

  // A write queue with DvrNativeBufferMetadata should work fine.
  auto config = ProducerQueueConfigBuilder()
                    .SetMetadata<DvrNativeBufferMetadata>()
                    .Build();
  std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
      write_queue(
          new DvrWriteBufferQueue(ProducerQueue::Create(config, UsagePolicy{})),
          dvrWriteBufferQueueDestroy);
  ASSERT_NE(nullptr, write_queue.get());
  ASSERT_EQ(nullptr, write_queue_);

  ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, write_queue_);

  ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
  ret = dvrWriteBufferQueueGetExternalSurface(write_queue_, &window);
  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, window);

  sp<Surface> surface = static_cast<Surface*>(window);
  ASSERT_TRUE(Surface::isValid(surface));
  // TODO(b/64723700): Remove dependencies of Android platform bits so that we
  // can run dvr_buffer_queue-test in DTS.
  uint32_t width = ANativeWindow_getWidth(window);
  uint32_t height = ANativeWindow_getHeight(window);
  uint32_t format = ANativeWindow_getFormat(window);
  ASSERT_EQ(kBufferWidth, width);
  ASSERT_EQ(kBufferHeight, height);
  ASSERT_EQ(kBufferFormat, format);
}

// Create buffer queue of three buffers and dequeue three buffers out of it.
// Before each dequeue operation, we resize the buffer queue and expect the
// queue always return buffer with desired dimension.
TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  static constexpr int kTimeout = 0;
  int fence_fd = -1;
@@ -281,7 +292,7 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
  AHardwareBuffer* ahb3 = nullptr;
  AHardwareBuffer_Desc buffer_desc;

  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);

  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, read_queue);
@@ -314,7 +325,7 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
  ASSERT_EQ(0, ret);
  ASSERT_TRUE(dvrWriteBufferIsValid(wb1));
  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1);
  pdx::LocalHandle release_fence1(fence_fd);
  android::base::unique_fd release_fence1(fence_fd);

  // Check the buffer dimension.
  ret = dvrWriteBufferGetAHardwareBuffer(wb1, &ahb1);
@@ -341,7 +352,7 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
  ASSERT_TRUE(dvrWriteBufferIsValid(wb2));
  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2,
           fence_fd);
  pdx::LocalHandle release_fence2(fence_fd);
  android::base::unique_fd release_fence2(fence_fd);

  // Check the buffer dimension, should be new width
  ret = dvrWriteBufferGetAHardwareBuffer(wb2, &ahb2);
@@ -367,7 +378,7 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
  ASSERT_TRUE(dvrWriteBufferIsValid(wb3));
  ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3,
           fence_fd);
  pdx::LocalHandle release_fence3(fence_fd);
  android::base::unique_fd release_fence3(fence_fd);

  // Check the buffer dimension, should be new width
  ret = dvrWriteBufferGetAHardwareBuffer(wb3, &ahb3);
@@ -387,9 +398,10 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) {

TEST_F(DvrBufferQueueTest, DequeueEmptyMetadata) {
  // Overrides default queue parameters: Empty metadata.
  config_builder_.SetMetadata<void>();
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(1));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/1, /*metadata_size=*/0, &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBuffer* rb = nullptr;
  DvrWriteBuffer* wb = nullptr;
@@ -416,8 +428,10 @@ TEST_F(DvrBufferQueueTest, DequeueEmptyMetadata) {
}

TEST_F(DvrBufferQueueTest, DequeueMismatchMetadata) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(1));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      /*capacity=*/1, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBuffer* rb = nullptr;
  DvrWriteBuffer* wb = nullptr;
@@ -451,11 +465,13 @@ TEST_F(DvrBufferQueueTest, DequeueMismatchMetadata) {
}

TEST_F(DvrBufferQueueTest, TestReadQueueEventFd) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  DvrReadBufferQueue* read_queue = nullptr;
  int ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
  ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);

  ASSERT_EQ(0, ret);
  ASSERT_NE(nullptr, read_queue);
@@ -468,8 +484,10 @@ TEST_F(DvrBufferQueueTest, TestReadQueueEventFd) {
// Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
// the corresponding AHardwareBuffer handle stays the same.
TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) {
  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
  int ret = dvrWriteBufferQueueCreate(
      kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
      kQueueCapacity, sizeof(TestMeta), &write_queue_);
  ASSERT_EQ(0, ret);

  int fence_fd = -1;
  DvrReadBufferQueue* read_queue = nullptr;
@@ -621,6 +639,3 @@ TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) {
}

}  // namespace

}  // namespace dvr
}  // namespace android