/* * Copyright 2023 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 "LibSurfaceFlingerUnittests" #include #include #include #include #include #include "Scheduler/VsyncSchedule.h" #include "ThreadContext.h" #include "mock/DisplayHardware/MockDisplayMode.h" #include "mock/MockVSyncDispatch.h" #include "mock/MockVSyncTracker.h" #include "mock/MockVsyncController.h" using android::mock::createDisplayMode; using testing::_; namespace android { constexpr PhysicalDisplayId kDisplayId = PhysicalDisplayId::fromPort(42u); class VsyncScheduleTest : public testing::Test { protected: VsyncScheduleTest(); ~VsyncScheduleTest() override; testing::MockFunction mRequestHardwareVsync; const std::unique_ptr mVsyncSchedule = std::unique_ptr( new scheduler::VsyncSchedule(kDisplayId, std::make_shared(), std::make_shared(), std::make_unique(), mRequestHardwareVsync.AsStdFunction())); mock::VsyncController& getController() { return *static_cast(&mVsyncSchedule->getController()); } }; VsyncScheduleTest::VsyncScheduleTest() { 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()); } VsyncScheduleTest::~VsyncScheduleTest() { 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()); } namespace { using namespace testing; TEST_F(VsyncScheduleTest, InitiallyDisallowed) { ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); } TEST_F(VsyncScheduleTest, EnableDoesNothingWhenDisallowed) { EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->enableHardwareVsync(); } TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed) { EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->disableHardwareVsync(false /* disallow */); } TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed2) { EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->disableHardwareVsync(true /* disallow */); } TEST_F(VsyncScheduleTest, MakeAllowed) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); } TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->disableHardwareVsync(false /* disallow */); } TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled2) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->disableHardwareVsync(true /* disallow */); } TEST_F(VsyncScheduleTest, EnableWorksWhenDisabled) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); mVsyncSchedule->enableHardwareVsync(); } TEST_F(VsyncScheduleTest, EnableWorksOnce) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); mVsyncSchedule->enableHardwareVsync(); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); mVsyncSchedule->enableHardwareVsync(); } TEST_F(VsyncScheduleTest, AllowedIsSticky) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); } TEST_F(VsyncScheduleTest, EnableDisable) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); mVsyncSchedule->enableHardwareVsync(); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false)); mVsyncSchedule->disableHardwareVsync(false /* disallow */); } TEST_F(VsyncScheduleTest, EnableDisable2) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); mVsyncSchedule->enableHardwareVsync(); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false)); mVsyncSchedule->disableHardwareVsync(true /* disallow */); } TEST_F(VsyncScheduleTest, StartPeriodTransition) { // Note: startPeriodTransition is only called when hardware vsyncs are // allowed. ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); EXPECT_CALL(getController(), onDisplayModeChanged(mode, false)); mVsyncSchedule->onDisplayModeChanged(mode, false); } TEST_F(VsyncScheduleTest, StartPeriodTransitionAlreadyEnabled) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); mVsyncSchedule->enableHardwareVsync(); const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz)); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); EXPECT_CALL(getController(), onDisplayModeChanged(mode, false)); mVsyncSchedule->onDisplayModeChanged(mode, false); } TEST_F(VsyncScheduleTest, StartPeriodTransitionForce) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz)); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true)); EXPECT_CALL(getController(), onDisplayModeChanged(mode, true)); mVsyncSchedule->onDisplayModeChanged(mode, true); } TEST_F(VsyncScheduleTest, AddResyncSampleDisallowed) { const Period period = (60_Hz).getPeriod(); const auto timestamp = TimePoint::now(); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0); mVsyncSchedule->addResyncSample(timestamp, period); } TEST_F(VsyncScheduleTest, AddResyncSampleDisabled) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); const Period period = (60_Hz).getPeriod(); const auto timestamp = TimePoint::now(); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0); mVsyncSchedule->addResyncSample(timestamp, period); } TEST_F(VsyncScheduleTest, AddResyncSampleReturnsTrue) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); mVsyncSchedule->enableHardwareVsync(); const Period period = (60_Hz).getPeriod(); const auto timestamp = TimePoint::now(); EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0); EXPECT_CALL(getController(), addHwVsyncTimestamp(timestamp.ns(), std::optional(period.ns()), _)) .WillOnce(Return(true)); mVsyncSchedule->addResyncSample(timestamp, period); } TEST_F(VsyncScheduleTest, AddResyncSampleReturnsFalse) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); mVsyncSchedule->enableHardwareVsync(); const Period period = (60_Hz).getPeriod(); const auto timestamp = TimePoint::now(); EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false)); EXPECT_CALL(getController(), addHwVsyncTimestamp(timestamp.ns(), std::optional(period.ns()), _)) .WillOnce(Return(false)); mVsyncSchedule->addResyncSample(timestamp, period); } TEST_F(VsyncScheduleTest, PendingState) FTL_FAKE_GUARD(kMainThreadContext) { ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState()); mVsyncSchedule->setPendingHardwareVsyncState(true); ASSERT_TRUE(mVsyncSchedule->getPendingHardwareVsyncState()); mVsyncSchedule->setPendingHardwareVsyncState(false); ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState()); } TEST_F(VsyncScheduleTest, DisableDoesNotMakeAllowed) { ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); mVsyncSchedule->disableHardwareVsync(false /* disallow */); ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); } TEST_F(VsyncScheduleTest, DisallowMakesNotAllowed) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); mVsyncSchedule->disableHardwareVsync(true /* disallow */); ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); } TEST_F(VsyncScheduleTest, StillAllowedAfterDisable) { ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); mVsyncSchedule->disableHardwareVsync(false /* disallow */); ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); } } // namespace } // namespace android