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 #include "gestures/TimerProvider.h"
18
19 #include <vector>
20
21 #include <gtest/gtest.h>
22
23 #include "InterfaceMocks.h"
24 #include "TestConstants.h"
25 #include "include/gestures.h"
26
27 namespace android {
28
29 namespace {
30
31 class TestTimerProvider : public TimerProvider {
32 public:
TestTimerProvider(InputReaderContext & context)33 TestTimerProvider(InputReaderContext& context) : TimerProvider(context) {}
34
setCurrentTime(nsecs_t time)35 void setCurrentTime(nsecs_t time) { mCurrentTime = time; }
36
37 protected:
getCurrentTime()38 nsecs_t getCurrentTime() override { return mCurrentTime; }
39
40 private:
41 nsecs_t mCurrentTime = 0;
42 };
43
pushTimeOntoVector(stime_t triggerTime,void * data)44 stime_t pushTimeOntoVector(stime_t triggerTime, void* data) {
45 std::vector<stime_t>* times = static_cast<std::vector<stime_t>*>(data);
46 times->push_back(triggerTime);
47 return NO_DEADLINE;
48 }
49
copyTimeToVariable(stime_t triggerTime,void * data)50 stime_t copyTimeToVariable(stime_t triggerTime, void* data) {
51 stime_t* time = static_cast<stime_t*>(data);
52 *time = triggerTime;
53 return NO_DEADLINE;
54 }
55
incrementInt(stime_t triggerTime,void * data)56 stime_t incrementInt(stime_t triggerTime, void* data) {
57 int* count = static_cast<int*>(data);
58 *count += 1;
59 return NO_DEADLINE;
60 }
61
62 } // namespace
63
64 using testing::AtLeast;
65
66 class TimerProviderTest : public testing::Test {
67 public:
TimerProviderTest()68 TimerProviderTest() : mProvider(mMockContext) {}
69
70 protected:
triggerCallbacksWithFakeTime(nsecs_t time)71 void triggerCallbacksWithFakeTime(nsecs_t time) {
72 mProvider.setCurrentTime(time);
73 mProvider.triggerCallbacks(time);
74 }
75
76 MockInputReaderContext mMockContext;
77 TestTimerProvider mProvider;
78 };
79
TEST_F(TimerProviderTest,SingleDeadlineTriggersWhenTimeoutIsExactlyOnTime)80 TEST_F(TimerProviderTest, SingleDeadlineTriggersWhenTimeoutIsExactlyOnTime) {
81 GesturesTimer* timer = mProvider.createTimer();
82 std::vector<stime_t> callTimes;
83 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(3);
84
85 // Call through kGestureTimerProvider in this test case, so that we cover the stime_t to nsecs_t
86 // conversion code. This is why the delay is 1.0 rather than 1'000'000'000 here.
87 kGestureTimerProvider.set_fn(&mProvider, timer, 1.0, &pushTimeOntoVector, &callTimes);
88
89 triggerCallbacksWithFakeTime(900'000'000);
90 triggerCallbacksWithFakeTime(999'999'999);
91 EXPECT_EQ(0u, callTimes.size());
92 triggerCallbacksWithFakeTime(1'000'000'000);
93 ASSERT_EQ(1u, callTimes.size());
94 EXPECT_NEAR(1.0, callTimes[0], EPSILON);
95
96 // Now that the timer has triggered, it shouldn't trigger again if we get another timeout from
97 // InputReader.
98 triggerCallbacksWithFakeTime(1'300'000'000);
99 EXPECT_EQ(1u, callTimes.size());
100 }
101
TEST_F(TimerProviderTest,SingleDeadlineTriggersWhenTimeoutIsLate)102 TEST_F(TimerProviderTest, SingleDeadlineTriggersWhenTimeoutIsLate) {
103 GesturesTimer* timer = mProvider.createTimer();
104 stime_t callTime = -1.0;
105 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
106 mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime);
107
108 triggerCallbacksWithFakeTime(1'010'000'000);
109 EXPECT_NEAR(1.01, callTime, EPSILON);
110 }
111
TEST_F(TimerProviderTest,SingleRescheduledDeadlineTriggers)112 TEST_F(TimerProviderTest, SingleRescheduledDeadlineTriggers) {
113 GesturesTimer* timer = mProvider.createTimer();
114 std::vector<stime_t> callTimes;
115 auto callback = [](stime_t triggerTime, void* callbackData) {
116 std::vector<stime_t>* times = static_cast<std::vector<stime_t>*>(callbackData);
117 times->push_back(triggerTime);
118 if (times->size() < 2) {
119 return 1.0;
120 } else {
121 return NO_DEADLINE;
122 }
123 };
124 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
125 // The deadline should be rescheduled for 2.01s, since the first triggerCallbacks call is 0.01s
126 // late.
127 EXPECT_CALL(mMockContext, requestTimeoutAtTime(2'010'000'000)).Times(1);
128
129 mProvider.setDeadline(timer, 1'000'000'000, callback, &callTimes);
130
131 triggerCallbacksWithFakeTime(1'010'000'000);
132 ASSERT_EQ(1u, callTimes.size());
133 EXPECT_NEAR(1.01, callTimes[0], EPSILON);
134
135 triggerCallbacksWithFakeTime(2'020'000'000);
136 ASSERT_EQ(2u, callTimes.size());
137 EXPECT_NEAR(1.01, callTimes[0], EPSILON);
138 EXPECT_NEAR(2.02, callTimes[1], EPSILON);
139
140 triggerCallbacksWithFakeTime(3'000'000'000);
141 EXPECT_EQ(2u, callTimes.size());
142 }
143
TEST_F(TimerProviderTest,MultipleDeadlinesTriggerWithMultipleTimeouts)144 TEST_F(TimerProviderTest, MultipleDeadlinesTriggerWithMultipleTimeouts) {
145 GesturesTimer* timer = mProvider.createTimer();
146 std::vector<stime_t> callTimes1;
147 std::vector<stime_t> callTimes2;
148
149 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
150 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'500'000'000)).Times(1);
151
152 mProvider.setDeadline(timer, 1'000'000'000, &pushTimeOntoVector, &callTimes1);
153 mProvider.setDeadline(timer, 1'500'000'000, &pushTimeOntoVector, &callTimes2);
154
155 EXPECT_EQ(0u, callTimes1.size());
156 EXPECT_EQ(0u, callTimes2.size());
157
158 triggerCallbacksWithFakeTime(1'010'000'000);
159 ASSERT_EQ(1u, callTimes1.size());
160 EXPECT_NEAR(1.01, callTimes1[0], EPSILON);
161 EXPECT_EQ(0u, callTimes2.size());
162
163 triggerCallbacksWithFakeTime(1'500'000'000);
164 EXPECT_EQ(1u, callTimes1.size());
165 ASSERT_EQ(1u, callTimes2.size());
166 EXPECT_NEAR(1.5, callTimes2[0], EPSILON);
167 }
168
TEST_F(TimerProviderTest,MultipleDeadlinesTriggerWithOneLateTimeout)169 TEST_F(TimerProviderTest, MultipleDeadlinesTriggerWithOneLateTimeout) {
170 GesturesTimer* timer = mProvider.createTimer();
171 stime_t callTime1 = -1.0;
172 stime_t callTime2 = -1.0;
173
174 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
175
176 mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime1);
177 mProvider.setDeadline(timer, 1'500'000'000, ©TimeToVariable, &callTime2);
178
179 triggerCallbacksWithFakeTime(1'510'000'000);
180 EXPECT_NEAR(1.51, callTime1, EPSILON);
181 EXPECT_NEAR(1.51, callTime2, EPSILON);
182 }
183
TEST_F(TimerProviderTest,MultipleDeadlinesAtSameTimeTriggerTogether)184 TEST_F(TimerProviderTest, MultipleDeadlinesAtSameTimeTriggerTogether) {
185 GesturesTimer* timer = mProvider.createTimer();
186 stime_t callTime1 = -1.0;
187 stime_t callTime2 = -1.0;
188
189 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(AtLeast(1));
190
191 mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime1);
192 mProvider.setDeadline(timer, 1'000'000'000, ©TimeToVariable, &callTime2);
193
194 triggerCallbacksWithFakeTime(1'000'000'000);
195 EXPECT_NEAR(1.0, callTime1, EPSILON);
196 EXPECT_NEAR(1.0, callTime2, EPSILON);
197 }
198
TEST_F(TimerProviderTest,MultipleTimersTriggerCorrectly)199 TEST_F(TimerProviderTest, MultipleTimersTriggerCorrectly) {
200 GesturesTimer* timer1 = mProvider.createTimer();
201 GesturesTimer* timer2 = mProvider.createTimer();
202 std::vector<stime_t> callTimes1;
203 std::vector<stime_t> callTimes2;
204
205 EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
206 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'250'000'000)).Times(1);
207 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'500'000'000)).Times(1);
208
209 mProvider.setDeadline(timer1, 500'000'000, &pushTimeOntoVector, &callTimes1);
210 mProvider.setDeadline(timer1, 1'250'000'000, &pushTimeOntoVector, &callTimes1);
211 mProvider.setDeadline(timer1, 1'500'000'000, &pushTimeOntoVector, &callTimes1);
212 mProvider.setDeadline(timer2, 750'000'000, &pushTimeOntoVector, &callTimes2);
213 mProvider.setDeadline(timer2, 1'250'000'000, &pushTimeOntoVector, &callTimes2);
214
215 triggerCallbacksWithFakeTime(800'000'000);
216 ASSERT_EQ(1u, callTimes1.size());
217 EXPECT_NEAR(0.8, callTimes1[0], EPSILON);
218 ASSERT_EQ(1u, callTimes2.size());
219 EXPECT_NEAR(0.8, callTimes2[0], EPSILON);
220
221 triggerCallbacksWithFakeTime(1'250'000'000);
222 ASSERT_EQ(2u, callTimes1.size());
223 EXPECT_NEAR(1.25, callTimes1[1], EPSILON);
224 ASSERT_EQ(2u, callTimes2.size());
225 EXPECT_NEAR(1.25, callTimes2[1], EPSILON);
226
227 triggerCallbacksWithFakeTime(1'501'000'000);
228 ASSERT_EQ(3u, callTimes1.size());
229 EXPECT_NEAR(1.501, callTimes1[2], EPSILON);
230 EXPECT_EQ(2u, callTimes2.size());
231 }
232
TEST_F(TimerProviderTest,CancelledTimerDoesntTrigger)233 TEST_F(TimerProviderTest, CancelledTimerDoesntTrigger) {
234 GesturesTimer* timer = mProvider.createTimer();
235 int numCalls = 0;
236
237 EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
238 mProvider.setDeadline(timer, 500'000'000, &incrementInt, &numCalls);
239 mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCalls);
240 mProvider.cancelTimer(timer);
241
242 triggerCallbacksWithFakeTime(1'100'000'000);
243 EXPECT_EQ(0, numCalls);
244 }
245
TEST_F(TimerProviderTest,CancellingOneTimerDoesntAffectOthers)246 TEST_F(TimerProviderTest, CancellingOneTimerDoesntAffectOthers) {
247 GesturesTimer* timer1 = mProvider.createTimer();
248 GesturesTimer* timer2 = mProvider.createTimer();
249 int numCalls1 = 0;
250 int numCalls2 = 0;
251
252 EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
253 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
254
255 mProvider.setDeadline(timer1, 500'000'000, &incrementInt, &numCalls1);
256 mProvider.setDeadline(timer2, 500'000'000, &incrementInt, &numCalls2);
257 mProvider.setDeadline(timer2, 1'000'000'000, &incrementInt, &numCalls2);
258 mProvider.cancelTimer(timer1);
259
260 triggerCallbacksWithFakeTime(501'000'000);
261 EXPECT_EQ(0, numCalls1);
262 EXPECT_EQ(1, numCalls2);
263
264 triggerCallbacksWithFakeTime(1'000'000'000);
265 EXPECT_EQ(0, numCalls1);
266 EXPECT_EQ(2, numCalls2);
267 }
268
TEST_F(TimerProviderTest,CancellingOneTimerCausesNewTimeoutRequestForAnother)269 TEST_F(TimerProviderTest, CancellingOneTimerCausesNewTimeoutRequestForAnother) {
270 GesturesTimer* timer1 = mProvider.createTimer();
271 GesturesTimer* timer2 = mProvider.createTimer();
272 auto callback = [](stime_t, void*) { return NO_DEADLINE; };
273
274 EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(AtLeast(1));
275
276 mProvider.setDeadline(timer1, 500'000'000, callback, nullptr);
277 mProvider.setDeadline(timer2, 1'000'000'000, callback, nullptr);
278
279 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
280 mProvider.cancelTimer(timer1);
281 }
282
TEST_F(TimerProviderTest,CancelledTimerCanBeReused)283 TEST_F(TimerProviderTest, CancelledTimerCanBeReused) {
284 GesturesTimer* timer = mProvider.createTimer();
285 int numCallsBeforeCancellation = 0;
286 int numCallsAfterCancellation = 0;
287
288 EXPECT_CALL(mMockContext, requestTimeoutAtTime(500'000'000)).Times(1);
289 EXPECT_CALL(mMockContext, requestTimeoutAtTime(1'000'000'000)).Times(1);
290
291 mProvider.setDeadline(timer, 500'000'000, &incrementInt, &numCallsBeforeCancellation);
292 mProvider.cancelTimer(timer);
293 mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCallsAfterCancellation);
294
295 triggerCallbacksWithFakeTime(1'000'000'000);
296 EXPECT_EQ(0, numCallsBeforeCancellation);
297 EXPECT_EQ(1, numCallsAfterCancellation);
298 }
299
TEST_F(TimerProviderTest,FreeingTimerCancelsFirst)300 TEST_F(TimerProviderTest, FreeingTimerCancelsFirst) {
301 GesturesTimer* timer = mProvider.createTimer();
302 int numCalls = 0;
303
304 mProvider.setDeadline(timer, 1'000'000'000, &incrementInt, &numCalls);
305 mProvider.freeTimer(timer);
306
307 triggerCallbacksWithFakeTime(1'000'000'000);
308 EXPECT_EQ(0, numCalls);
309 }
310
311 } // namespace android