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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19 #define LOG_NDEBUG 0
20 
21 #include "Scheduler/VSyncModulator.h"
22 
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 
26 using namespace testing;
27 
28 namespace android::scheduler {
29 
30 class MockScheduler : public IPhaseOffsetControl {
31 public:
setPhaseOffset(ConnectionHandle handle,nsecs_t phaseOffset)32     void setPhaseOffset(ConnectionHandle handle, nsecs_t phaseOffset) {
33         mPhaseOffset[handle] = phaseOffset;
34     }
35 
getOffset(ConnectionHandle handle)36     nsecs_t getOffset(ConnectionHandle handle) { return mPhaseOffset[handle]; }
37 
38 private:
39     std::unordered_map<ConnectionHandle, nsecs_t> mPhaseOffset;
40 };
41 
42 class VSyncModulatorTest : public testing::Test {
43 protected:
44     static constexpr auto MIN_EARLY_FRAME_COUNT_TRANSACTION =
45             VSyncModulator::MIN_EARLY_FRAME_COUNT_TRANSACTION;
46     // Add a 1ms slack to avoid strange timer race conditions.
47     static constexpr auto MARGIN_FOR_TX_APPLY = VSyncModulator::MARGIN_FOR_TX_APPLY + 1ms;
48 
49     // Used to enumerate the different offsets we have
50     enum {
51         SF_LATE,
52         APP_LATE,
53         SF_EARLY,
54         APP_EARLY,
55         SF_EARLY_GL,
56         APP_EARLY_GL,
57     };
58 
59     std::unique_ptr<VSyncModulator> mVSyncModulator;
60     MockScheduler mMockScheduler;
61     ConnectionHandle mAppConnection{1};
62     ConnectionHandle mSfConnection{2};
63     VSyncModulator::OffsetsConfig mOffsets = {{SF_EARLY, APP_EARLY},
64                                               {SF_EARLY_GL, APP_EARLY_GL},
65                                               {SF_LATE, APP_LATE}};
66 
SetUp()67     void SetUp() override {
68         mVSyncModulator = std::make_unique<VSyncModulator>(mMockScheduler, mAppConnection,
69                                                            mSfConnection, mOffsets);
70         mVSyncModulator->setPhaseOffsets(mOffsets);
71 
72         EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
73         EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
74     };
75 
TearDown()76     void TearDown() override { mVSyncModulator.reset(); }
77 };
78 
TEST_F(VSyncModulatorTest,Normal)79 TEST_F(VSyncModulatorTest, Normal) {
80     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::Normal);
81     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
82     mVSyncModulator->onTransactionHandled();
83     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
84     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
85 
86     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
87         mVSyncModulator->onRefreshed(false);
88         EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
89         EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
90     }
91 }
92 
TEST_F(VSyncModulatorTest,EarlyEnd)93 TEST_F(VSyncModulatorTest, EarlyEnd) {
94     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
95     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
96     mVSyncModulator->onTransactionHandled();
97     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
98     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
99 
100     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
101         mVSyncModulator->onRefreshed(false);
102         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
103         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
104     }
105 
106     mVSyncModulator->onRefreshed(false);
107     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
108     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
109 }
110 
TEST_F(VSyncModulatorTest,EarlyStart)111 TEST_F(VSyncModulatorTest, EarlyStart) {
112     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyStart);
113     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
114     mVSyncModulator->onTransactionHandled();
115     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
116     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
117 
118     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
119         mVSyncModulator->onRefreshed(false);
120         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
121         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
122     }
123 
124     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
125     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
126     mVSyncModulator->onTransactionHandled();
127     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
128     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
129 
130     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
131         mVSyncModulator->onRefreshed(false);
132         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
133         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
134     }
135 
136     mVSyncModulator->onRefreshed(false);
137     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
138     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
139 }
140 
TEST_F(VSyncModulatorTest,EarlyStartWithEarly)141 TEST_F(VSyncModulatorTest, EarlyStartWithEarly) {
142     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyStart);
143     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
144     mVSyncModulator->onTransactionHandled();
145     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
146     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
147 
148     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
149         mVSyncModulator->onRefreshed(false);
150         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
151         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
152     }
153 
154     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::Early);
155     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
156     mVSyncModulator->onTransactionHandled();
157     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
158     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
159 
160     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
161         mVSyncModulator->onRefreshed(false);
162         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
163         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
164     }
165 
166     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
167     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
168     mVSyncModulator->onTransactionHandled();
169     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
170     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
171 
172     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
173         mVSyncModulator->onRefreshed(false);
174         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
175         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
176     }
177 
178     mVSyncModulator->onRefreshed(false);
179     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
180     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
181 }
182 
TEST_F(VSyncModulatorTest,EarlyStartWithMoreTransactions)183 TEST_F(VSyncModulatorTest, EarlyStartWithMoreTransactions) {
184     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyStart);
185     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
186     mVSyncModulator->onTransactionHandled();
187     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
188     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
189 
190     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
191         mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::Normal);
192         std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
193         mVSyncModulator->onRefreshed(false);
194         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
195         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
196     }
197 
198     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
199     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
200     mVSyncModulator->onTransactionHandled();
201     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
202     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
203 
204     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
205         mVSyncModulator->onRefreshed(false);
206         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
207         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
208     }
209 
210     mVSyncModulator->onRefreshed(false);
211     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
212     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
213 }
214 
TEST_F(VSyncModulatorTest,EarlyStartAfterEarlyEnd)215 TEST_F(VSyncModulatorTest, EarlyStartAfterEarlyEnd) {
216     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
217     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
218     mVSyncModulator->onTransactionHandled();
219     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
220     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
221 
222     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
223         mVSyncModulator->onRefreshed(false);
224         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
225         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
226     }
227 
228     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyStart);
229     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
230     mVSyncModulator->onTransactionHandled();
231     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
232     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
233 
234     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
235         mVSyncModulator->onRefreshed(false);
236         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
237         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
238     }
239 
240     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
241     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
242     mVSyncModulator->onTransactionHandled();
243     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
244     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
245 
246     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
247         mVSyncModulator->onRefreshed(false);
248         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
249         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
250     }
251 
252     mVSyncModulator->onRefreshed(false);
253     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
254     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
255 }
256 
TEST_F(VSyncModulatorTest,EarlyStartAfterEarlyEndWithMoreTransactions)257 TEST_F(VSyncModulatorTest, EarlyStartAfterEarlyEndWithMoreTransactions) {
258     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
259     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
260     mVSyncModulator->onTransactionHandled();
261     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
262     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
263 
264     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
265         mVSyncModulator->onRefreshed(false);
266         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
267         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
268     }
269 
270     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyStart);
271     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
272     mVSyncModulator->onTransactionHandled();
273     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
274     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
275 
276     for (int i = 0; i < 5 * MIN_EARLY_FRAME_COUNT_TRANSACTION; i++) {
277         mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::Normal);
278         std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
279         mVSyncModulator->onRefreshed(false);
280         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
281         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
282     }
283 
284     mVSyncModulator->setTransactionStart(Scheduler::TransactionStart::EarlyEnd);
285     std::this_thread::sleep_for(MARGIN_FOR_TX_APPLY);
286     mVSyncModulator->onTransactionHandled();
287     EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
288     EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
289 
290     for (int i = 0; i < MIN_EARLY_FRAME_COUNT_TRANSACTION - 1; i++) {
291         mVSyncModulator->onRefreshed(false);
292         EXPECT_EQ(APP_EARLY, mMockScheduler.getOffset(mAppConnection));
293         EXPECT_EQ(SF_EARLY, mMockScheduler.getOffset(mSfConnection));
294     }
295 
296     mVSyncModulator->onRefreshed(false);
297     EXPECT_EQ(APP_LATE, mMockScheduler.getOffset(mAppConnection));
298     EXPECT_EQ(SF_LATE, mMockScheduler.getOffset(mSfConnection));
299 }
300 
301 } // namespace android::scheduler
302