1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19
20 #include <ftl/fake_guard.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24
25 #include <scheduler/Fps.h>
26 #include "Scheduler/VsyncSchedule.h"
27 #include "ThreadContext.h"
28 #include "mock/DisplayHardware/MockDisplayMode.h"
29 #include "mock/MockVSyncDispatch.h"
30 #include "mock/MockVSyncTracker.h"
31 #include "mock/MockVsyncController.h"
32
33 using android::mock::createDisplayMode;
34 using testing::_;
35
36 namespace android {
37
38 constexpr PhysicalDisplayId kDisplayId = PhysicalDisplayId::fromPort(42u);
39
40 class VsyncScheduleTest : public testing::Test {
41 protected:
42 VsyncScheduleTest();
43 ~VsyncScheduleTest() override;
44
45 testing::MockFunction<void(PhysicalDisplayId, bool)> mRequestHardwareVsync;
46
47 const std::unique_ptr<scheduler::VsyncSchedule> mVsyncSchedule =
48 std::unique_ptr<scheduler::VsyncSchedule>(
49 new scheduler::VsyncSchedule(kDisplayId, std::make_shared<mock::VSyncTracker>(),
50 std::make_shared<mock::VSyncDispatch>(),
51 std::make_unique<mock::VsyncController>(),
52 mRequestHardwareVsync.AsStdFunction()));
53
getController()54 mock::VsyncController& getController() {
55 return *static_cast<mock::VsyncController*>(&mVsyncSchedule->getController());
56 }
57 };
58
VsyncScheduleTest()59 VsyncScheduleTest::VsyncScheduleTest() {
60 const ::testing::TestInfo* const test_info =
61 ::testing::UnitTest::GetInstance()->current_test_info();
62 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
63 }
64
~VsyncScheduleTest()65 VsyncScheduleTest::~VsyncScheduleTest() {
66 const ::testing::TestInfo* const test_info =
67 ::testing::UnitTest::GetInstance()->current_test_info();
68 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
69 }
70
71 namespace {
72
73 using namespace testing;
74
TEST_F(VsyncScheduleTest,InitiallyDisallowed)75 TEST_F(VsyncScheduleTest, InitiallyDisallowed) {
76 ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
77 }
78
TEST_F(VsyncScheduleTest,EnableDoesNothingWhenDisallowed)79 TEST_F(VsyncScheduleTest, EnableDoesNothingWhenDisallowed) {
80 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
81
82 mVsyncSchedule->enableHardwareVsync();
83 }
84
TEST_F(VsyncScheduleTest,DisableDoesNothingWhenDisallowed)85 TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed) {
86 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
87
88 mVsyncSchedule->disableHardwareVsync(false /* disallow */);
89 }
90
TEST_F(VsyncScheduleTest,DisableDoesNothingWhenDisallowed2)91 TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed2) {
92 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
93
94 mVsyncSchedule->disableHardwareVsync(true /* disallow */);
95 }
96
TEST_F(VsyncScheduleTest,MakeAllowed)97 TEST_F(VsyncScheduleTest, MakeAllowed) {
98 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
99 }
100
TEST_F(VsyncScheduleTest,DisableDoesNothingWhenDisabled)101 TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled) {
102 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
103 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
104
105 mVsyncSchedule->disableHardwareVsync(false /* disallow */);
106 }
107
TEST_F(VsyncScheduleTest,DisableDoesNothingWhenDisabled2)108 TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled2) {
109 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
110 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
111
112 mVsyncSchedule->disableHardwareVsync(true /* disallow */);
113 }
114
TEST_F(VsyncScheduleTest,EnableWorksWhenDisabled)115 TEST_F(VsyncScheduleTest, EnableWorksWhenDisabled) {
116 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
117 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
118
119 mVsyncSchedule->enableHardwareVsync();
120 }
121
TEST_F(VsyncScheduleTest,EnableWorksOnce)122 TEST_F(VsyncScheduleTest, EnableWorksOnce) {
123 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
124 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
125
126 mVsyncSchedule->enableHardwareVsync();
127
128 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
129 mVsyncSchedule->enableHardwareVsync();
130 }
131
TEST_F(VsyncScheduleTest,AllowedIsSticky)132 TEST_F(VsyncScheduleTest, AllowedIsSticky) {
133 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
134 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
135 }
136
TEST_F(VsyncScheduleTest,EnableDisable)137 TEST_F(VsyncScheduleTest, EnableDisable) {
138 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
139 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
140
141 mVsyncSchedule->enableHardwareVsync();
142
143 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false));
144 mVsyncSchedule->disableHardwareVsync(false /* disallow */);
145 }
146
TEST_F(VsyncScheduleTest,EnableDisable2)147 TEST_F(VsyncScheduleTest, EnableDisable2) {
148 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
149 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
150
151 mVsyncSchedule->enableHardwareVsync();
152
153 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false));
154 mVsyncSchedule->disableHardwareVsync(true /* disallow */);
155 }
156
TEST_F(VsyncScheduleTest,StartPeriodTransition)157 TEST_F(VsyncScheduleTest, StartPeriodTransition) {
158 // Note: startPeriodTransition is only called when hardware vsyncs are
159 // allowed.
160 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
161
162 const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz));
163
164 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
165 EXPECT_CALL(getController(), onDisplayModeChanged(mode, false));
166
167 mVsyncSchedule->onDisplayModeChanged(mode, false);
168 }
169
TEST_F(VsyncScheduleTest,StartPeriodTransitionAlreadyEnabled)170 TEST_F(VsyncScheduleTest, StartPeriodTransitionAlreadyEnabled) {
171 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
172 mVsyncSchedule->enableHardwareVsync();
173
174 const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz));
175
176 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
177 EXPECT_CALL(getController(), onDisplayModeChanged(mode, false));
178
179 mVsyncSchedule->onDisplayModeChanged(mode, false);
180 }
181
TEST_F(VsyncScheduleTest,StartPeriodTransitionForce)182 TEST_F(VsyncScheduleTest, StartPeriodTransitionForce) {
183 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
184
185 const auto mode = ftl::as_non_null(createDisplayMode(DisplayModeId(0), 60_Hz));
186
187 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, true));
188 EXPECT_CALL(getController(), onDisplayModeChanged(mode, true));
189
190 mVsyncSchedule->onDisplayModeChanged(mode, true);
191 }
192
TEST_F(VsyncScheduleTest,AddResyncSampleDisallowed)193 TEST_F(VsyncScheduleTest, AddResyncSampleDisallowed) {
194 const Period period = (60_Hz).getPeriod();
195 const auto timestamp = TimePoint::now();
196
197 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
198 EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0);
199
200 mVsyncSchedule->addResyncSample(timestamp, period);
201 }
202
TEST_F(VsyncScheduleTest,AddResyncSampleDisabled)203 TEST_F(VsyncScheduleTest, AddResyncSampleDisabled) {
204 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
205 const Period period = (60_Hz).getPeriod();
206 const auto timestamp = TimePoint::now();
207
208 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
209 EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0);
210
211 mVsyncSchedule->addResyncSample(timestamp, period);
212 }
213
TEST_F(VsyncScheduleTest,AddResyncSampleReturnsTrue)214 TEST_F(VsyncScheduleTest, AddResyncSampleReturnsTrue) {
215 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
216 mVsyncSchedule->enableHardwareVsync();
217
218 const Period period = (60_Hz).getPeriod();
219 const auto timestamp = TimePoint::now();
220
221 EXPECT_CALL(mRequestHardwareVsync, Call(_, _)).Times(0);
222 EXPECT_CALL(getController(),
223 addHwVsyncTimestamp(timestamp.ns(), std::optional<nsecs_t>(period.ns()), _))
224 .WillOnce(Return(true));
225
226 mVsyncSchedule->addResyncSample(timestamp, period);
227 }
228
TEST_F(VsyncScheduleTest,AddResyncSampleReturnsFalse)229 TEST_F(VsyncScheduleTest, AddResyncSampleReturnsFalse) {
230 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
231 mVsyncSchedule->enableHardwareVsync();
232
233 const Period period = (60_Hz).getPeriod();
234 const auto timestamp = TimePoint::now();
235
236 EXPECT_CALL(mRequestHardwareVsync, Call(kDisplayId, false));
237 EXPECT_CALL(getController(),
238 addHwVsyncTimestamp(timestamp.ns(), std::optional<nsecs_t>(period.ns()), _))
239 .WillOnce(Return(false));
240
241 mVsyncSchedule->addResyncSample(timestamp, period);
242 }
243
TEST_F(VsyncScheduleTest,PendingState)244 TEST_F(VsyncScheduleTest, PendingState) FTL_FAKE_GUARD(kMainThreadContext) {
245 ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState());
246 mVsyncSchedule->setPendingHardwareVsyncState(true);
247 ASSERT_TRUE(mVsyncSchedule->getPendingHardwareVsyncState());
248
249 mVsyncSchedule->setPendingHardwareVsyncState(false);
250 ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState());
251 }
252
TEST_F(VsyncScheduleTest,DisableDoesNotMakeAllowed)253 TEST_F(VsyncScheduleTest, DisableDoesNotMakeAllowed) {
254 ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
255 mVsyncSchedule->disableHardwareVsync(false /* disallow */);
256 ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
257 }
258
TEST_F(VsyncScheduleTest,DisallowMakesNotAllowed)259 TEST_F(VsyncScheduleTest, DisallowMakesNotAllowed) {
260 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
261 mVsyncSchedule->disableHardwareVsync(true /* disallow */);
262 ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
263 }
264
TEST_F(VsyncScheduleTest,StillAllowedAfterDisable)265 TEST_F(VsyncScheduleTest, StillAllowedAfterDisable) {
266 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */));
267 mVsyncSchedule->disableHardwareVsync(false /* disallow */);
268 ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */));
269 }
270
271 } // namespace
272 } // namespace android
273