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