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 VsyncConfig kEarly{SF_OFFSET_EARLY, APP_OFFSET_EARLY, nanos(SF_DURATION_LATE),
61 nanos(APP_DURATION_LATE)};
62 const VsyncConfig kEarlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU, nanos(SF_DURATION_EARLY),
63 nanos(APP_DURATION_EARLY)};
64 const VsyncConfig kLate{SF_OFFSET_LATE, APP_OFFSET_LATE, nanos(SF_DURATION_EARLY_GPU),
65 nanos(APP_DURATION_EARLY_GPU)};
66
67 const VsyncConfigSet mOffsets = {kEarly, kEarlyGpu, kLate, nanos(HWC_MIN_WORK_DURATION)};
68 sp<TestableVsyncModulator> mVsyncModulator = sp<TestableVsyncModulator>::make(mOffsets, Now);
69
SetUp()70 void SetUp() override { EXPECT_EQ(kLate, mVsyncModulator->setVsyncConfigSet(mOffsets)); }
71 };
72
73 #define CHECK_COMMIT(result, configs) \
74 EXPECT_EQ(result, mVsyncModulator->onTransactionCommit()); \
75 EXPECT_EQ(configs, mVsyncModulator->getVsyncConfig());
76
77 #define CHECK_REFRESH(N, result, configs) \
78 for (int i = 0; i < N; i++) { \
79 EXPECT_EQ(result, mVsyncModulator->onDisplayRefresh(false)); \
80 EXPECT_EQ(configs, mVsyncModulator->getVsyncConfig()); \
81 }
82
TEST_F(VsyncModulatorTest,Late)83 TEST_F(VsyncModulatorTest, Late) {
84 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
85
86 CHECK_COMMIT(std::nullopt, kLate);
87 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kLate);
88 }
89
TEST_F(VsyncModulatorTest,EarlyEnd)90 TEST_F(VsyncModulatorTest, EarlyEnd) {
91 const auto token = sp<BBinder>::make();
92 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
93
94 CHECK_COMMIT(kEarly, kEarly);
95 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
96 CHECK_REFRESH(1, kLate, kLate);
97 }
98
TEST_F(VsyncModulatorTest,EarlyStart)99 TEST_F(VsyncModulatorTest, EarlyStart) {
100 const auto token = sp<BBinder>::make();
101 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
102
103 CHECK_COMMIT(kEarly, kEarly);
104 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
105
106 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
107
108 CHECK_COMMIT(kEarly, kEarly);
109 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
110 CHECK_REFRESH(1, kLate, kLate);
111 }
112
TEST_F(VsyncModulatorTest,EarlyStartWithMoreTransactions)113 TEST_F(VsyncModulatorTest, EarlyStartWithMoreTransactions) {
114 const auto token = sp<BBinder>::make();
115 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
116
117 CHECK_COMMIT(kEarly, kEarly);
118
119 for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
120 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
121 CHECK_REFRESH(1, std::nullopt, kEarly);
122 }
123
124 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
125
126 CHECK_COMMIT(kEarly, kEarly);
127 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
128 CHECK_REFRESH(1, kLate, kLate);
129 }
130
TEST_F(VsyncModulatorTest,EarlyStartAfterEarlyEnd)131 TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEnd) {
132 const auto token = sp<BBinder>::make();
133 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
134
135 CHECK_COMMIT(kEarly, kEarly);
136 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
137
138 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
139
140 CHECK_COMMIT(kEarly, kEarly);
141 CHECK_REFRESH(1, kEarly, kEarly);
142 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
143
144 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
145
146 CHECK_COMMIT(kEarly, kEarly);
147 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
148 CHECK_REFRESH(1, kLate, kLate);
149 }
150
TEST_F(VsyncModulatorTest,EarlyStartAfterEarlyEndWithMoreTransactions)151 TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEndWithMoreTransactions) {
152 const auto token = sp<BBinder>::make();
153 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
154
155 CHECK_COMMIT(kEarly, kEarly);
156 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
157
158 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
159
160 CHECK_COMMIT(kEarly, kEarly);
161 CHECK_REFRESH(1, kEarly, kEarly);
162
163 for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
164 EXPECT_FALSE(mVsyncModulator->setTransactionSchedule(Schedule::Late));
165 CHECK_REFRESH(1, std::nullopt, kEarly);
166 }
167
168 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token));
169
170 CHECK_COMMIT(kEarly, kEarly);
171 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
172 CHECK_REFRESH(1, kLate, kLate);
173 }
174
TEST_F(VsyncModulatorTest,EarlyStartDifferentClients)175 TEST_F(VsyncModulatorTest, EarlyStartDifferentClients) {
176 const auto token1 = sp<BBinder>::make();
177 const auto token2 = sp<BBinder>::make();
178 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token1));
179
180 CHECK_COMMIT(kEarly, kEarly);
181 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
182
183 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token2));
184
185 CHECK_COMMIT(kEarly, kEarly);
186 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
187
188 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token1));
189
190 CHECK_COMMIT(kEarly, kEarly);
191 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
192
193 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyEnd, token2));
194
195 CHECK_COMMIT(kEarly, kEarly);
196 CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
197 CHECK_REFRESH(1, kLate, kLate);
198 }
199
TEST_F(VsyncModulatorTest,EarlyStartWithBinderDeath)200 TEST_F(VsyncModulatorTest, EarlyStartWithBinderDeath) {
201 const auto token = sp<BBinder>::make();
202 EXPECT_EQ(kEarly, mVsyncModulator->setTransactionSchedule(Schedule::EarlyStart, token));
203
204 CHECK_COMMIT(kEarly, kEarly);
205 CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
206
207 mVsyncModulator->binderDied(token);
208
209 CHECK_COMMIT(std::nullopt, kLate);
210 }
211
212 } // namespace android::scheduler
213