• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_cts_ChoreographerNativeTest_getChoreographer(JNIEnv *,jclass)120 static jlong android_view_cts_ChoreographerNativeTest_getChoreographer(JNIEnv*, jclass) {
121     std::lock_guard<std::mutex> _l{gLock};
122     return reinterpret_cast<jlong>(AChoreographer_getInstance());
123 }
124 
android_view_cts_ChoreographerNativeTest_prepareChoreographerTests(JNIEnv * env,jclass,jlong choreographerPtr,jlongArray supportedRefreshPeriods)125 static jboolean android_view_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_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)139 android_view_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_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid(JNIEnv * env,jclass,jlong choreographerPtr)166 static void android_view_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_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture(JNIEnv * env,jclass,jlong choreographerPtr)188 static void android_view_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     for (auto [i, lastValue] = std::tuple{0, cb1.frameTime}; i < cb1.getTimeline().size(); i++) {
200         auto deadline = std::chrono::nanoseconds{cb1.getTimeline()[i].deadline};
201         ASSERT(deadline > std::chrono::nanoseconds{start}, "Deadline must be after start time");
202         ASSERT(deadline > cb1.frameTime, "Deadline must be after frame time");
203         ASSERT(deadline > lastValue, "Deadline must be greater than last frame deadline");
204         lastValue = deadline;
205     }
206 }
207 
208 static void
android_view_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(JNIEnv * env,jclass,jlong choreographerPtr)209 android_view_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(
210         JNIEnv* env, jclass, jlong choreographerPtr) {
211     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
212     VsyncCallback cb1("cb1", env);
213     auto start = now();
214 
215     AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
216     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
217 
218     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
219     std::lock_guard<std::mutex> _l{gLock};
220     for (auto [i, lastValue] = std::tuple{0, cb1.frameTime}; i < cb1.getTimeline().size(); i++) {
221         auto expectedPresentTime =
222                 std::chrono::nanoseconds(cb1.getTimeline()[i].expectedPresentTime);
223         auto deadline = std::chrono::nanoseconds(cb1.getTimeline()[i].deadline);
224         ASSERT(expectedPresentTime > cb1.frameTime,
225                "Expected present time must be after frame time");
226         ASSERT(expectedPresentTime > deadline, "Expected present time must be after deadline");
227         ASSERT(expectedPresentTime > lastValue,
228                "Expected present time must be greater than last frame expected present time");
229         lastValue = expectedPresentTime;
230     }
231 }
232 
android_view_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)233 static void android_view_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback(
234         JNIEnv* env, jclass, jlong choreographerPtr) {
235     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
236     Callback cb1("cb1");
237     Callback cb2("cb2");
238     auto start = now();
239 
240     AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb1);
241     AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb2);
242     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
243 
244     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
245     verifyCallback(env, cb2, 1, start, NOMINAL_VSYNC_PERIOD * 3);
246     {
247         std::lock_guard<std::mutex> _l{gLock};
248         auto delta = cb2.frameTime - cb1.frameTime;
249         ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
250                 "Callback 1 and 2 have frame times too large of a delta in frame times");
251     }
252 
253     AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb1);
254     start = now();
255     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
256     verifyCallback(env, cb1, 2, start, NOMINAL_VSYNC_PERIOD * 3);
257     verifyCallback(env, cb2, 1, start, ZERO);
258 }
259 
android_view_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)260 static void android_view_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback(
261         JNIEnv* env, jclass, jlong choreographerPtr) {
262     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
263     Callback cb1 = Callback("cb1");
264     auto start = now();
265 
266     auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
267     AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb1, delay);
268 
269     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
270     verifyCallback(env, cb1, 0, start, ZERO);
271 
272     std::this_thread::sleep_for(DELAY_PERIOD);
273     verifyCallback(env, cb1, 1, start, DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3);
274 }
275 
android_view_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)276 static void android_view_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback(
277         JNIEnv* env, jclass, jlong choreographerPtr) {
278     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
279     Callback cb1("cb1");
280     Callback cb2("cb2");
281     auto start = now();
282     const auto delay = NOMINAL_VSYNC_PERIOD * 3;
283     // Delay calculations are known to be broken on 32-bit systems (overflow),
284     // so we skip testing the delay on such systems by setting this to ZERO.
285     const auto delayToTest = sizeof(long) == sizeof(int64_t) ? delay : ZERO;
286 
287     AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
288     AChoreographer_postFrameCallback(choreographer, frameCallback, &cb2);
289     std::this_thread::sleep_for(delay);
290 
291     verifyCallback(env, cb1, 1, start, delayToTest);
292     verifyCallback(env, cb2, 1, start, delayToTest);
293 
294     // This delta can only be reliably calculated on 64-bit systems.  We skip this
295     // part of the test on systems known to be broken.
296     if (sizeof(long) == sizeof(int64_t)) {
297         std::lock_guard<std::mutex> _l{gLock};
298         auto delta = cb2.frameTime - cb1.frameTime;
299         ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
300                 "Callback 1 and 2 have frame times too large of a delta in frame times");
301     }
302 
303     AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
304     start = now();
305     std::this_thread::sleep_for(delay);
306 
307     verifyCallback(env, cb1, 2, start, delayToTest);
308     verifyCallback(env, cb2, 1, start, ZERO);
309 }
310 
android_view_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)311 static void android_view_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback(
312         JNIEnv* env, jclass, jlong choreographerPtr) {
313     if (sizeof(long) != sizeof(int64_t)) {
314         // skip test for known broken states.
315         return;
316     }
317 
318     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
319     Callback cb1("cb1");
320     auto start = now();
321 
322     auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
323     AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
324 
325     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
326     verifyCallback(env, cb1, 0, start, ZERO);
327 
328     std::this_thread::sleep_for(DELAY_PERIOD);
329     const auto delayToTest =
330             sizeof(long) == sizeof(int64_t) ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3 : ZERO;
331     verifyCallback(env, cb1, 1, start, delayToTest);
332 }
333 
android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)334 static void android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback(
335         JNIEnv* env, jclass, jlong choreographerPtr) {
336     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
337     Callback cb1("cb1");
338     Callback cb64("cb64");
339     auto start = now();
340 
341     AChoreographer_postFrameCallback(choreographer, frameCallback, &cb1);
342     AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb64);
343     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
344 
345     verifyCallback(env, cb1, 1, start, ZERO);
346     verifyCallback(env, cb64, 1, start, NOMINAL_VSYNC_PERIOD * 3);
347 
348     // This delta can only be reliably calculated on 64-bit systems.  We skip this
349     // part of the test on systems known to be broken.
350     if (sizeof(long) == sizeof(int64_t)) {
351         std::lock_guard<std::mutex> _l{gLock};
352         auto delta = cb64.frameTime - cb1.frameTime;
353         ASSERT(delta == ZERO || delta > ZERO && delta < NOMINAL_VSYNC_PERIOD * 2,
354                 "Callback 1 and 2 have frame times too large of a delta in frame times");
355     }
356 
357     AChoreographer_postFrameCallback64(choreographer, frameCallback64, &cb64);
358     start = now();
359     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
360     verifyCallback(env, cb1, 1, start, ZERO);
361     verifyCallback(env, cb64, 2, start, NOMINAL_VSYNC_PERIOD * 3);
362 }
363 
android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback(JNIEnv * env,jclass,jlong choreographerPtr)364 static void android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback(
365         JNIEnv* env, jclass, jlong choreographerPtr) {
366     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
367     Callback cb1("cb1");
368     Callback cb64("cb64");
369     auto start = now();
370 
371     auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
372     AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
373     AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb64, delay);
374 
375     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
376     verifyCallback(env, cb1, 0, start, ZERO);
377     verifyCallback(env, cb64, 0, start, ZERO);
378 
379     std::this_thread::sleep_for(DELAY_PERIOD);
380     verifyCallback(env, cb64, 1, start, DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3);
381     const auto delayToTestFor32Bit =
382             sizeof(long) == sizeof(int64_t) ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3 : ZERO;
383     verifyCallback(env, cb1, 1, start, delayToTestFor32Bit);
384 }
385 
android_view_cts_ChoreographerNativeTest_testRefreshRateCallback(JNIEnv * env,jclass,jlong choreographerPtr)386 static void android_view_cts_ChoreographerNativeTest_testRefreshRateCallback(
387         JNIEnv* env, jclass, jlong choreographerPtr) {
388     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
389     RefreshRateCallback cb("cb");
390 
391     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb);
392 
393     // Give the display system time to push an initial callback.
394     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
395     verifyRefreshRateCallback<RefreshRateCallback>(env, cb, 1);
396     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
397 }
398 
android_view_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback(JNIEnv * env,jclass,jlong choreographerPtr)399 static void android_view_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback(
400         JNIEnv* env, jclass, jlong choreographerPtr) {
401     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
402     RefreshRateCallback cb1("cb1");
403     RefreshRateCallback cb2("cb2");
404 
405     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
406 
407     // Give the display system time to push an initial callback.
408     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
409     verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
410 
411     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
412     // Flush out pending callback events for the callback
413     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
414     resetRefreshRateCallback(cb1);
415 
416     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
417     // Verify that cb2 is called on registration, but not cb1.
418     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
419     verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 0);
420     verifyRefreshRateCallback<RefreshRateCallback>(env, cb2, 1);
421     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
422 }
423 
android_view_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks(JNIEnv * env,jclass,jlong choreographerPtr)424 static void android_view_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks(
425         JNIEnv* env, jclass, jlong choreographerPtr) {
426     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
427     RefreshRateCallback cb1("cb1");
428     RefreshRateCallback cb2("cb2");
429 
430     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
431     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
432 
433     // Give the display system time to push an initial refresh rate change.
434     // Polling the event will allow both callbacks to be triggered.
435     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
436     verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
437     verifyRefreshRateCallback<RefreshRateCallback>(env, cb2, 1);
438 
439     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
440     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
441 }
442 
android_view_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice(JNIEnv * env,jclass,jlong choreographerPtr)443 static void android_view_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice(
444         JNIEnv* env, jclass, jlong choreographerPtr) {
445     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
446     RefreshRateCallback cb1("cb1");
447     RefreshRateCallback cb2("cb2");
448 
449     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
450     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
451 
452     // Give the display system time to push an initial callback.
453     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
454     verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 1);
455 
456     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb1);
457     // Flush out pending callback events for the callback
458     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
459     resetRefreshRateCallback(cb1);
460 
461     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
462     // Verify that cb1 is not called again, even thiough it was registered once
463     // and unregistered again
464     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 10);
465     verifyRefreshRateCallback<RefreshRateCallback>(env, cb1, 0);
466     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb2);
467 }
468 
469 // This test must be run on the UI thread for fine-grained control of looper
470 // scheduling.
android_view_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks(JNIEnv * env,jclass,jlong choreographerPtr)471 static void android_view_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks(
472         JNIEnv* env, jclass, jlong choreographerPtr) {
473     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
474     RefreshRateCallback cb("cb");
475 
476     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallback, &cb);
477 
478     Callback cb1("cb1");
479     Callback cb64("cb64");
480     auto start = now();
481 
482     auto vsyncPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(
483                            NOMINAL_VSYNC_PERIOD)
484                            .count();
485     auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
486     AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, &cb1, delay);
487     AChoreographer_postFrameCallbackDelayed64(choreographer, frameCallback64, &cb64, delay);
488 
489     std::this_thread::sleep_for(DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 10);
490     // Ensure that callbacks are seen by the looper instance at approximately
491     // the same time, and provide enough time for the looper instance to process
492     // the delayed callback and the requested vsync signal if needed.
493     ALooper_pollAll(vsyncPeriod * 5, nullptr, nullptr, nullptr);
494     verifyRefreshRateCallback<RefreshRateCallback>(env, cb, 1);
495     verifyCallback(env, cb64, 1, start,
496                    DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15);
497     const auto delayToTestFor32Bit =
498         sizeof(long) == sizeof(int64_t)
499             ? DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 15
500             : ZERO;
501     verifyCallback(env, cb1, 1, start, delayToTestFor32Bit);
502     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
503 }
504 
505 // This test cannot be run on the UI thread because it relies on callbacks to be dispatched on the
506 // application UI thread.
507 static void
android_view_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager(JNIEnv * env,jobject clazz)508 android_view_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager(
509         JNIEnv* env, jobject clazz) {
510     // Test harness choreographer is not on the main thread, so create a thread-local choreographer
511     // instance.
512     ALooper_prepare(0);
513     AChoreographer* choreographer = AChoreographer_getInstance();
514     RefreshRateCallbackWithDisplayManager cb("cb", env, clazz);
515 
516     AChoreographer_registerRefreshRateCallback(choreographer, refreshRateCallbackWithDisplayManager,
517                                                &cb);
518 
519     auto delayPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
520 
521     const size_t numRuns = 1000;
522     int previousCount = 0;
523     for (int i = 0; i < numRuns; ++i) {
524         const size_t numTries = 5;
525         for (int j = 0; j < numTries; j++) {
526             // In theory we only need to poll once because the test harness configuration should
527             // enforce that we won't get spurious callbacks. In practice, there may still be
528             // spurious callbacks due to hotplug or other display events that aren't suppressed. So
529             // we add some slack by retrying a few times, but we stop at the first refresh rate
530             // callback (1) to keep the test runtime reasonably short, and (2) to keep the test
531             // under better control so that it does not spam the system with refresh rate changes.
532             int result = ALooper_pollOnce(delayPeriod * 5, nullptr, nullptr, nullptr);
533             ASSERT(result == ALOOPER_POLL_CALLBACK, "Callback failed on run: %d with error: %d", i,
534                    result);
535             if (previousCount != cb.count) {
536                 verifyRefreshRateCallback<RefreshRateCallbackWithDisplayManager>(env, cb,
537                                                                                  previousCount + 1);
538                 previousCount = cb.count;
539                 break;
540             }
541 
542             ASSERT(j < numTries - 1, "No callback observed for run: %d", i);
543         }
544     }
545     AChoreographer_unregisterRefreshRateCallback(choreographer, refreshRateCallback, &cb);
546 }
547 
548 static JNINativeMethod gMethods[] = {
549         {"nativeGetChoreographer", "()J",
550          (void*)android_view_cts_ChoreographerNativeTest_getChoreographer},
551         {"nativePrepareChoreographerTests", "(J[J)Z",
552          (void*)android_view_cts_ChoreographerNativeTest_prepareChoreographerTests},
553         {"nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
554          (void*)android_view_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback},
555         {"nativeTestFrameCallbackDataVsyncIdValid", "(J)V",
556          (void*)android_view_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid},
557         {"nativeTestFrameCallbackDataDeadlineInFuture", "(J)V",
558          (void*)android_view_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture},
559         {"nativeTestFrameCallbackDataExpectedPresentTimeInFuture", "(J)V",
560          (void*)android_view_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture},
561         {"nativeTestPostCallback64WithoutDelayEventuallyRunsCallbacks", "(J)V",
562          (void*)android_view_cts_ChoreographerNativeTest_testPostCallback64WithoutDelayEventuallyRunsCallback},
563         {"nativeTestPostCallback64WithDelayEventuallyRunsCallbacks", "(J)V",
564          (void*)android_view_cts_ChoreographerNativeTest_testPostCallback64WithDelayEventuallyRunsCallback},
565         {"nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
566          (void*)android_view_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback},
567         {"nativeTestPostCallbackWithDelayEventuallyRunsCallbacks", "(J)V",
568          (void*)android_view_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback},
569         {"nativeTestPostCallbackMixedWithoutDelayEventuallyRunsCallbacks", "(J)V",
570          (void*)android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithoutDelayEventuallyRunsCallback},
571         {"nativeTestPostCallbackMixedWithDelayEventuallyRunsCallbacks", "(J)V",
572          (void*)android_view_cts_ChoreographerNativeTest_testPostCallbackMixedWithDelayEventuallyRunsCallback},
573         {"nativeTestRefreshRateCallback", "(J)V",
574          (void*)android_view_cts_ChoreographerNativeTest_testRefreshRateCallback},
575         {"nativeTestUnregisteringRefreshRateCallback", "(J)V",
576          (void*)android_view_cts_ChoreographerNativeTest_testUnregisteringRefreshRateCallback},
577         {"nativeTestMultipleRefreshRateCallbacks", "(J)V",
578          (void*)android_view_cts_ChoreographerNativeTest_testMultipleRefreshRateCallbacks},
579         {"nativeTestAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice", "(J)V",
580          (void*)android_view_cts_ChoreographerNativeTest_testAttemptToAddRefreshRateCallbackTwiceDoesNotAddTwice},
581         {"nativeTestRefreshRateCallbackMixedWithFrameCallbacks", "(J)V",
582          (void*)android_view_cts_ChoreographerNativeTest_testRefreshRateCallbackMixedWithFrameCallbacks},
583         {"nativeTestRefreshRateCallbacksAreSyncedWithDisplayManager", "()V",
584          (void*)android_view_cts_ChoreographerNativeTest_testRefreshRateCallbacksAreSyncedWithDisplayManager},
585 };
586 
register_android_view_cts_ChoreographerNativeTest(JNIEnv * env)587 int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env)
588 {
589     jclass clazz = env->FindClass("android/view/cts/ChoreographerNativeTest");
590     gJni.choreographerNativeTest.clazz = static_cast<jclass>(env->NewGlobalRef(clazz));
591     gJni.choreographerNativeTest.checkRefreshRateIsCurrentAndSwitch =
592             env->GetMethodID(clazz, "checkRefreshRateIsCurrentAndSwitch", "(I)V");
593     return env->RegisterNatives(clazz, gMethods,
594             sizeof(gMethods) / sizeof(JNINativeMethod));
595 }
596