Adding onFrameAvailable test for BLASTBufferQueue

Bug: 142546708
Test: build, boot, libgui_test
Change-Id: I92a03e777334b7b4729338c7e3a75dad1db8b613
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index a5f115e..db1ac24 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -18,8 +18,14 @@
 
 #include <gui/BLASTBufferQueue.h>
 
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
 #include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/DisplayInfo.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
 
 #include <gtest/gtest.h>
 
@@ -27,10 +33,8 @@
 
 namespace android {
 
-const int DEFAULT_WIDTH = 100;
-const int DEFAULT_HEIGHT = 100;
-
 using Transaction = SurfaceComposerClient::Transaction;
+using android::hardware::graphics::common::V1_2::BufferUsage;
 
 class BLASTBufferQueueHelper {
 public:
@@ -47,12 +51,24 @@
     }
 
     int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
+
     int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
+
     Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
+
+    sp<IGraphicBufferProducer> getIGraphicBufferProducer() {
+        return mBlastBufferQueueAdapter->getIGraphicBufferProducer();
+    }
+
     const sp<SurfaceControl> getSurfaceControl() {
         return mBlastBufferQueueAdapter->mSurfaceControl;
     }
 
+    void waitForCallback() {
+        std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
+        mBlastBufferQueueAdapter->mDequeueWaitCV.wait_for(lock, 1s);
+    }
+
 private:
     sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
 };
@@ -73,39 +89,149 @@
     }
 
     void SetUp() {
+        mComposer = ComposerService::getComposerService();
         mClient = new SurfaceComposerClient();
-        mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
-                                                 DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
+        mDisplayToken = mClient->getInternalDisplayToken();
+        ASSERT_NE(nullptr, mDisplayToken.get());
+        Transaction t;
+        t.setDisplayLayerStack(mDisplayToken, 0);
+        t.apply();
+        t.clear();
+
+        DisplayInfo info;
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplayToken, &info));
+        mDisplayWidth = info.w;
+        mDisplayHeight = info.h;
+
+        mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
+                                                 mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
+                                                 ISurfaceComposerClient::eFXSurfaceBufferState,
+                                                 /*parent*/ nullptr);
+        t.setLayerStack(mSurfaceControl, 0)
+                .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
+                .setFrame(mSurfaceControl, Rect(0, 0, mDisplayWidth, mDisplayHeight))
+                .show(mSurfaceControl)
+                .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
+                .apply();
+    }
+
+    void fillBuffer(uint32_t* bufData, uint32_t width, uint32_t height, uint32_t stride, uint8_t r,
+                    uint8_t g, uint8_t b) {
+        for (uint32_t row = 0; row < height; row++) {
+            for (uint32_t col = 0; col < width; col++) {
+                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+                *pixel = r;
+                *(pixel + 1) = g;
+                *(pixel + 2) = b;
+                *(pixel + 3) = 255;
+            }
+        }
+    }
+
+    void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b) {
+        const auto width = mScreenCaptureBuf->getWidth();
+        const auto height = mScreenCaptureBuf->getHeight();
+        const auto stride = mScreenCaptureBuf->getStride();
+
+        uint32_t* bufData;
+        mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
+                                reinterpret_cast<void**>(&bufData));
+
+        for (uint32_t row = 0; row < height; row++) {
+            for (uint32_t col = 0; col < width; col++) {
+                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+                EXPECT_EQ(r, *(pixel));
+                EXPECT_EQ(g, *(pixel + 1));
+                EXPECT_EQ(b, *(pixel + 2));
+            }
+        }
+        mScreenCaptureBuf->unlock();
+        ASSERT_EQ(false, ::testing::Test::HasFailure());
     }
 
     sp<SurfaceComposerClient> mClient;
+    sp<ISurfaceComposer> mComposer;
+
+    sp<IBinder> mDisplayToken;
+
     sp<SurfaceControl> mSurfaceControl;
+    sp<GraphicBuffer> mScreenCaptureBuf;
+
+    uint32_t mDisplayWidth;
+    uint32_t mDisplayHeight;
 };
 
 TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
     // create BLASTBufferQueue adapter associated with this surface
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
-    ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
-    ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
+    ASSERT_EQ(mDisplayWidth, adapter.getWidth());
+    ASSERT_EQ(mDisplayHeight, adapter.getHeight());
     ASSERT_EQ(nullptr, adapter.getNextTransaction());
 }
 
 TEST_F(BLASTBufferQueueTest, Update) {
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     sp<SurfaceControl> updateSurface =
-            mClient->createSurface(String8("UpdateTest"), DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2,
-                                   PIXEL_FORMAT_RGB_888);
-    adapter.update(updateSurface, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
+            mClient->createSurface(String8("UpdateTest"), mDisplayWidth / 2, mDisplayHeight / 2,
+                                   PIXEL_FORMAT_RGBA_8888);
+    adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
     ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
-    ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
-    ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
+    ASSERT_EQ(mDisplayWidth / 2, adapter.getWidth());
+    ASSERT_EQ(mDisplayHeight / 2, adapter.getHeight());
 }
 
 TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     Transaction next;
     adapter.setNextTransaction(&next);
     ASSERT_EQ(&next, adapter.getNextTransaction());
 }
+
+TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) {
+    uint8_t r = 255;
+    uint8_t g = 0;
+    uint8_t b = 0;
+
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+    auto igbProducer = adapter.getIGraphicBufferProducer();
+    ASSERT_NE(nullptr, igbProducer.get());
+    IGraphicBufferProducer::QueueBufferOutput qbOutput;
+    ASSERT_EQ(NO_ERROR,
+              igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+                                   &qbOutput));
+    ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(3));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buf;
+    auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
+                                          PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                          nullptr, nullptr);
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+    ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+    uint32_t* bufData;
+    buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+              reinterpret_cast<void**>(&bufData));
+    fillBuffer(bufData, buf->getWidth(), buf->getHeight(), buf->getStride(), r, g, b);
+    buf->unlock();
+
+    IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN,
+                                                   Rect(mDisplayWidth, mDisplayHeight),
+                                                   NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+                                                   Fence::NO_FENCE);
+    igbProducer->queueBuffer(slot, input, &qbOutput);
+
+    adapter.waitForCallback();
+
+    // capture screen and verify that it is red
+    bool capturedSecureLayers;
+    ASSERT_EQ(NO_ERROR,
+              mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
+                                       ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
+                                       mDisplayWidth, mDisplayHeight,
+                                       /*useIdentityTransform*/ false));
+    ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b));
+}
 } // namespace android