blob: adf080471c9b8bde7b2cbd4f39013fe38f9e0fa5 [file] [log] [blame]
/*
* 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 <ftl/fake_guard.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <log/log.h>
#include <scheduler/Fps.h>
#include "Scheduler/VsyncSchedule.h"
#include "ThreadContext.h"
#include "mock/MockSchedulerCallback.h"
#include "mock/MockVSyncDispatch.h"
#include "mock/MockVSyncTracker.h"
#include "mock/MockVsyncController.h"
using testing::_;
namespace android {
constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
class VsyncScheduleTest : public testing::Test {
protected:
VsyncScheduleTest();
~VsyncScheduleTest() override;
scheduler::mock::SchedulerCallback mCallback;
const std::unique_ptr<scheduler::VsyncSchedule> mVsyncSchedule =
std::unique_ptr<scheduler::VsyncSchedule>(
new scheduler::VsyncSchedule(DEFAULT_DISPLAY_ID,
std::make_shared<mock::VSyncTracker>(),
std::make_shared<mock::VSyncDispatch>(),
std::make_unique<mock::VsyncController>()));
mock::VsyncController& getController() {
return *static_cast<mock::VsyncController*>(&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(mCallback, setVsyncEnabled(_, _)).Times(0);
mVsyncSchedule->enableHardwareVsync(mCallback);
}
TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed) {
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */);
}
TEST_F(VsyncScheduleTest, MakeAllowed) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
}
TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */);
}
TEST_F(VsyncScheduleTest, EnableWorksWhenDisabled) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, true));
mVsyncSchedule->enableHardwareVsync(mCallback);
}
TEST_F(VsyncScheduleTest, EnableWorksOnce) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, true));
mVsyncSchedule->enableHardwareVsync(mCallback);
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
mVsyncSchedule->enableHardwareVsync(mCallback);
}
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(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, true));
mVsyncSchedule->enableHardwareVsync(mCallback);
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, false));
mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */);
}
TEST_F(VsyncScheduleTest, StartPeriodTransition) {
// Note: startPeriodTransition is only called when hardware vsyncs are
// allowed.
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
const Period period = (60_Hz).getPeriod();
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, true));
EXPECT_CALL(getController(), startPeriodTransition(period.ns(), false));
mVsyncSchedule->startPeriodTransition(mCallback, period, false);
}
TEST_F(VsyncScheduleTest, StartPeriodTransitionAlreadyEnabled) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
mVsyncSchedule->enableHardwareVsync(mCallback);
const Period period = (60_Hz).getPeriod();
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
EXPECT_CALL(getController(), startPeriodTransition(period.ns(), false));
mVsyncSchedule->startPeriodTransition(mCallback, period, false);
}
TEST_F(VsyncScheduleTest, StartPeriodTransitionForce) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
const Period period = (60_Hz).getPeriod();
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, true));
EXPECT_CALL(getController(), startPeriodTransition(period.ns(), true));
mVsyncSchedule->startPeriodTransition(mCallback, period, true);
}
TEST_F(VsyncScheduleTest, AddResyncSampleDisallowed) {
const Period period = (60_Hz).getPeriod();
const auto timestamp = TimePoint::now();
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0);
mVsyncSchedule->addResyncSample(mCallback, 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(mCallback, setVsyncEnabled(_, _)).Times(0);
EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0);
mVsyncSchedule->addResyncSample(mCallback, timestamp, period);
}
TEST_F(VsyncScheduleTest, AddResyncSampleReturnsTrue) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
mVsyncSchedule->enableHardwareVsync(mCallback);
const Period period = (60_Hz).getPeriod();
const auto timestamp = TimePoint::now();
EXPECT_CALL(mCallback, setVsyncEnabled(_, _)).Times(0);
EXPECT_CALL(getController(),
addHwVsyncTimestamp(timestamp.ns(), std::optional<nsecs_t>(period.ns()), _))
.WillOnce(Return(true));
mVsyncSchedule->addResyncSample(mCallback, timestamp, period);
}
TEST_F(VsyncScheduleTest, AddResyncSampleReturnsFalse) {
ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
mVsyncSchedule->enableHardwareVsync(mCallback);
const Period period = (60_Hz).getPeriod();
const auto timestamp = TimePoint::now();
EXPECT_CALL(mCallback, setVsyncEnabled(DEFAULT_DISPLAY_ID, false));
EXPECT_CALL(getController(),
addHwVsyncTimestamp(timestamp.ns(), std::optional<nsecs_t>(period.ns()), _))
.WillOnce(Return(false));
mVsyncSchedule->addResyncSample(mCallback, 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());
}
} // namespace
} // namespace android