xref: /aosp_15_r20/cts/tests/surfacecontrol/jni/ChoreographerTestUtils.h (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker  *
4*b7c941bbSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*b7c941bbSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*b7c941bbSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*b7c941bbSAndroid Build Coastguard Worker  *
8*b7c941bbSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*b7c941bbSAndroid Build Coastguard Worker  *
10*b7c941bbSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*b7c941bbSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*b7c941bbSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b7c941bbSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*b7c941bbSAndroid Build Coastguard Worker  * limitations under the License.
15*b7c941bbSAndroid Build Coastguard Worker  *
16*b7c941bbSAndroid Build Coastguard Worker  */
17*b7c941bbSAndroid Build Coastguard Worker 
18*b7c941bbSAndroid Build Coastguard Worker #include <android/choreographer.h>
19*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h>
20*b7c941bbSAndroid Build Coastguard Worker #include <android/looper.h>
21*b7c941bbSAndroid Build Coastguard Worker #include <android/trace.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <jni.h>
23*b7c941bbSAndroid Build Coastguard Worker #include <jniAssert.h>
24*b7c941bbSAndroid Build Coastguard Worker #include <sys/time.h>
25*b7c941bbSAndroid Build Coastguard Worker #include <time.h>
26*b7c941bbSAndroid Build Coastguard Worker 
27*b7c941bbSAndroid Build Coastguard Worker #include <chrono>
28*b7c941bbSAndroid Build Coastguard Worker #include <cinttypes>
29*b7c941bbSAndroid Build Coastguard Worker #include <cmath>
30*b7c941bbSAndroid Build Coastguard Worker #include <cstdlib>
31*b7c941bbSAndroid Build Coastguard Worker #include <cstring>
32*b7c941bbSAndroid Build Coastguard Worker #include <limits>
33*b7c941bbSAndroid Build Coastguard Worker #include <mutex>
34*b7c941bbSAndroid Build Coastguard Worker #include <set>
35*b7c941bbSAndroid Build Coastguard Worker #include <sstream>
36*b7c941bbSAndroid Build Coastguard Worker #include <string>
37*b7c941bbSAndroid Build Coastguard Worker #include <thread>
38*b7c941bbSAndroid Build Coastguard Worker #include <tuple>
39*b7c941bbSAndroid Build Coastguard Worker #include <vector>
40*b7c941bbSAndroid Build Coastguard Worker 
41*b7c941bbSAndroid Build Coastguard Worker using namespace std::chrono_literals;
42*b7c941bbSAndroid Build Coastguard Worker static constexpr std::chrono::nanoseconds NOMINAL_VSYNC_PERIOD{16ms};
43*b7c941bbSAndroid Build Coastguard Worker static constexpr std::chrono::nanoseconds DELAY_PERIOD{NOMINAL_VSYNC_PERIOD * 5};
44*b7c941bbSAndroid Build Coastguard Worker static constexpr std::chrono::nanoseconds ZERO{std::chrono::nanoseconds::zero()};
45*b7c941bbSAndroid Build Coastguard Worker 
46*b7c941bbSAndroid Build Coastguard Worker #define NANOS_PER_SECOND 1000000000LL
systemTime()47*b7c941bbSAndroid Build Coastguard Worker static int64_t systemTime() {
48*b7c941bbSAndroid Build Coastguard Worker     struct timespec time;
49*b7c941bbSAndroid Build Coastguard Worker     int result = clock_gettime(CLOCK_MONOTONIC, &time);
50*b7c941bbSAndroid Build Coastguard Worker     if (result < 0) {
51*b7c941bbSAndroid Build Coastguard Worker         return -errno;
52*b7c941bbSAndroid Build Coastguard Worker     }
53*b7c941bbSAndroid Build Coastguard Worker     return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
54*b7c941bbSAndroid Build Coastguard Worker }
55*b7c941bbSAndroid Build Coastguard Worker 
56*b7c941bbSAndroid Build Coastguard Worker static std::mutex gLock;
57*b7c941bbSAndroid Build Coastguard Worker struct Callback {
CallbackCallback58*b7c941bbSAndroid Build Coastguard Worker     Callback(const char* name) : name(name) {}
59*b7c941bbSAndroid Build Coastguard Worker     std::string name;
60*b7c941bbSAndroid Build Coastguard Worker     int count{0};
61*b7c941bbSAndroid Build Coastguard Worker     std::chrono::nanoseconds frameTime{0LL};
62*b7c941bbSAndroid Build Coastguard Worker };
63*b7c941bbSAndroid Build Coastguard Worker 
64*b7c941bbSAndroid Build Coastguard Worker struct VsyncCallback : Callback {
VsyncCallbackVsyncCallback65*b7c941bbSAndroid Build Coastguard Worker     VsyncCallback(const char* name, JNIEnv* env) : Callback(name), env(env) {}
66*b7c941bbSAndroid Build Coastguard Worker 
67*b7c941bbSAndroid Build Coastguard Worker     struct FrameTime {
FrameTimeVsyncCallback::FrameTime68*b7c941bbSAndroid Build Coastguard Worker         FrameTime(const AChoreographerFrameCallbackData* callbackData, int index)
69*b7c941bbSAndroid Build Coastguard Worker               : vsyncId(AChoreographerFrameCallbackData_getFrameTimelineVsyncId(callbackData,
70*b7c941bbSAndroid Build Coastguard Worker                                                                                 index)),
71*b7c941bbSAndroid Build Coastguard Worker                 expectedPresentTime(
72*b7c941bbSAndroid Build Coastguard Worker                         AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
73*b7c941bbSAndroid Build Coastguard Worker                                 callbackData, index)),
74*b7c941bbSAndroid Build Coastguard Worker                 deadline(AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(callbackData,
75*b7c941bbSAndroid Build Coastguard Worker                                                                                        index)) {}
76*b7c941bbSAndroid Build Coastguard Worker 
77*b7c941bbSAndroid Build Coastguard Worker         const AVsyncId vsyncId{-1};
78*b7c941bbSAndroid Build Coastguard Worker         const int64_t expectedPresentTime{-1};
79*b7c941bbSAndroid Build Coastguard Worker         const int64_t deadline{-1};
80*b7c941bbSAndroid Build Coastguard Worker     };
81*b7c941bbSAndroid Build Coastguard Worker 
populateVsyncCallback82*b7c941bbSAndroid Build Coastguard Worker     void populate(const AChoreographerFrameCallbackData* callbackData) {
83*b7c941bbSAndroid Build Coastguard Worker         size_t index = AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(callbackData);
84*b7c941bbSAndroid Build Coastguard Worker         preferredFrameTimelineIndex = index;
85*b7c941bbSAndroid Build Coastguard Worker         size_t length = AChoreographerFrameCallbackData_getFrameTimelinesLength(callbackData);
86*b7c941bbSAndroid Build Coastguard Worker         ASSERT(index < length, "Preferred frame timeline index out of bounds");
87*b7c941bbSAndroid Build Coastguard Worker         timelines.reserve(length);
88*b7c941bbSAndroid Build Coastguard Worker 
89*b7c941bbSAndroid Build Coastguard Worker         for (int i = 0; i < length; i++) {
90*b7c941bbSAndroid Build Coastguard Worker             timelines.push_back(FrameTime(callbackData, i));
91*b7c941bbSAndroid Build Coastguard Worker         }
92*b7c941bbSAndroid Build Coastguard Worker     }
93*b7c941bbSAndroid Build Coastguard Worker 
getPreferredFrameTimelineIndexVsyncCallback94*b7c941bbSAndroid Build Coastguard Worker     size_t getPreferredFrameTimelineIndex() const { return preferredFrameTimelineIndex; }
getTimelineVsyncCallback95*b7c941bbSAndroid Build Coastguard Worker     const std::vector<FrameTime>& getTimeline() const { return timelines; }
96*b7c941bbSAndroid Build Coastguard Worker 
97*b7c941bbSAndroid Build Coastguard Worker private:
98*b7c941bbSAndroid Build Coastguard Worker     JNIEnv* env;
99*b7c941bbSAndroid Build Coastguard Worker     size_t preferredFrameTimelineIndex{std::numeric_limits<size_t>::max()};
100*b7c941bbSAndroid Build Coastguard Worker     std::vector<FrameTime> timelines;
101*b7c941bbSAndroid Build Coastguard Worker };
102*b7c941bbSAndroid Build Coastguard Worker 
vsyncCallback(int64_t frameTimeNanos,void * data)103*b7c941bbSAndroid Build Coastguard Worker static void vsyncCallback(int64_t frameTimeNanos, void* data) {
104*b7c941bbSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> _l(gLock);
105*b7c941bbSAndroid Build Coastguard Worker     ATrace_beginSection("vsyncCallback base");
106*b7c941bbSAndroid Build Coastguard Worker     Callback* cb = static_cast<Callback*>(data);
107*b7c941bbSAndroid Build Coastguard Worker     cb->count++;
108*b7c941bbSAndroid Build Coastguard Worker     cb->frameTime = std::chrono::nanoseconds{frameTimeNanos};
109*b7c941bbSAndroid Build Coastguard Worker     ATrace_endSection();
110*b7c941bbSAndroid Build Coastguard Worker }
111*b7c941bbSAndroid Build Coastguard Worker 
vsyncCallback(const AChoreographerFrameCallbackData * callbackData,void * data)112*b7c941bbSAndroid Build Coastguard Worker static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
113*b7c941bbSAndroid Build Coastguard Worker     ATrace_beginSection("vsyncCallback");
114*b7c941bbSAndroid Build Coastguard Worker     vsyncCallback(AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData), data);
115*b7c941bbSAndroid Build Coastguard Worker 
116*b7c941bbSAndroid Build Coastguard Worker     VsyncCallback* cb = static_cast<VsyncCallback*>(data);
117*b7c941bbSAndroid Build Coastguard Worker     cb->populate(callbackData);
118*b7c941bbSAndroid Build Coastguard Worker     ATrace_endSection();
119*b7c941bbSAndroid Build Coastguard Worker }
120*b7c941bbSAndroid Build Coastguard Worker 
frameCallback64(int64_t frameTimeNanos,void * data)121*b7c941bbSAndroid Build Coastguard Worker static void frameCallback64(int64_t frameTimeNanos, void* data) {
122*b7c941bbSAndroid Build Coastguard Worker     vsyncCallback(frameTimeNanos, data);
123*b7c941bbSAndroid Build Coastguard Worker }
124*b7c941bbSAndroid Build Coastguard Worker 
frameCallback(long frameTimeNanos,void * data)125*b7c941bbSAndroid Build Coastguard Worker static void frameCallback(long frameTimeNanos, void* data) {
126*b7c941bbSAndroid Build Coastguard Worker     vsyncCallback((int64_t)frameTimeNanos, data);
127*b7c941bbSAndroid Build Coastguard Worker }
128*b7c941bbSAndroid Build Coastguard Worker 
now()129*b7c941bbSAndroid Build Coastguard Worker static std::chrono::nanoseconds now() {
130*b7c941bbSAndroid Build Coastguard Worker     return std::chrono::steady_clock::now().time_since_epoch();
131*b7c941bbSAndroid Build Coastguard Worker }
132*b7c941bbSAndroid Build Coastguard Worker 
verifyCallback(JNIEnv * env,const Callback & cb,int expectedCount,std::chrono::nanoseconds startTime,std::chrono::nanoseconds maxTime)133*b7c941bbSAndroid Build Coastguard Worker static void verifyCallback(JNIEnv* env, const Callback& cb, int expectedCount,
134*b7c941bbSAndroid Build Coastguard Worker                            std::chrono::nanoseconds startTime, std::chrono::nanoseconds maxTime) {
135*b7c941bbSAndroid Build Coastguard Worker     std::lock_guard<std::mutex> _l{gLock};
136*b7c941bbSAndroid Build Coastguard Worker     ASSERT(cb.count == expectedCount, "Choreographer failed to invoke '%s' %d times - actual: %d",
137*b7c941bbSAndroid Build Coastguard Worker            cb.name.c_str(), expectedCount, cb.count);
138*b7c941bbSAndroid Build Coastguard Worker     if (maxTime > ZERO) {
139*b7c941bbSAndroid Build Coastguard Worker         ASSERT(cb.frameTime - startTime < maxTime,
140*b7c941bbSAndroid Build Coastguard Worker                "Callback '%s' has incorrect frame time in invocation %d", cb.name.c_str(),
141*b7c941bbSAndroid Build Coastguard Worker                expectedCount);
142*b7c941bbSAndroid Build Coastguard Worker     }
143*b7c941bbSAndroid Build Coastguard Worker }
144