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

Commit bfdd1132 authored by Tom Murphy's avatar Tom Murphy
Browse files

Add unittesting for the bufferQueueConsumer::acquireBuffer

The bufferQueueConsumer::acquireBuffer code is tricky and hard to maintain. We will need to make changes to this code to implement the new vulkan timings extension. Add unit tests to verify the existing behaviour and prevent breakages.

Test: unit tests added
Flag: Flag: EXEMPT unit tests
Bug: 378669647
Change-Id: I00f3f92a03b861f64b394cbc1c1e6eab64000246
parent 2f4e35ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,11 +51,17 @@ namespace android {

class IConsumerListener;
class IProducerListener;
#ifdef ENABLE_BQC_TESTING
class MockBufferQueueCore;
#endif

class BufferQueueCore : public virtual RefBase {

    friend class BufferQueueProducer;
    friend class BufferQueueConsumer;
#ifdef ENABLE_BQC_TESTING
    friend class TestableBufferQueueCore;
#endif

public:
    // Used as a placeholder slot number when the value isn't pointing to an
+3 −0
Original line number Diff line number Diff line
@@ -51,12 +51,15 @@ cc_test {
        "-Werror",
        "-Wextra",
        "-Wthread-safety",
        // Allow access to buffer queue core private members
        "-DENABLE_BQC_TESTING",
    ],

    srcs: [
        "BLASTBufferQueue_test.cpp",
        "BufferItemConsumer_test.cpp",
        "BufferQueue_test.cpp",
        "BufferQueueConsumer_test.cpp",
        "BufferReleaseChannel_test.cpp",
        "Choreographer_test.cpp",
        "CompositorTiming_test.cpp",
+161 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ENABLE_BQC_TESTING
#define ENABLE_BQC_TESTING
#endif

#define LOG_TAG "BufferQueueConsumer_test"

#include <gui/BufferItem.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <gui/IConsumerListener.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
#include <utils/Timers.h>

#include <mutex>
#include <vector>

#include <gtest/gtest.h>

namespace android {

class TestableBufferQueueCore : public BufferQueueCore {
public:
    TestableBufferQueueCore() = default;
    ~TestableBufferQueueCore() override = default;

    void ConfigureQueueStateViaFriend(const std::vector<android::BufferItem>& initialQueue) {
        this->mQueue.clear();
        for (const auto& item : initialQueue) {
            this->mQueue.push_back(item);
        }
    }

    size_t getQueueSizeForTest() { return this->mQueue.size(); }

    android::BufferItem getQueueFrontForTest() {
        return this->mQueue.empty() ? android::BufferItem() : this->mQueue.itemAt(0);
    }
};

class BufferQueueConsumerVkTimingTest : public ::testing::Test {
protected:
    sp<TestableBufferQueueCore> mTestableCore;
    sp<BufferQueueConsumer> mConsumer;

    virtual void SetUp() override {
        mTestableCore = sp<TestableBufferQueueCore>::make();
        mConsumer = sp<BufferQueueConsumer>::make(mTestableCore);
    }

    virtual void TearDown() override {
        mConsumer.clear();
        mTestableCore.clear();
    }

    android::BufferItem CreateBufferItem(int slot, uint64_t frameNum, nsecs_t timestamp,
                                         bool isReady = true, bool isAutoTimestamp = true,
                                         bool isStale = false, bool isDroppable = true) {
        android::BufferItem item;
        item.mSlot = slot;
        item.mFrameNumber = frameNum;
        item.mTimestamp = timestamp;
        item.mGraphicBuffer = nullptr;
        item.mFence = isReady ? Fence::NO_FENCE : new Fence();
        item.mIsStale = isStale;
        item.mIsDroppable = isDroppable;
        item.mAcquireCalled = false;
        item.mIsAutoTimestamp = isAutoTimestamp;
        item.mCrop = Rect::INVALID_RECT;
        item.mTransform = 0;
        //            item.mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
        item.mDataSpace = HAL_DATASPACE_UNKNOWN;
        item.mSurfaceDamage = Region::INVALID_REGION;
        item.mQueuedBuffer = true;
        item.mAutoRefresh = false;
        item.mApi = 0;
        item.mTransformToDisplayInverse = false;
        return item;
    }

    void runBufferTest(nsecs_t expectedPresentTime, int expectedAcquiredSlotNum,
                       size_t expectedAcquiredFrameNum, size_t expectedNumberOfDroppedBuffers,
                       uint64_t maxFrameNumber = 99) {
        std::vector<BufferItem> queue = {CreateBufferItem(0, 0, 10000, true /*isReady*/,
                                                          false /*isAutoGeneratedTimestamp*/),
                                         CreateBufferItem(1, 1, 20000, true, false),
                                         CreateBufferItem(2, 2, 30000, true, true),
                                         CreateBufferItem(3, 3, 40000, true, true),
                                         CreateBufferItem(4, 4, 50000, true, false),
                                         CreateBufferItem(5, 5, 60000, true, false),
                                         CreateBufferItem(6, 6, 70000, true, true),
                                         CreateBufferItem(7, 7, 80000, false, true),
                                         CreateBufferItem(8, 8, 90000, false, true)};
        mTestableCore->ConfigureQueueStateViaFriend(queue);

        BufferItem acquiredBuffer;
        status_t result =
                mConsumer->acquireBuffer(&acquiredBuffer, expectedPresentTime, maxFrameNumber);

        EXPECT_EQ(result, android::OK);
        EXPECT_EQ(acquiredBuffer.mSlot, expectedAcquiredSlotNum);
        EXPECT_EQ(acquiredBuffer.mFrameNumber, expectedAcquiredFrameNum);

        EXPECT_EQ(mTestableCore->getQueueSizeForTest(), (size_t)9 - expectedNumberOfDroppedBuffers);
        if (mTestableCore->getQueueSizeForTest() > 0) {
            android::BufferItem frontItem = mTestableCore->getQueueFrontForTest();
            EXPECT_EQ(frontItem.mSlot, expectedAcquiredSlotNum + 1);
        }
    }
};

TEST_F(BufferQueueConsumerVkTimingTest, FifoLatestReadyTestZeroExpectPresent) {
    // Verify that we dequeue and acquire only the first frame when expected present is 0
    nsecs_t expectedPresentTime = 0;
    int expectedAcquiredSlotNum = 0;
    size_t expectedAcquiredFrameNum = 0;
    size_t expectedNumberOfDroppedBuffers = 1;
    runBufferTest(expectedPresentTime, expectedAcquiredSlotNum, expectedAcquiredFrameNum,
                  expectedNumberOfDroppedBuffers);
}

TEST_F(BufferQueueConsumerVkTimingTest, FifoLatestReadyTestBasicTimestamp) {
    // Verify that we dequeue the first frame (with timestamp 1000) and acquire the second frame
    // based on  it's timestamp of 2000
    nsecs_t expectedPresentTime = 21000;
    int expectedAcquiredSlotNum = 1;
    size_t expectedAcquiredFrameNum = 1;
    size_t expectedNumberOfDroppedBuffers = 2;
    runBufferTest(expectedPresentTime, expectedAcquiredSlotNum, expectedAcquiredFrameNum,
                  expectedNumberOfDroppedBuffers);
}

TEST_F(BufferQueueConsumerVkTimingTest, FifoLatestReadyTestBasicLaterTimestamp) {
    // Verify that we dequeue up until the 3rd frame with timestamp of 3000. We don't dequeue the
    // next frame even though it's timestamp is in the past because
    nsecs_t expectedPresentTime = 41000;
    int expectedAcquiredSlotNum = 2;
    size_t expectedAcquiredFrameNum = 2;
    size_t expectedNumberOfDroppedBuffers = 3;
    runBufferTest(expectedPresentTime, expectedAcquiredSlotNum, expectedAcquiredFrameNum,
                  expectedNumberOfDroppedBuffers);
}

} // namespace android