1 /*
2 * Copyright (C) 2015 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 #include <android-base/thread_annotations.h>
18 #include <android/gui/ISurfaceComposer.h>
19 #include <gui/Choreographer.h>
20 #include <jni.h>
21 #include <private/android/choreographer.h>
22 #include <utils/Looper.h>
23 #include <utils/Timers.h>
24
25 #include <cinttypes>
26 #include <mutex>
27 #include <optional>
28 #include <queue>
29 #include <thread>
30
31 #undef LOG_TAG
32 #define LOG_TAG "AChoreographer"
33
34 using namespace android;
35
AChoreographer_to_Choreographer(AChoreographer * choreographer)36 static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
37 return reinterpret_cast<Choreographer*>(choreographer);
38 }
39
AChoreographer_to_Choreographer(const AChoreographer * choreographer)40 static inline const Choreographer* AChoreographer_to_Choreographer(
41 const AChoreographer* choreographer) {
42 return reinterpret_cast<const Choreographer*>(choreographer);
43 }
44
45 static inline const ChoreographerFrameCallbackDataImpl*
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(const AChoreographerFrameCallbackData * data)46 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(
47 const AChoreographerFrameCallbackData* data) {
48 return reinterpret_cast<const ChoreographerFrameCallbackDataImpl*>(data);
49 }
50
51 // Glue for private C api
52 namespace android {
AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod)53 void AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod) {
54 Choreographer::signalRefreshRateCallbacks(vsyncPeriod);
55 }
56
AChoreographer_initJVM(JNIEnv * env)57 void AChoreographer_initJVM(JNIEnv* env) {
58 Choreographer::initJVM(env);
59 }
60
AChoreographer_routeGetInstance()61 AChoreographer* AChoreographer_routeGetInstance() {
62 return AChoreographer_getInstance();
63 }
AChoreographer_routePostFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)64 void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
65 AChoreographer_frameCallback callback, void* data) {
66 #pragma clang diagnostic push
67 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
68 return AChoreographer_postFrameCallback(choreographer, callback, data);
69 #pragma clang diagnostic pop
70 }
AChoreographer_routePostFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)71 void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
72 AChoreographer_frameCallback callback, void* data,
73 long delayMillis) {
74 #pragma clang diagnostic push
75 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
76 return AChoreographer_postFrameCallbackDelayed(choreographer, callback, data, delayMillis);
77 #pragma clang diagnostic pop
78 }
AChoreographer_routePostFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)79 void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
80 AChoreographer_frameCallback64 callback, void* data) {
81 return AChoreographer_postFrameCallback64(choreographer, callback, data);
82 }
AChoreographer_routePostFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)83 void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
84 AChoreographer_frameCallback64 callback,
85 void* data, uint32_t delayMillis) {
86 return AChoreographer_postFrameCallbackDelayed64(choreographer, callback, data, delayMillis);
87 }
AChoreographer_routePostVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)88 void AChoreographer_routePostVsyncCallback(AChoreographer* choreographer,
89 AChoreographer_vsyncCallback callback, void* data) {
90 return AChoreographer_postVsyncCallback(choreographer, callback, data);
91 }
AChoreographer_routeRegisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)92 void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
93 AChoreographer_refreshRateCallback callback,
94 void* data) {
95 return AChoreographer_registerRefreshRateCallback(choreographer, callback, data);
96 }
AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)97 void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
98 AChoreographer_refreshRateCallback callback,
99 void* data) {
100 return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data);
101 }
AChoreographerFrameCallbackData_routeGetFrameTimeNanos(const AChoreographerFrameCallbackData * data)102 int64_t AChoreographerFrameCallbackData_routeGetFrameTimeNanos(
103 const AChoreographerFrameCallbackData* data) {
104 return AChoreographerFrameCallbackData_getFrameTimeNanos(data);
105 }
AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(const AChoreographerFrameCallbackData * data)106 size_t AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(
107 const AChoreographerFrameCallbackData* data) {
108 return AChoreographerFrameCallbackData_getFrameTimelinesLength(data);
109 }
AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)110 size_t AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(
111 const AChoreographerFrameCallbackData* data) {
112 return AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(data);
113 }
AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)114 AVsyncId AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(
115 const AChoreographerFrameCallbackData* data, size_t index) {
116 return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index);
117 }
AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)118 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(
119 const AChoreographerFrameCallbackData* data, size_t index) {
120 return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(data,
121 index);
122 }
AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)123 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
124 const AChoreographerFrameCallbackData* data, size_t index) {
125 return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index);
126 }
127
AChoreographer_getFrameInterval(const AChoreographer * choreographer)128 int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
129 return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
130 }
131
AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId)132 int64_t AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId) {
133 return Choreographer::getStartTimeNanosForVsyncId(vsyncId);
134 }
135
136 } // namespace android
137
138 /* Glue for the NDK interface */
139
Choreographer_to_AChoreographer(Choreographer * choreographer)140 static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) {
141 return reinterpret_cast<AChoreographer*>(choreographer);
142 }
143
AChoreographer_getInstance()144 AChoreographer* AChoreographer_getInstance() {
145 return Choreographer_to_AChoreographer(Choreographer::getForThread());
146 }
147
AChoreographer_postFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)148 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
149 AChoreographer_frameCallback callback, void* data) {
150 AChoreographer_to_Choreographer(choreographer)
151 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, 0);
152 }
AChoreographer_postFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)153 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
154 AChoreographer_frameCallback callback, void* data,
155 long delayMillis) {
156 AChoreographer_to_Choreographer(choreographer)
157 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, ms2ns(delayMillis));
158 }
AChoreographer_postVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)159 void AChoreographer_postVsyncCallback(AChoreographer* choreographer,
160 AChoreographer_vsyncCallback callback, void* data) {
161 AChoreographer_to_Choreographer(choreographer)
162 ->postFrameCallbackDelayed(nullptr, nullptr, callback, data, 0);
163 }
AChoreographer_postFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)164 void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
165 AChoreographer_frameCallback64 callback, void* data) {
166 AChoreographer_to_Choreographer(choreographer)
167 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, 0);
168 }
AChoreographer_postFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)169 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
170 AChoreographer_frameCallback64 callback, void* data,
171 uint32_t delayMillis) {
172 AChoreographer_to_Choreographer(choreographer)
173 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, ms2ns(delayMillis));
174 }
AChoreographer_registerRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)175 void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
176 AChoreographer_refreshRateCallback callback,
177 void* data) {
178 AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
179 }
AChoreographer_unregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)180 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
181 AChoreographer_refreshRateCallback callback,
182 void* data) {
183 AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
184 }
185
AChoreographerFrameCallbackData_getFrameTimeNanos(const AChoreographerFrameCallbackData * data)186 int64_t AChoreographerFrameCallbackData_getFrameTimeNanos(
187 const AChoreographerFrameCallbackData* data) {
188 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
189 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
190 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
191 "Data is only valid in callback");
192 return frameCallbackData->frameTimeNanos;
193 }
AChoreographerFrameCallbackData_getFrameTimelinesLength(const AChoreographerFrameCallbackData * data)194 size_t AChoreographerFrameCallbackData_getFrameTimelinesLength(
195 const AChoreographerFrameCallbackData* data) {
196 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
197 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
198 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
199 "Data is only valid in callback");
200 return frameCallbackData->vsyncEventData.frameTimelinesLength;
201 }
AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)202 size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
203 const AChoreographerFrameCallbackData* data) {
204 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
205 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
206 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
207 "Data is only valid in callback");
208 return frameCallbackData->vsyncEventData.preferredFrameTimelineIndex;
209 }
AChoreographerFrameCallbackData_getFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)210 AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
211 const AChoreographerFrameCallbackData* data, size_t index) {
212 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
213 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
214 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
215 "Data is only valid in callback");
216 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
217 return frameCallbackData->vsyncEventData.frameTimelines[index].vsyncId;
218 }
AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)219 int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
220 const AChoreographerFrameCallbackData* data, size_t index) {
221 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
222 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
223 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
224 "Data is only valid in callback");
225 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
226 return frameCallbackData->vsyncEventData.frameTimelines[index].expectedPresentationTime;
227 }
AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)228 int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
229 const AChoreographerFrameCallbackData* data, size_t index) {
230 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
231 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
232 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
233 "Data is only valid in callback");
234 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
235 return frameCallbackData->vsyncEventData.frameTimelines[index].deadlineTimestamp;
236 }
237
AChoreographer_create()238 AChoreographer* AChoreographer_create() {
239 Choreographer* choreographer = new Choreographer(nullptr);
240 status_t result = choreographer->initialize();
241 if (result != OK) {
242 ALOGW("Failed to initialize");
243 return nullptr;
244 }
245 return Choreographer_to_AChoreographer(choreographer);
246 }
247
AChoreographer_destroy(AChoreographer * choreographer)248 void AChoreographer_destroy(AChoreographer* choreographer) {
249 if (choreographer == nullptr) {
250 return;
251 }
252
253 delete AChoreographer_to_Choreographer(choreographer);
254 }
255
AChoreographer_getFd(const AChoreographer * choreographer)256 int AChoreographer_getFd(const AChoreographer* choreographer) {
257 return AChoreographer_to_Choreographer(choreographer)->getFd();
258 }
259
AChoreographer_handlePendingEvents(AChoreographer * choreographer,void * data)260 void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
261 // Pass dummy fd and events args to handleEvent, since the underlying
262 // DisplayEventDispatcher doesn't need them outside of validating that a
263 // Looper instance didn't break, but these args circumvent those checks.
264 Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
265 impl->handleEvent(-1, Looper::EVENT_INPUT, data);
266 }
267