/* * Copyright 2021 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. */ #undef LOG_TAG #define LOG_TAG "FpsReporterTest" #include #include #include #include #include "BufferQueueLayer.h" #include "BufferStateLayer.h" #include "EffectLayer.h" #include "FpsReporter.h" #include "Layer.h" #include "TestableSurfaceFlinger.h" #include "fake/FakeClock.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/MockEventThread.h" #include "mock/MockFrameTimeline.h" #include "mock/MockVsyncController.h" namespace android { using testing::_; using testing::DoAll; using testing::Mock; using testing::Return; using testing::SetArgPointee; using testing::UnorderedElementsAre; using android::Hwc2::IComposer; using android::Hwc2::IComposerClient; using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; struct TestableFpsListener : public gui::BnFpsListener { TestableFpsListener() {} float lastReportedFps = 0; binder::Status onFpsReported(float fps) override { lastReportedFps = fps; return binder::Status::ok(); } }; /** * This class covers all the test that are related to refresh rate selection. */ class FpsReporterTest : public testing::Test { public: FpsReporterTest(); ~FpsReporterTest() override; protected: static constexpr int DEFAULT_DISPLAY_WIDTH = 1920; static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; static constexpr uint32_t WIDTH = 100; static constexpr uint32_t HEIGHT = 100; static constexpr uint32_t LAYER_FLAGS = 0; static constexpr int32_t PRIORITY_UNSET = -1; void setupScheduler(); sp createBufferStateLayer(LayerMetadata metadata); TestableSurfaceFlinger mFlinger; mock::FrameTimeline mFrameTimeline = mock::FrameTimeline(std::make_shared(), 0); sp mClient; sp mParent; sp mTarget; sp mChild; sp mGrandChild; sp mUnrelated; sp mFpsListener; fake::FakeClock* mClock = new fake::FakeClock(); sp mFpsReporter = new FpsReporter(mFrameTimeline, *(mFlinger.flinger()), std::unique_ptr(mClock)); }; FpsReporterTest::FpsReporterTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); setupScheduler(); mFlinger.setupComposer(std::make_unique()); mFpsListener = new TestableFpsListener(); } FpsReporterTest::~FpsReporterTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } sp FpsReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) { sp client; LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, LAYER_FLAGS, metadata); return new BufferStateLayer(args); } void FpsReporterTest::setupScheduler() { auto eventThread = std::make_unique(); auto sfEventThread = std::make_unique(); EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*eventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, ResyncCallback()))); EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, ResyncCallback()))); auto vsyncController = std::make_unique(); auto vsyncTracker = std::make_unique(); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); EXPECT_CALL(*vsyncTracker, currentPeriod()) .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), std::move(eventThread), std::move(sfEventThread)); } namespace { TEST_F(FpsReporterTest, callsListeners) { mParent = createBufferStateLayer(); constexpr int32_t kTaskId = 12; LayerMetadata targetMetadata; targetMetadata.setInt32(METADATA_TASK_ID, kTaskId); mTarget = createBufferStateLayer(targetMetadata); mChild = createBufferStateLayer(); mGrandChild = createBufferStateLayer(); mUnrelated = createBufferStateLayer(); mParent->addChild(mTarget); mTarget->addChild(mChild); mChild->addChild(mGrandChild); mParent->commitChildList(); mFlinger.mutableCurrentState().layersSortedByZ.add(mParent); mFlinger.mutableCurrentState().layersSortedByZ.add(mTarget); mFlinger.mutableCurrentState().layersSortedByZ.add(mChild); mFlinger.mutableCurrentState().layersSortedByZ.add(mGrandChild); float expectedFps = 44.0; EXPECT_CALL(mFrameTimeline, computeFps(UnorderedElementsAre(mTarget->getSequence(), mChild->getSequence(), mGrandChild->getSequence()))) .WillOnce(Return(expectedFps)); mFpsReporter->addListener(mFpsListener, kTaskId); mClock->advanceTime(600ms); mFpsReporter->dispatchLayerFps(); EXPECT_EQ(expectedFps, mFpsListener->lastReportedFps); mFpsReporter->removeListener(mFpsListener); Mock::VerifyAndClearExpectations(&mFrameTimeline); EXPECT_CALL(mFrameTimeline, computeFps(_)).Times(0); mFpsReporter->dispatchLayerFps(); } TEST_F(FpsReporterTest, rateLimits) { const constexpr int32_t kTaskId = 12; LayerMetadata targetMetadata; targetMetadata.setInt32(METADATA_TASK_ID, kTaskId); mTarget = createBufferStateLayer(targetMetadata); mFlinger.mutableCurrentState().layersSortedByZ.add(mTarget); float firstFps = 44.0; float secondFps = 53.0; EXPECT_CALL(mFrameTimeline, computeFps(UnorderedElementsAre(mTarget->getSequence()))) .WillOnce(Return(firstFps)) .WillOnce(Return(secondFps)); mFpsReporter->addListener(mFpsListener, kTaskId); mClock->advanceTime(600ms); mFpsReporter->dispatchLayerFps(); EXPECT_EQ(firstFps, mFpsListener->lastReportedFps); mClock->advanceTime(200ms); mFpsReporter->dispatchLayerFps(); EXPECT_EQ(firstFps, mFpsListener->lastReportedFps); mClock->advanceTime(200ms); mFpsReporter->dispatchLayerFps(); EXPECT_EQ(firstFps, mFpsListener->lastReportedFps); mClock->advanceTime(200ms); mFpsReporter->dispatchLayerFps(); EXPECT_EQ(secondFps, mFpsListener->lastReportedFps); } } // namespace } // namespace android