More dvr display test.

Refine the single layer single buffer test by displaying all three basic
colors, so that the color channels can be visually checked.

Add DisplayWithDoubleBuffering, which uses single direct surface, single
write buffer queue, two write buffers. Should observe blinking screen:
three primary color blocks display in one sequence and in another
sequence.

Add DisplayWithTwoHardwareLayers, which uses two direct surfaces.
Ahould observe three secondary colors.

Bug: 69267804
Test: mma, manually push and run dvr_display-test in a rooted 8.1.0 phone
Visually check the colors on screen.

Change-Id: Idd3458c9a654a7d947c7e2f5797c268a2d9a782b
(cherry picked from commit 8ed8c7a0892126b06564c640e64aa6c0d67afbcb)
diff --git a/libs/vr/libdvr/tests/dvr_api_test.h b/libs/vr/libdvr/tests/dvr_api_test.h
index 648af75..d8359e7 100644
--- a/libs/vr/libdvr/tests/dvr_api_test.h
+++ b/libs/vr/libdvr/tests/dvr_api_test.h
@@ -3,8 +3,6 @@
 
 #include <gtest/gtest.h>
 
-#define ASSERT_NOT_NULL(x) ASSERT_TRUE((x) != nullptr)
-
 /** DvrTestBase loads the libdvr.so at runtime and get the Dvr API version 1. */
 class DvrApiTest : public ::testing::Test {
  protected:
@@ -17,11 +15,11 @@
     // https://github.com/android-ndk/ndk/issues/360
     flags |= RTLD_NODELETE;
     platform_handle_ = dlopen("libdvr.so", flags);
-    ASSERT_NOT_NULL(platform_handle_) << "Dvr shared library missing.";
+    ASSERT_NE(nullptr, platform_handle_) << "Dvr shared library missing.";
 
     auto dvr_get_api = reinterpret_cast<decltype(&dvrGetApi)>(
         dlsym(platform_handle_, "dvrGetApi"));
-    ASSERT_NOT_NULL(dvr_get_api) << "Platform library missing dvrGetApi.";
+    ASSERT_NE(nullptr, dvr_get_api) << "Platform library missing dvrGetApi.";
 
     ASSERT_EQ(dvr_get_api(&api_, sizeof(api_), /*version=*/1), 0)
         << "Unable to find compatible Dvr API.";
diff --git a/libs/vr/libdvr/tests/dvr_display-test.cpp b/libs/vr/libdvr/tests/dvr_display-test.cpp
index 1165573..c72f940 100644
--- a/libs/vr/libdvr/tests/dvr_display-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display-test.cpp
@@ -16,20 +16,58 @@
 
 class DvrDisplayTest : public DvrApiTest {
  protected:
+  void SetUp() override {
+    DvrApiTest::SetUp();
+    int ret = api_.GetNativeDisplayMetrics(sizeof(display_metrics_),
+                                           &display_metrics_);
+    ASSERT_EQ(ret, 0) << "Failed to get display metrics.";
+    ALOGD(
+        "display_width: %d, display_height: %d, display_x_dpi: %d, "
+        "display_y_dpi: %d, vsync_period_ns: %d.",
+        display_metrics_.display_width, display_metrics_.display_height,
+        display_metrics_.display_x_dpi, display_metrics_.display_y_dpi,
+        display_metrics_.vsync_period_ns);
+  }
+
   void TearDown() override {
     if (write_queue_ != nullptr) {
       api_.WriteBufferQueueDestroy(write_queue_);
       write_queue_ = nullptr;
     }
+    if (direct_surface_ != nullptr) {
+      api_.SurfaceDestroy(direct_surface_);
+      direct_surface_ = nullptr;
+    }
     DvrApiTest::TearDown();
   }
 
+  /* Convert a write buffer to an android hardware buffer and fill in
+   * color_textures evenly to the buffer.
+   * AssertionError if the width of the buffer is not equal to the input width,
+   * AssertionError if the height of the buffer is not equal to the input
+   * height.
+   */
+  void FillWriteBuffer(DvrWriteBuffer* write_buffer,
+                       const std::vector<uint32_t>& color_textures,
+                       uint32_t width, uint32_t height);
+
+  // Write buffer queue properties.
+  static constexpr uint64_t kUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+                                     AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
+                                     AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+  uint32_t kFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+  static constexpr size_t kMetadataSize = 0;
+  static constexpr int kTimeoutMs = 1000;  // Time for getting buffer.
+  uint32_t kLayerCount = 1;
   DvrWriteBufferQueue* write_queue_ = nullptr;
+  DvrSurface* direct_surface_ = nullptr;
+
+  // Device display properties.
+  DvrNativeDisplayMetrics display_metrics_;
 };
 
-TEST_F(DvrDisplayTest, DisplaySingleColor) {
-  // Create direct surface.
-  DvrSurface* direct_surface = nullptr;
+TEST_F(DvrDisplayTest, DisplayWithOneBuffer) {
+  // Create a direct surface.
   std::vector<DvrSurfaceAttribute> direct_surface_attributes = {
       {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
        .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
@@ -43,73 +81,32 @@
   };
   int ret =
       api_.SurfaceCreate(direct_surface_attributes.data(),
-                         direct_surface_attributes.size(), &direct_surface);
+                         direct_surface_attributes.size(), &direct_surface_);
   ASSERT_EQ(ret, 0) << "Failed to create direct surface.";
 
-  // Get screen dimension.
-  DvrNativeDisplayMetrics display_metrics;
-  ret = api_.GetNativeDisplayMetrics(sizeof(display_metrics), &display_metrics);
-  ASSERT_EQ(ret, 0) << "Failed to get display metrics.";
-  ALOGD(
-      "display_width: %d, display_height: %d, display_x_dpi: %d, "
-      "display_y_dpi: %d, vsync_period_ns: %d.",
-      display_metrics.display_width, display_metrics.display_height,
-      display_metrics.display_x_dpi, display_metrics.display_y_dpi,
-      display_metrics.vsync_period_ns);
-
   // Create a buffer queue with the direct surface.
-  constexpr uint32_t kLayerCount = 1;
-  constexpr uint64_t kUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
-                              AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
-                              AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
-  constexpr uint32_t kFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
   constexpr size_t kCapacity = 1;
-  constexpr size_t kMetadataSize = 0;
-  uint32_t width = display_metrics.display_width;
-  uint32_t height = display_metrics.display_height;
+  uint32_t width = display_metrics_.display_width;
+  uint32_t height = display_metrics_.display_height;
   ret = api_.SurfaceCreateWriteBufferQueue(
-      direct_surface, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+      direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity,
       kMetadataSize, &write_queue_);
   EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
-  ASSERT_NOT_NULL(write_queue_) << "Write buffer queue should not be null.";
+  ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null.";
 
   // Get buffer from WriteBufferQueue.
   DvrWriteBuffer* write_buffer = nullptr;
-  constexpr int kTimeoutMs = 1000;
   DvrNativeBufferMetadata out_meta;
   int out_fence_fd = -1;
   ret = api_.WriteBufferQueueGainBuffer(write_queue_, kTimeoutMs, &write_buffer,
                                         &out_meta, &out_fence_fd);
   EXPECT_EQ(0, ret) << "Failed to get the buffer.";
-  ASSERT_NOT_NULL(write_buffer) << "Gained buffer should not be null.";
+  ASSERT_NE(nullptr, write_buffer) << "Gained buffer should not be null.";
 
-  // Convert to an android hardware buffer.
-  AHardwareBuffer* ah_buffer{nullptr};
-  ret = api_.WriteBufferGetAHardwareBuffer(write_buffer, &ah_buffer);
-  EXPECT_EQ(0, ret) << "Failed to get a hardware buffer from the write buffer.";
-  ASSERT_NOT_NULL(ah_buffer) << "AHardware buffer should not be null.";
-
-  // Change the content of the android hardware buffer.
-  void* buffer_data{nullptr};
-  int32_t fence = -1;
-  ret = AHardwareBuffer_lock(ah_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
-                             fence, nullptr, &buffer_data);
-  EXPECT_EQ(0, ret) << "Failed to lock the hardware buffer.";
-  ASSERT_NOT_NULL(buffer_data) << "Buffer data should not be null.";
-
-  uint32_t color_texture = 0xff0000ff;  // Red color in RGBA.
-  for (uint32_t i = 0; i < width * height; ++i) {
-    memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
-                                   i * sizeof(color_texture)),
-           &color_texture, sizeof(color_texture));
-  }
-
-  fence = -1;
-  ret = AHardwareBuffer_unlock(ah_buffer, &fence);
-  EXPECT_EQ(0, ret) << "Failed to unlock the hardware buffer.";
-
-  // Release the android hardware buffer.
-  AHardwareBuffer_release(ah_buffer);
+  // Color the write buffer.
+  FillWriteBuffer(write_buffer,
+                  {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
+                  width, height);
 
   // Post buffer.
   int ready_fence_fd = -1;
@@ -118,4 +115,237 @@
   EXPECT_EQ(0, ret) << "Failed to post the buffer.";
 
   sleep(5);  // For visual check on the device under test.
+  // Should observe three primary colors on the screen center.
+}
+
+TEST_F(DvrDisplayTest, DisplayWithDoubleBuffering) {
+  // Create a direct surface.
+  std::vector<DvrSurfaceAttribute> direct_surface_attributes = {
+      {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+      {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+       .value.int32_value = 10},
+      {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+  };
+  int ret =
+      api_.SurfaceCreate(direct_surface_attributes.data(),
+                         direct_surface_attributes.size(), &direct_surface_);
+  ASSERT_EQ(ret, 0) << "Failed to create direct surface.";
+
+  // Create a buffer queue with the direct surface.
+  constexpr size_t kCapacity = 2;
+  uint32_t width = display_metrics_.display_width;
+  uint32_t height = display_metrics_.display_height;
+  ret = api_.SurfaceCreateWriteBufferQueue(
+      direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+      kMetadataSize, &write_queue_);
+  EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+  ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null.";
+
+  int num_display_cycles_in_5s = 5 / (display_metrics_.vsync_period_ns / 1e9);
+  ALOGD("The number of display cycles: %d", num_display_cycles_in_5s);
+  int bufferhub_id_prev_write_buffer = -1;
+  for (int i = 0; i < num_display_cycles_in_5s; ++i) {
+    // Get a buffer from the WriteBufferQueue.
+    DvrWriteBuffer* write_buffer = nullptr;
+    DvrNativeBufferMetadata out_meta;
+    int out_fence_fd = -1;
+    ret = api_.WriteBufferQueueGainBuffer(
+        write_queue_, kTimeoutMs, &write_buffer, &out_meta, &out_fence_fd);
+    EXPECT_EQ(0, ret) << "Failed to get the a write buffer.";
+    ASSERT_NE(nullptr, write_buffer) << "The gained buffer should not be null.";
+
+    int bufferhub_id = api_.WriteBufferGetId(write_buffer);
+    ALOGD("Display cycle: %d, bufferhub id of the write buffer: %d", i,
+          bufferhub_id);
+    EXPECT_NE(bufferhub_id_prev_write_buffer, bufferhub_id)
+        << "Double buffering should be using the two buffers in turns, not "
+           "reusing the same write buffer.";
+    bufferhub_id_prev_write_buffer = bufferhub_id;
+
+    // Color the write buffer.
+    if (i % 2) {
+      FillWriteBuffer(write_buffer, {0xffff0000, 0xff00ff00, 0xff0000ff}, width,
+                      height);
+    } else {
+      FillWriteBuffer(write_buffer, {0xff00ff00, 0xff0000ff, 0xffff0000}, width,
+                      height);
+    }
+
+    // Post the write buffer.
+    int ready_fence_fd = -1;
+    ret = api_.WriteBufferQueuePostBuffer(write_queue_, write_buffer, &out_meta,
+                                          ready_fence_fd);
+    EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+  }
+  // Should observe blinking screen in secondary colors
+  // although it is actually displaying primary colors.
+}
+
+TEST_F(DvrDisplayTest, DisplayWithTwoHardwareLayers) {
+  // Create the direct_surface_0 of z order 10 and direct_surface_1 of z
+  // order 11.
+  DvrSurface* direct_surface_0 = nullptr;
+  std::vector<DvrSurfaceAttribute> direct_surface_0_attributes = {
+      {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+      {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+       .value.int32_value = 10},
+      {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+  };
+  int ret =
+      api_.SurfaceCreate(direct_surface_0_attributes.data(),
+                         direct_surface_0_attributes.size(), &direct_surface_0);
+  EXPECT_EQ(ret, 0) << "Failed to create direct surface.";
+
+  DvrSurface* direct_surface_1 = nullptr;
+  std::vector<DvrSurfaceAttribute> direct_surface_1_attributes = {
+      {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+      {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+       .value.int32_value = 11},
+      {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+       .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+       .value.bool_value = true},
+  };
+  ret =
+      api_.SurfaceCreate(direct_surface_1_attributes.data(),
+                         direct_surface_1_attributes.size(), &direct_surface_1);
+  EXPECT_EQ(ret, 0) << "Failed to create direct surface.";
+
+  // Create a buffer queue for each of the direct surfaces.
+  constexpr size_t kCapacity = 1;
+  uint32_t width = display_metrics_.display_width;
+  uint32_t height = display_metrics_.display_height;
+
+  DvrWriteBufferQueue* write_queue_0 = nullptr;
+  ret = api_.SurfaceCreateWriteBufferQueue(
+      direct_surface_0, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+      kMetadataSize, &write_queue_0);
+  EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+  EXPECT_NE(nullptr, write_queue_0) << "Write buffer queue should not be null.";
+
+  DvrWriteBufferQueue* write_queue_1 = nullptr;
+  ret = api_.SurfaceCreateWriteBufferQueue(
+      direct_surface_1, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+      kMetadataSize, &write_queue_1);
+  EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+  EXPECT_NE(nullptr, write_queue_1) << "Write buffer queue should not be null.";
+
+  // Get a buffer from each of the write buffer queues.
+  DvrWriteBuffer* write_buffer_0 = nullptr;
+  DvrNativeBufferMetadata out_meta_0;
+  int out_fence_fd = -1;
+  ret = api_.WriteBufferQueueGainBuffer(
+      write_queue_0, kTimeoutMs, &write_buffer_0, &out_meta_0, &out_fence_fd);
+  EXPECT_EQ(0, ret) << "Failed to get the buffer.";
+  EXPECT_NE(nullptr, write_buffer_0) << "Gained buffer should not be null.";
+
+  DvrWriteBuffer* write_buffer_1 = nullptr;
+  DvrNativeBufferMetadata out_meta_1;
+  out_fence_fd = -1;
+  ret = api_.WriteBufferQueueGainBuffer(
+      write_queue_1, kTimeoutMs, &write_buffer_1, &out_meta_1, &out_fence_fd);
+  EXPECT_EQ(0, ret) << "Failed to get the buffer.";
+  EXPECT_NE(nullptr, write_buffer_1) << "Gained buffer should not be null.";
+
+  // Color the write buffers.
+  FillWriteBuffer(write_buffer_0, {0xffff0000, 0xff00ff00, 0xff0000ff}, width,
+                  height);
+  FillWriteBuffer(write_buffer_1, {0x7f00ff00, 0x7f0000ff, 0x7fff0000}, width,
+                  height);
+
+  // Post buffers.
+  int ready_fence_fd = -1;
+  ret = api_.WriteBufferQueuePostBuffer(write_queue_0, write_buffer_0,
+                                        &out_meta_0, ready_fence_fd);
+  EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+
+  ready_fence_fd = -1;
+  ret = api_.WriteBufferQueuePostBuffer(write_queue_1, write_buffer_1,
+                                        &out_meta_1, ready_fence_fd);
+  EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+
+  sleep(5);  // For visual check on the device under test.
+  // Should observe three secondary colors.
+
+  // Test finished. Clean up buffers and surfaces.
+  if (write_queue_0 != nullptr) {
+    api_.WriteBufferQueueDestroy(write_queue_0);
+    write_queue_0 = nullptr;
+  }
+  if (write_queue_1 != nullptr) {
+    api_.WriteBufferQueueDestroy(write_queue_1);
+    write_queue_1 = nullptr;
+  }
+  if (direct_surface_0 != nullptr) {
+    api_.SurfaceDestroy(direct_surface_0);
+  }
+  if (direct_surface_1 != nullptr) {
+    api_.SurfaceDestroy(direct_surface_1);
+  }
+}
+
+void DvrDisplayTest::FillWriteBuffer(
+    DvrWriteBuffer* write_buffer, const std::vector<uint32_t>& color_textures,
+    uint32_t width, uint32_t height) {
+  uint32_t num_colors = color_textures.size();
+  // Convert the first write buffer to an android hardware buffer.
+  AHardwareBuffer* ah_buffer = nullptr;
+  int ret = api_.WriteBufferGetAHardwareBuffer(write_buffer, &ah_buffer);
+  ASSERT_EQ(0, ret) << "Failed to get a hardware buffer from the write buffer.";
+  ASSERT_NE(nullptr, ah_buffer) << "AHardware buffer should not be null.";
+  AHardwareBuffer_Desc ah_buffer_describe;
+  AHardwareBuffer_describe(ah_buffer, &ah_buffer_describe);
+  ASSERT_EQ(ah_buffer_describe.format, kFormat)
+      << "The format of the android hardware buffer is wrong.";
+  ASSERT_EQ(ah_buffer_describe.layers, kLayerCount)
+      << "The obtained android hardware buffer should have 2 layers.";
+  ASSERT_EQ(ah_buffer_describe.width, width)
+      << "The obtained android hardware buffer width is wrong.";
+  ASSERT_EQ(ah_buffer_describe.height, height)
+      << "The obtained android hardware buffer height is wrong.";
+  // Change the content of the android hardware buffer.
+  void* buffer_data = nullptr;
+  int32_t fence = -1;
+  ret = AHardwareBuffer_lock(ah_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+                             fence, nullptr, &buffer_data);
+  ASSERT_EQ(0, ret) << "Failed to lock the hardware buffer.";
+  ASSERT_NE(nullptr, buffer_data) << "Buffer data should not be null.";
+
+  uint32_t num_pixels = width * height / num_colors;
+  for (uint32_t color_index = 0; color_index < num_colors - 1; ++color_index) {
+    uint32_t color_texture = color_textures[color_index];
+    for (uint32_t i = 0; i < num_pixels; ++i) {
+      memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
+                                     (i + num_pixels * color_index) *
+                                         sizeof(color_texture)),
+             &color_texture, sizeof(color_texture));
+    }
+  }
+  uint32_t color_texture = color_textures[num_colors - 1];
+  uint32_t num_colored_pixels = num_pixels * (num_colors - 1);
+  num_pixels = width * height - num_colored_pixels;
+  for (uint32_t i = 0; i < num_pixels; ++i) {
+    memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
+                                   (i + num_colored_pixels) *
+                                       sizeof(color_texture)),
+           &color_texture, sizeof(color_texture));
+  }
+  fence = -1;
+  ret = AHardwareBuffer_unlock(ah_buffer, &fence);
+  EXPECT_EQ(0, ret) << "Failed to unlock the hardware buffer.";
+
+  // Release the android hardware buffer.
+  AHardwareBuffer_release(ah_buffer);
 }