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