Loading libs/gui/include/gui/BufferQueueCore.h +6 −0 Original line number Diff line number Diff line Loading @@ -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 Loading libs/gui/tests/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -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", Loading libs/gui/tests/BufferQueueConsumer_test.cpp 0 → 100644 +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 Loading
libs/gui/include/gui/BufferQueueCore.h +6 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/gui/tests/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
libs/gui/tests/BufferQueueConsumer_test.cpp 0 → 100644 +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