Merge "Add VTS test for clearing buffer slots to Composer HIDL and AIDL"
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 4822678..b66ee19 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -657,6 +657,7 @@
                                                              IComposerClient::Attribute::WIDTH);
         mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
                                                               IComposerClient::Attribute::HEIGHT);
+
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<TestCommandReader>();
     }
@@ -666,11 +667,13 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
     }
 
-    NativeHandleWrapper allocate() {
+    NativeHandleWrapper allocate() { return allocate(mDisplayWidth, mDisplayHeight); }
+
+    NativeHandleWrapper allocate(uint32_t width, uint32_t height) {
         uint64_t usage =
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
                                       BufferUsage::COMPOSER_OVERLAY);
-        return mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
+        return mGralloc->allocate(width, height, 1, PixelFormat::RGBA_8888, usage);
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -884,6 +887,57 @@
 }
 
 /**
+ * Test IComposerClient::Command::SET_LAYER_BUFFER with the behavior used for clearing buffer slots.
+ */
+TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER_TO_CLEAR_BUFFER_SLOTS) {
+    // A buffer used to clear buffer slots
+    auto clearSlotBuffer = allocate(1u, 1u);
+
+    auto handle1 = allocate();
+    ASSERT_NE(nullptr, handle1.get());
+    IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+    mWriter->setLayerDisplayFrame(displayFrame);
+    mWriter->setLayerBuffer(0, handle1.get(), -1);
+    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        GTEST_SUCCEED() << "Composition change requested, skipping test";
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    // Ensure we can clear a buffer slot and then set that same slot with a new buffer
+    auto handle2 = allocate();
+    ASSERT_NE(nullptr, handle2.get());
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBuffer(0, clearSlotBuffer.get(), -1);
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBuffer(0, handle2.get(), -1);
+    mWriter->validateDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+}
+
+/**
  * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
  */
 TEST_P(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 0c8742f..e35d07b 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -91,7 +91,7 @@
     void setClientTarget(int64_t display, uint32_t slot, const native_handle_t* target,
                          int acquireFence, Dataspace dataspace, const std::vector<Rect>& damage) {
         ClientTarget clientTargetCommand;
-        clientTargetCommand.buffer = getBuffer(slot, target, acquireFence);
+        clientTargetCommand.buffer = getBufferCommand(slot, target, acquireFence);
         clientTargetCommand.dataspace = dataspace;
         clientTargetCommand.damage.assign(damage.begin(), damage.end());
         getDisplayCommand(display).clientTarget.emplace(std::move(clientTargetCommand));
@@ -100,7 +100,7 @@
     void setOutputBuffer(int64_t display, uint32_t slot, const native_handle_t* buffer,
                          int releaseFence) {
         getDisplayCommand(display).virtualDisplayOutputBuffer.emplace(
-                getBuffer(slot, buffer, releaseFence));
+                getBufferCommand(slot, buffer, releaseFence));
     }
 
     void validateDisplay(int64_t display,
@@ -132,7 +132,14 @@
 
     void setLayerBuffer(int64_t display, int64_t layer, uint32_t slot,
                         const native_handle_t* buffer, int acquireFence) {
-        getLayerCommand(display, layer).buffer = getBuffer(slot, buffer, acquireFence);
+        getLayerCommand(display, layer).buffer = getBufferCommand(slot, buffer, acquireFence);
+    }
+
+    void setLayerBufferWithNewCommand(int64_t display, int64_t layer, uint32_t slot,
+                                      const native_handle_t* buffer, int acquireFence) {
+        flushLayerCommand();
+        getLayerCommand(display, layer).buffer = getBufferCommand(slot, buffer, acquireFence);
+        flushLayerCommand();
     }
 
     void setLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector<Rect>& damage) {
@@ -234,7 +241,7 @@
     std::vector<DisplayCommand> mCommands;
     const int64_t mDisplay;
 
-    Buffer getBuffer(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
+    Buffer getBufferCommand(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
         Buffer bufferCommand;
         bufferCommand.slot = static_cast<int32_t>(slot);
         if (bufferHandle) bufferCommand.handle.emplace(::android::dupToAidl(bufferHandle));
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 4d7bf13..0f00fd6 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1131,17 +1131,21 @@
         }
     }
 
-    sp<GraphicBuffer> allocate(::android::PixelFormat pixelFormat) {
+    sp<GraphicBuffer> allocate(uint32_t width, uint32_t height,
+                               ::android::PixelFormat pixelFormat) {
         return sp<GraphicBuffer>::make(
-                static_cast<uint32_t>(getPrimaryDisplay().getDisplayWidth()),
-                static_cast<uint32_t>(getPrimaryDisplay().getDisplayHeight()), pixelFormat,
-                /*layerCount*/ 1U,
-                (static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
-                 static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
-                 static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY)),
+                width, height, pixelFormat, /*layerCount*/ 1U,
+                static_cast<uint64_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+                        static_cast<uint64_t>(common::BufferUsage::CPU_READ_OFTEN) |
+                        static_cast<uint64_t>(common::BufferUsage::COMPOSER_OVERLAY),
                 "VtsHalGraphicsComposer3_TargetTest");
     }
 
+    sp<GraphicBuffer> allocate(::android::PixelFormat pixelFormat) {
+        return allocate(static_cast<uint32_t>(getPrimaryDisplay().getDisplayWidth()),
+                        static_cast<uint32_t>(getPrimaryDisplay().getDisplayHeight()), pixelFormat);
+    }
+
     void sendRefreshFrame(const VtsDisplay& display, const VsyncPeriodChangeTimeline* timeline) {
         if (timeline != nullptr) {
             // Refresh time should be before newVsyncAppliedTimeNanos
@@ -1642,6 +1646,33 @@
     execute();
 }
 
+TEST_P(GraphicsComposerAidlCommandTest, SetLayerBufferWithSlotsToClear) {
+    auto clearSlotBuffer = allocate(1u, 1u, ::android::PIXEL_FORMAT_RGB_888);
+    ASSERT_NE(nullptr, clearSlotBuffer);
+    auto clearSlotBufferHandle = clearSlotBuffer->handle;
+
+    const auto buffer1 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer1);
+    const auto handle1 = buffer1->handle;
+    const auto& [layerStatus, layer] =
+            mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
+    EXPECT_TRUE(layerStatus.isOk());
+    auto& writer = getWriter(getPrimaryDisplayId());
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle1, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+
+    // Ensure we can clear a buffer slot and then set that same slot with a new buffer
+    const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
+    ASSERT_NE(nullptr, buffer2);
+    const auto handle2 = buffer2->handle;
+    writer.setLayerBufferWithNewCommand(getPrimaryDisplayId(), layer, /* slot */ 0,
+                                        clearSlotBufferHandle, /*acquireFence*/ -1);
+    writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle2, /*acquireFence*/ -1);
+    execute();
+    ASSERT_TRUE(mReader.takeErrors().empty());
+}
+
 TEST_P(GraphicsComposerAidlCommandTest, SetLayerSurfaceDamage) {
     const auto& [layerStatus, layer] =
             mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);