• 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_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