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

Commit 1e35190f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents 11e66edf d741b3df
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