1 /*
2 * Copyright (C) 2016 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
18 #include <ChoreographerTestUtils.h>
19 #include <android/choreographer.h>
20 #include <android/looper.h>
21 #include <jni.h>
22 #include <sys/time.h>
23 #include <time.h>
24
25 #include <chrono>
26 #include <cmath>
27 #include <cstdlib>
28 #include <cstring>
29 #include <limits>
30 #include <mutex>
31 #include <set>
32 #include <sstream>
33 #include <string>
34 #include <thread>
35 #include <tuple>
36 #include <vector>
37
38 #define LOG_TAG "ChoreographerNativeTest"
39
40
41 using namespace std::chrono_literals;
42
43 struct {
44 struct {
45 jclass clazz;
46 jmethodID checkRefreshRateIsCurrentAndSwitch;
47 } choreographerNativeTest;
48 } gJni;
49
50 static std::set<int64_t> gSupportedRefreshPeriods;
51
52 struct RefreshRateCallback {
RefreshRateCallbackRefreshRateCallback53 RefreshRateCallback(const char* name): name(name) {}
54 std::string name;
55 int count{0};
56 std::chrono::nanoseconds vsyncPeriod{0LL};
57 };
58
59 struct RefreshRateCallbackWithDisplayManager {
RefreshRateCallbackWithDisplayManagerRefreshRateCallbackWithDisplayManager60 RefreshRateCallbackWithDisplayManager(const char* name, JNIEnv* env, jobject clazz)
61 : name(name), env(env), clazz(clazz) {}
62 std::string name;
63 JNIEnv* env;
64 jobject clazz;
65 int count{0};
66 std::chrono::nanoseconds vsyncPeriod{0LL};
67 };
68
refreshRateCallback(int64_t vsyncPeriodNanos,void * data)69 static void refreshRateCallback(int64_t vsyncPeriodNanos, void* data) {
70 std::lock_guard<std::mutex> _l(gLock);
71 RefreshRateCallback* cb = static_cast<RefreshRateCallback*>(data);
72 cb->count++;
73 cb->vsyncPeriod = std::chrono::nanoseconds{vsyncPeriodNanos};
74 }
75
refreshRateCallbackWithDisplayManager(int64_t vsyncPeriodNanos,void * data)76 static void refreshRateCallbackWithDisplayManager(int64_t vsyncPeriodNanos, void* data) {
77 std::lock_guard<std::mutex> _l(gLock);
78 RefreshRateCallbackWithDisplayManager* cb =
79 static_cast<RefreshRateCallbackWithDisplayManager*>(data);
80 cb->count++;
81 cb->vsyncPeriod = std::chrono::nanoseconds{vsyncPeriodNanos};
82 cb->env->CallVoidMethod(cb->clazz,
83 gJni.choreographerNativeTest.checkRefreshRateIsCurrentAndSwitch,
84 static_cast<int>(std::round(1e9f / cb->vsyncPeriod.count())));
85 }
86
dumpSupportedRefreshPeriods()87 static std::string dumpSupportedRefreshPeriods() {
88 std::stringstream ss;
89 ss << "{ ";
90 for (const long& period : gSupportedRefreshPeriods) {
91 ss << period << ",";
92 }
93 ss << "}";
94 return ss.str();
95 }
96
97 template <class T>
verifyRefreshRateCallback(JNIEnv * env,const T & cb,int expectedMin)98 static void verifyRefreshRateCallback(JNIEnv* env, const T& cb, int expectedMin) {
99 std::lock_guard<std::mutex> _l(gLock);
100 ASSERT(cb.count >= expectedMin, "Choreographer failed to invoke '%s' %d times - actual: %d",
101 cb.name.c_str(), expectedMin, cb.count);
102 // Unfortunately we can't verify the specific vsync period as public apis
103 // don't provide a guarantee that we adhere to a particular refresh rate.
104 // The best we can do is check that the reported period is contained in the
105 // set of supported periods.
106 ASSERT(cb.vsyncPeriod > ZERO,
107 "Choreographer failed to report a nonzero refresh period invoking '%s'",
108 cb.name.c_str());
109 ASSERT(gSupportedRefreshPeriods.count(cb.vsyncPeriod.count()) > 0,
110 "Choreographer failed to report a supported refresh period invoking '%s': supported "
111 "periods: %s, actual: %lu",
112 cb.name.c_str(), dumpSupportedRefreshPeriods().c_str(), cb.vsyncPeriod.count());
113 }
114
resetRefreshRateCallback(RefreshRateCallback & cb)115 static void resetRefreshRateCallback(RefreshRateCallback& cb) {
116 std::lock_guard<std::mutex> _l(gLock);
117 cb.count = 0;
118 }
119
android_view_surfacecontrol_cts_ChoreographerNativeTest_getChoreographer(JNIEnv *,jclass)120 static jlong android_view_surfacecontrol_cts_ChoreographerNativeTest_getChoreographer(JNIEnv*, jclass) {
121 std::lock_guard<std::mutex> _l{gLock};
122 return reinterpret_cast<jlong>(AChoreographer_getInstance());
123 }
124
android_view_surfacecontrol_cts_ChoreographerNativeTest_prepareChoreographerTests(JNIEnv * env,jclass,jlong choreographerPtr,jlongArray supportedRefreshPeriods)125 static jboolean android_view_surfacecontrol_cts_ChoreographerNativeTest_prepareChoreographerTests(JNIEnv* env, jclass,
126 jlong choreographerPtr, jlongArray supportedRefreshPeriods) {
127 std::lock_guard<std::mutex> _l{gLock};
128 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
129 const size_t count = env->GetArrayLength(supportedRefreshPeriods);
130 const jlong* vals = env->GetLongArrayElements(supportedRefreshPeriods, nullptr);
131 for (size_t i = 0; i < count; ++i) {
132 gSupportedRefreshPeriods.insert(vals[i]);
133 }
134 env->ReleaseLongArrayElements(supportedRefreshPeriods, const_cast<jlong*>(vals), JNI_ABORT);
135 return choreographer != nullptr;
136 }
137
138 static void
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)139 android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback(
140 JNIEnv* env, jclass, jlong choreographerPtr) {
141 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
142 VsyncCallback cb1("cb1", env);
143 VsyncCallback cb2("cb2", env);
144 auto start = now();
145
146 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
147 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb2);
148 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
149
150 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
151 verifyCallback(env, cb2, 1, start, NOMINAL_VSYNC_PERIOD * 3);
152 {
153 std::lock_guard<std::mutex> _l{gLock};
154 auto delta = cb2.frameTime - cb1.frameTime;
155 ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
156 "Callback 1 and 2 have frame times too large of a delta in frame times");
157 }
158
159 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
160 start = now();
161 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
162 verifyCallback(env, cb1, 2, start, NOMINAL_VSYNC_PERIOD * 3);
163 verifyCallback(env, cb2, 1, start, ZERO);
164 }
165
android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid(JNIEnv * env,jclass,jlong choreographerPtr)166 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid(
167 JNIEnv* env, jclass, jlong choreographerPtr) {
168 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
169 VsyncCallback cb1("cb1", env);
170 auto start = now();
171
172 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
173 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
174
175 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
176 std::lock_guard<std::mutex> _l{gLock};
177 for (const VsyncCallback::FrameTime& frameTime : cb1.getTimeline()) {
178 int64_t vsyncId = frameTime.vsyncId;
179 ASSERT(vsyncId >= 0, "Invalid vsync ID");
180 ASSERT(std::count_if(cb1.getTimeline().begin(), cb1.getTimeline().end(),
181 [vsyncId](const VsyncCallback::FrameTime& ft) {
182 return ft.vsyncId == vsyncId;
183 }) == 1,
184 "Vsync ID is not unique");
185 }
186 }
187
android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture(JNIEnv * env,jclass,jlong choreographerPtr)188 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture(
189 JNIEnv* env, jclass, jlong choreographerPtr) {
190 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
191 VsyncCallback cb1("cb1", env);
192 auto start = now();
193
194 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
195 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
196
197 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
198 std::lock_guard<std::mutex> _l{gLock};
199 std::vector<VsyncCallback::FrameTime> frameTimelines = cb1.getTimeline();
200 for (auto [i, lastValue] = std::tuple{0, cb1.frameTime}; i < frameTimelines.size(); i++) {
201 auto deadline = std::chrono::nanoseconds{frameTimelines[i].deadline};
202 ASSERT(deadline > std::chrono::nanoseconds{start}, "Deadline must be after start time");
203 ASSERT(deadline > cb1.frameTime, "Deadline must be after frame time");
204 ASSERT(deadline > lastValue, "Deadline must be greater than last frame deadline");
205 lastValue = deadline;
206 }
207 // To avoid API fragmentation, enforce there are at least a certain amount of frame timeline
208 // choices, by number of choices or by the last deadline timestamp.
209 ASSERT(std::chrono::nanoseconds{frameTimelines[frameTimelines.size() - 1].deadline} >
210 start + std::chrono::nanoseconds{45ms},
211 "Not enough later choices for frame timelines");
212 }
213
214 static void
android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(JNIEnv * env,jclass,jlong choreographerPtr)215 android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(
216 JNIEnv* env, jclass, jlong choreographerPtr) {
217 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
218 VsyncCallback cb1("cb1", env);
219 auto start = now();
220
221 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
222 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
223
224 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
225 std::lock_guard<std::mutex> _l{gLock};
226 for (auto [i, lastValue] = std::tuple{0, cb1.frameTime}; i < cb1.getTimeline().size(); i++) {
227 auto expectedPresentTime =
228 std::chrono::nanoseconds(cb1.getTimeline()[i].expectedPresentTime);
229 auto deadline = std::chrono::nanoseconds(cb1.getTimeline()[i].deadline);
230 ASSERT(expectedPresentTime > cb1.frameTime,
231 "Expected present time must be after frame time");
232 ASSERT(expectedPresentTime > deadline, "Expected present time must be after deadline");
233 ASSERT(expectedPresentTime > lastValue,
234 "Expected present time must be greater than last frame expected present time");
235 lastValue = expectedPresentTime;
236 }
237 }
238
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)239 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback(
240 JNIEnv* env, jclass, jlong choreographerPtr) {
241 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
242 Callback cb1("cb1");
243 Callback cb2("cb2");
244 auto start = now();
245
246 AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb1);
247 AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb2);
248 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
249
250 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
251 verifyCallback(env, cb2, 1, start, NOMINAL_VSYNC_PERIOD * 3);
252 {
253 std::lock_guard<std::mutex> _l{gLock};
254 auto delta = cb2.frameTime - cb1.frameTime;
255 ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
256 "Callback 1 and 2 have frame times too large of a delta in frame times");
257 }
258
259 AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb1);
260 start = now();
261 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
262 verifyCallback(env, cb1, 2, start, NOMINAL_VSYNC_PERIOD * 3);
263 verifyCallback(env, cb2, 1, start, ZERO);
264 }
265
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)266 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback(
267 JNIEnv* env, jclass, jlong choreographerPtr) {
268 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
269 Callback cb1 = Callback("cb1");
270 auto start = now();
271
272 auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
273 AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb1, delay);
274
275 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
276 verifyCallback(env, cb1, 0, start, ZERO);
277
278 std::this_thread::sleep_for(DELAY_PERIOD);
279 verifyCallback(env, cb1, 1, start, DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3);
280 }
281
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)282 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback(
283 JNIEnv* env, jclass, jlong choreographerPtr) {
284 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
285 Callback cb1("cb1");
286 Callback cb2("cb2");
287 auto start = now();
288 const auto delay = NOMINAL_VSYNC_PERIOD * 3;
289 // Delay calculations are known to be broken on 32-bit systems (overflow),
290 // so we skip testing the delay on such systems by setting this to ZERO.
291 const auto delayToTest = sizeof(long) == sizeof(int64_t) ? delay : ZERO;
292
293 AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
294 AChoreographer_postFrameCallback(choreographer, frameCallback, &cb2);
295 std::this_thread::sleep_for(delay);
296
297 verifyCallback(env, cb1, 1, start, delayToTest);
298 verifyCallback(env, cb2, 1, start, delayToTest);
299
300 // This delta can only be reliably calculated on 64-bit systems. We skip this
301 // part of the test on systems known to be broken.
302 if (sizeof(long) == sizeof(int64_t)) {
303 std::lock_guard<std::mutex> _l{gLock};
304 auto delta = cb2.frameTime - cb1.frameTime;
305 ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
306 "Callback 1 and 2 have frame times too large of a delta in frame times");
307 }
308
309 AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
310 start = now();
311 std::this_thread::sleep_for(delay);
312
313 verifyCallback(env, cb1, 2, start, delayToTest);
314 verifyCallback(env, cb2, 1, start, ZERO);
315 }
316
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)317 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback(
318 JNIEnv* env, jclass, jlong choreographerPtr) {
319 if (sizeof(long) != sizeof(int64_t)) {
320 // skip test for known broken states.
321 return;
322 }
323
324 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
325 Callback cb1("cb1");
326 auto start = now();
327
328 auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
329 AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
330
331 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
332 verifyCallback(env, cb1, 0, start, ZERO);
333
334 std::this_thread::sleep_for(DELAY_PERIOD);
335 const auto delayToTest =
336 sizeof(long) == sizeof(int64_t) ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3 : ZERO;
337 verifyCallback(env, cb1, 1, start, delayToTest);
338 }
339
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)340 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback(
341 JNIEnv* env, jclass, jlong choreographerPtr) {
342 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
343 Callback cb1("cb1");
344 Callback cb64("cb64");
345 auto start = now();
346
347 AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
348 AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb64);
349 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
350
351 verifyCallback(env, cb1, 1, start, ZERO);
352 verifyCallback(env, cb64, 1, start, NOMINAL_VSYNC_PERIOD * 3);
353
354 // This delta can only be reliably calculated on 64-bit systems. We skip this
355 // part of the test on systems known to be broken.
356 if (sizeof(long) == sizeof(int64_t)) {
357 std::lock_guard<std::mutex> _l{gLock};
358 auto delta = cb64.frameTime - cb1.frameTime;
359 ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
360 "Callback 1 and 2 have frame times too large of a delta in frame times");
361 }
362
363 AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb64);
364 start = now();
365 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
366 verifyCallback(env, cb1, 1, start, ZERO);
367 verifyCallback(env, cb64, 2, start, NOMINAL_VSYNC_PERIOD * 3);
368 }
369
android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)370 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback(
371 JNIEnv* env, jclass, jlong choreographerPtr) {
372 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
373 Callback cb1("cb1");
374 Callback cb64("cb64");
375 auto start = now();
376
377 auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
378 AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
379 AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb64, delay);
380
381 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
382 verifyCallback(env, cb1, 0, start, ZERO);
383 verifyCallback(env, cb64, 0, start, ZERO);
384
385 std::this_thread::sleep_for(DELAY_PERIOD);
386 verifyCallback(env, cb64, 1, start, DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3);
387 const auto delayToTestFor32Bit =
388 sizeof(long) == sizeof(int64_t) ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3 : ZERO;
389 verifyCallback(env, cb1, 1, start, delayToTestFor32Bit);
390 }
391
android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallback(JNIEnv * env,jclass,jlong choreographerPtr)392 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallback(
393 JNIEnv* env, jclass, jlong choreographerPtr) {
394 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
395 RefreshRateCallback cb("cb");
396
397 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb);
398
399 // Give the display system time to push an initial callback.
400 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
401 verifyRefreshRateCallback<RefreshRateCallback>(env, cb, 1);
402 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
403 }
404
android_view_surfacecontrol_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback(JNIEnv * env,jclass,jlong choreographerPtr)405 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback(
406 JNIEnv* env, jclass, jlong choreographerPtr) {
407 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
408 RefreshRateCallback cb1("cb1");
409 RefreshRateCallback cb2("cb2");
410
411 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
412
413 // Give the display system time to push an initial callback.
414 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
415 verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
416
417 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
418 // Flush out pending callback events for the callback
419 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
420 resetRefreshRateCallback(cb1);
421
422 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
423 // Verify that cb2 is called on registration, but not cb1.
424 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
425 verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 0);
426 verifyRefreshRateCallback<RefreshRateCallback>(env, cb2, 1);
427 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
428 }
429
android_view_surfacecontrol_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks(JNIEnv * env,jclass,jlong choreographerPtr)430 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks(
431 JNIEnv* env, jclass, jlong choreographerPtr) {
432 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
433 RefreshRateCallback cb1("cb1");
434 RefreshRateCallback cb2("cb2");
435
436 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
437 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
438
439 // Give the display system time to push an initial refresh rate change.
440 // Polling the event will allow both callbacks to be triggered.
441 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
442 verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
443 verifyRefreshRateCallback<RefreshRateCallback>(env, cb2, 1);
444
445 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
446 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
447 }
448
android_view_surfacecontrol_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice(JNIEnv * env,jclass,jlong choreographerPtr)449 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice(
450 JNIEnv* env, jclass, jlong choreographerPtr) {
451 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
452 RefreshRateCallback cb1("cb1");
453 RefreshRateCallback cb2("cb2");
454
455 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
456 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
457
458 // Give the display system time to push an initial callback.
459 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
460 verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
461
462 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
463 // Flush out pending callback events for the callback
464 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
465 resetRefreshRateCallback(cb1);
466
467 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
468 // Verify that cb1 is not called again, even thiough it was registered once
469 // and unregistered again
470 std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
471 verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 0);
472 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
473 }
474
475 // This test must be run on the UI thread for fine-grained control of looper
476 // scheduling.
android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks(JNIEnv * env,jclass,jlong choreographerPtr)477 static void android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks(
478 JNIEnv* env, jclass, jlong choreographerPtr) {
479 AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
480 RefreshRateCallback cb("cb");
481
482 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb);
483
484 Callback cb1("cb1");
485 Callback cb64("cb64");
486 auto start = now();
487
488 auto vsyncPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(
489 NOMINAL_VSYNC_PERIOD)
490 .count();
491 auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
492 AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
493 AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb64, delay);
494
495 std::this_thread::sleep_for(DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 10);
496 // Ensure that callbacks are seen by the looper instance at approximately
497 // the same time, and provide enough time for the looper instance to process
498 // the delayed callback and the requested vsync signal if needed.
499 int pollResult;
500 do {
501 pollResult = ALooper_pollOnce(vsyncPeriod * 5, nullptr, nullptr, nullptr);
502 } while (pollResult != ALOOPER_POLL_TIMEOUT && pollResult != ALOOPER_POLL_ERROR);
503 verifyRefreshRateCallback<RefreshRateCallback>(env, cb, 1);
504 verifyCallback(env, cb64, 1, start,
505 DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15);
506 const auto delayToTestFor32Bit =
507 sizeof(long) == sizeof(int64_t)
508 ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15
509 : ZERO;
510 verifyCallback(env, cb1, 1, start, delayToTestFor32Bit);
511 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
512 }
513
514 // This test cannot be run on the UI thread because it relies on callbacks to be dispatched on the
515 // application UI thread.
516 static void
android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager(JNIEnv * env,jobject clazz)517 android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager(
518 JNIEnv* env, jobject clazz) {
519 // Test harness choreographer is not on the main thread, so create a thread-local choreographer
520 // instance.
521 ALooper_prepare(0);
522 AChoreographer* choreographer = AChoreographer_getInstance();
523 RefreshRateCallbackWithDisplayManager cb("cb", env, clazz);
524
525 AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallbackWithDisplayManager,
526 &cb);
527
528 auto delayPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
529
530 const size_t numRuns = 1000;
531 int previousCount = 0;
532 for (int i = 0; i < numRuns; ++i) {
533 const size_t numTries = 5;
534 for (int j = 0; j < numTries; j++) {
535 // In theory we only need to poll once because the test harness configuration should
536 // enforce that we won't get spurious callbacks. In practice, there may still be
537 // spurious callbacks due to hotplug or other display events that aren't suppressed. So
538 // we add some slack by retrying a few times, but we stop at the first refresh rate
539 // callback (1) to keep the test runtime reasonably short, and (2) to keep the test
540 // under better control so that it does not spam the system with refresh rate changes.
541 int result = ALooper_pollOnce(delayPeriod * 5, nullptr, nullptr, nullptr);
542 ASSERT(result == ALOOPER_POLL_CALLBACK, "Callback failed on run: %d with error: %d", i,
543 result);
544 if (previousCount != cb.count) {
545 verifyRefreshRateCallback<RefreshRateCallbackWithDisplayManager>(env, cb,
546 previousCount + 1);
547 previousCount = cb.count;
548 break;
549 }
550
551 ASSERT(j < numTries - 1, "No callback observed for run: %d", i);
552 }
553 }
554 AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
555 }
556
557 static JNINativeMethod gMethods[] = {
558 {"nativeGetChoreographer", "()J",
559 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_getChoreographer},
560 {"nativePrepareChoreographerTests", "(J[J)Z",
561 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_prepareChoreographerTests},
562 {"nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
563 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback},
564 {"nativeTestFrameCallbackDataVsyncIdValid", "(J)V",
565 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid},
566 {"nativeTestFrameCallbackDataDeadlineInFuture", "(J)V",
567 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture},
568 {"nativeTestFrameCallbackDataExpectedPresentTimeInFuture", "(J)V",
569 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture},
570 {"nativeTestPostCallback64WithoutDelayEventuallyRunsCallbacks", "(J)V",
571 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback},
572 {"nativeTestPostCallback64WithDelayEventuallyRunsCallbacks", "(J)V",
573 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback},
574 {"nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
575 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback},
576 {"nativeTestPostCallbackWithDelayEventuallyRunsCallbacks", "(J)V",
577 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback},
578 {"nativeTestPostCallbackMixedWithoutDelayEventuallyRunsCallbacks", "(J)V",
579 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback},
580 {"nativeTestPostCallbackMixedWithDelayEventuallyRunsCallbacks", "(J)V",
581 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback},
582 {"nativeTestRefreshRateCallback", "(J)V",
583 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallback},
584 {"nativeTestUnregisteringRefreshRateCallback", "(J)V",
585 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback},
586 {"nativeTestMultipleRefreshRateCallbacks", "(J)V",
587 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks},
588 {"nativeTestAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice", "(J)V",
589 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice},
590 {"nativeTestRefreshRateCallbackMixedWithFrameCallbacks", "(J)V",
591 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks},
592 {"nativeTestRefreshRateCallbacksAreSyncedWithDisplayManager", "()V",
593 (void*)android_view_surfacecontrol_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager},
594 };
595
register_android_view_surfacecontrol_cts_ChoreographerNativeTest(JNIEnv * env)596 int register_android_view_surfacecontrol_cts_ChoreographerNativeTest(JNIEnv* env)
597 {
598 jclass clazz = env->FindClass("android/view/surfacecontrol/cts/ChoreographerNativeTest");
599 gJni.choreographerNativeTest.clazz = static_cast<jclass>(env->NewGlobalRef(clazz));
600 gJni.choreographerNativeTest.checkRefreshRateIsCurrentAndSwitch =
601 env->GetMethodID(clazz, "checkRefreshRateIsCurrentAndSwitch", "(I)V");
602 return env->RegisterNatives(clazz, gMethods,
603 sizeof(gMethods) / sizeof(JNINativeMethod));
604 }
605