1 /*
2 * Copyright 2020 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 #include <binder/Binder.h>
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20
21 #include "Scheduler/VsyncModulator.h"
22
23 namespace android::scheduler {
24
25 class TestableVsyncModulator : public VsyncModulator {
26 public:
TestableVsyncModulator(const VsyncConfigSet & config,Now now)27 TestableVsyncModulator(const VsyncConfigSet& config, Now now) : VsyncModulator(config, now) {}
28
binderDied(const wp<IBinder> & token)29 void binderDied(const wp<IBinder>& token) { VsyncModulator::binderDied(token); }
30 };
31
32 class VsyncModulatorTest : public testing::Test {
33 enum {
34 SF_OFFSET_LATE,
35 APP_OFFSET_LATE,
36 SF_DURATION_LATE,
37 APP_DURATION_LATE,
38 SF_OFFSET_EARLY,
39 APP_OFFSET_EARLY,
40 SF_DURATION_EARLY,
41 APP_DURATION_EARLY,
42 SF_OFFSET_EARLY_GPU,
43 APP_OFFSET_EARLY_GPU,
44 SF_DURATION_EARLY_GPU,
45 APP_DURATION_EARLY_GPU,
46 HWC_MIN_WORK_DURATION,
47 };
48
Now()49 static VsyncModulator::TimePoint Now() {
50 static VsyncModulator::TimePoint now;
51 return now += VsyncModulator::MIN_EARLY_TRANSACTION_TIME;
52 }
53
54 protected:
55 static constexpr auto MIN_EARLY_TRANSACTION_FRAMES =
56 VsyncModulator::MIN_EARLY_TRANSACTION_FRAMES;
57
58 using Schedule = scheduler::TransactionSchedule;
59 using nanos = std::chrono::nanoseconds;
60 const VsyncModulator::VsyncConfig kEarly{SF_OFFSET_EARLY, APP_OFFSET_EARLY,
61 nanos(SF_DURATION_LATE), nanos(APP_DURATION_LATE)};
62 const VsyncModulator::VsyncConfig kEarlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU,
63 nanos(SF_DURATION_EARLY),
64 nanos(APP_DURATION_EARLY)};
65 const VsyncModulator::VsyncConfig kLate{SF_OFFSET_LATE, APP_OFFSET_LATE,
66 nanos(SF_DURATION_EARLY_GPU),
67 nanos(APP_DURATION_EARLY_GPU)};
68
69 const VsyncModulator::VsyncConfigSet mOffsets = {kEarly, kEarlyGpu, kLate,
70 nanos(HWC_MIN_WORK_DURATION)};
71 sp<TestableVsyncModulator> mVsyncModulator = sp<TestableVsyncModulator>::make(mOffsets, Now);
72
SetUp()73 void SetUp() override { EXPECT_EQ(kLate, mVsyncModulator->setVsyncConfigSet(mOffsets)); }
74 };
75
76 #define CHECK_COMMIT(result, configs) \
77 EXPECT_EQ(result, mVsyncModulator->onTransactionCommit()); \
78 EXPECT_EQ(configs, mVsyncModulator->getVsyncConfig());
79
80 #define CHECK_REFRESH(N, result, configs) \
81 for (int i = 0; i < N; i++) { \
82 EXPECT_EQ(result, mVsyncModulator->onDisplayRefresh(false)); \
83 EXPECT_EQ(configs, mVsyncModulator->getVsyncConfig()); \
84 }
85
TEST_F(VsyncModulatorTest,Late)86 TEST_F(VsyncModulatorTest, Late) {
87 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
88
89 CHECK_COMMIT(std::nullopt, kLate);
90 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kLate);
91 }
92
TEST_F(VsyncModulatorTest,EarlyEnd)93 TEST_F(VsyncModulatorTest, EarlyEnd) {
94 const auto token = sp<BBinder>::make();
95 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
96
97 CHECK_COMMIT(kEarly, kEarly);
98 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
99 CHECK_REFRESH(1, kLate, kLate);
100 }
101
TEST_F(VsyncModulatorTest,EarlyStart)102 TEST_F(VsyncModulatorTest, EarlyStart) {
103 const auto token = sp<BBinder>::make();
104 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
105
106 CHECK_COMMIT(kEarly, kEarly);
107 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
108
109 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
110
111 CHECK_COMMIT(kEarly, kEarly);
112 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
113 CHECK_REFRESH(1, kLate, kLate);
114 }
115
TEST_F(VsyncModulatorTest,EarlyStartWithMoreTransactions)116 TEST_F(VsyncModulatorTest, EarlyStartWithMoreTransactions) {
117 const auto token = sp<BBinder>::make();
118 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
119
120 CHECK_COMMIT(kEarly, kEarly);
121
122 for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
123 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
124 CHECK_REFRESH(1, std::nullopt, kEarly);
125 }
126
127 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
128
129 CHECK_COMMIT(kEarly, kEarly);
130 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
131 CHECK_REFRESH(1, kLate, kLate);
132 }
133
TEST_F(VsyncModulatorTest,EarlyStartAfterEarlyEnd)134 TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEnd) {
135 const auto token = sp<BBinder>::make();
136 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
137
138 CHECK_COMMIT(kEarly, kEarly);
139 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
140
141 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
142
143 CHECK_COMMIT(kEarly, kEarly);
144 CHECK_REFRESH(1, kEarly, kEarly);
145 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
146
147 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
148
149 CHECK_COMMIT(kEarly, kEarly);
150 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
151 CHECK_REFRESH(1, kLate, kLate);
152 }
153
TEST_F(VsyncModulatorTest,EarlyStartAfterEarlyEndWithMoreTransactions)154 TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEndWithMoreTransactions) {
155 const auto token = sp<BBinder>::make();
156 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
157
158 CHECK_COMMIT(kEarly, kEarly);
159 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
160
161 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
162
163 CHECK_COMMIT(kEarly, kEarly);
164 CHECK_REFRESH(1, kEarly, kEarly);
165
166 for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
167 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
168 CHECK_REFRESH(1, std::nullopt, kEarly);
169 }
170
171 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
172
173 CHECK_COMMIT(kEarly, kEarly);
174 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
175 CHECK_REFRESH(1, kLate, kLate);
176 }
177
TEST_F(VsyncModulatorTest,EarlyStartDifferentClients)178 TEST_F(VsyncModulatorTest, EarlyStartDifferentClients) {
179 const auto token1 = sp<BBinder>::make();
180 const auto token2 = sp<BBinder>::make();
181 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token1));
182
183 CHECK_COMMIT(kEarly, kEarly);
184 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
185
186 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token2));
187
188 CHECK_COMMIT(kEarly, kEarly);
189 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
190
191 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token1));
192
193 CHECK_COMMIT(kEarly, kEarly);
194 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
195
196 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token2));
197
198 CHECK_COMMIT(kEarly, kEarly);
199 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
200 CHECK_REFRESH(1, kLate, kLate);
201 }
202
TEST_F(VsyncModulatorTest,EarlyStartWithBinderDeath)203 TEST_F(VsyncModulatorTest, EarlyStartWithBinderDeath) {
204 const auto token = sp<BBinder>::make();
205 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
206
207 CHECK_COMMIT(kEarly, kEarly);
208 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
209
210 mVsyncModulator->binderDied(token);
211
212 CHECK_COMMIT(std::nullopt, kLate);
213 }
214
215 } // namespace android::scheduler
216