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