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, CALLBACK_ANIMATION);
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 CALLBACK_ANIMATION);
159 }
AChoreographer_postVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)160 void AChoreographer_postVsyncCallback(AChoreographer* choreographer,
161 AChoreographer_vsyncCallback callback, void* data) {
162 AChoreographer_to_Choreographer(choreographer)
163 ->postFrameCallbackDelayed(nullptr, nullptr, callback, data, 0, CALLBACK_ANIMATION);
164 }
AChoreographer_postFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)165 void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
166 AChoreographer_frameCallback64 callback, void* data) {
167 AChoreographer_to_Choreographer(choreographer)
168 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, 0, CALLBACK_ANIMATION);
169 }
AChoreographer_postFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)170 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
171 AChoreographer_frameCallback64 callback, void* data,
172 uint32_t delayMillis) {
173 AChoreographer_to_Choreographer(choreographer)
174 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, ms2ns(delayMillis),
175 CALLBACK_ANIMATION);
176 }
AChoreographer_registerRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)177 void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
178 AChoreographer_refreshRateCallback callback,
179 void* data) {
180 AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
181 }
AChoreographer_unregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)182 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
183 AChoreographer_refreshRateCallback callback,
184 void* data) {
185 AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
186 }
187
AChoreographerFrameCallbackData_getFrameTimeNanos(const AChoreographerFrameCallbackData * data)188 int64_t AChoreographerFrameCallbackData_getFrameTimeNanos(
189 const AChoreographerFrameCallbackData* data) {
190 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
191 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
192 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
193 "Data is only valid in callback");
194 return frameCallbackData->frameTimeNanos;
195 }
AChoreographerFrameCallbackData_getFrameTimelinesLength(const AChoreographerFrameCallbackData * data)196 size_t AChoreographerFrameCallbackData_getFrameTimelinesLength(
197 const AChoreographerFrameCallbackData* data) {
198 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
199 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
200 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
201 "Data is only valid in callback");
202 return frameCallbackData->vsyncEventData.frameTimelinesLength;
203 }
AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)204 size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
205 const AChoreographerFrameCallbackData* data) {
206 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
207 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
208 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
209 "Data is only valid in callback");
210 return frameCallbackData->vsyncEventData.preferredFrameTimelineIndex;
211 }
AChoreographerFrameCallbackData_getFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)212 AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
213 const AChoreographerFrameCallbackData* data, size_t index) {
214 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
215 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
216 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
217 "Data is only valid in callback");
218 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
219 return frameCallbackData->vsyncEventData.frameTimelines[index].vsyncId;
220 }
AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)221 int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
222 const AChoreographerFrameCallbackData* data, size_t index) {
223 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
224 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
225 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
226 "Data is only valid in callback");
227 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
228 return frameCallbackData->vsyncEventData.frameTimelines[index].expectedPresentationTime;
229 }
AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)230 int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
231 const AChoreographerFrameCallbackData* data, size_t index) {
232 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
233 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
234 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
235 "Data is only valid in callback");
236 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
237 return frameCallbackData->vsyncEventData.frameTimelines[index].deadlineTimestamp;
238 }
239
AChoreographer_create()240 AChoreographer* AChoreographer_create() {
241 Choreographer* choreographer = new Choreographer(nullptr);
242 status_t result = choreographer->initialize();
243 if (result != OK) {
244 ALOGW("Failed to initialize");
245 return nullptr;
246 }
247 return Choreographer_to_AChoreographer(choreographer);
248 }
249
AChoreographer_destroy(AChoreographer * choreographer)250 void AChoreographer_destroy(AChoreographer* choreographer) {
251 if (choreographer == nullptr) {
252 return;
253 }
254
255 delete AChoreographer_to_Choreographer(choreographer);
256 }
257
AChoreographer_getFd(const AChoreographer * choreographer)258 int AChoreographer_getFd(const AChoreographer* choreographer) {
259 return AChoreographer_to_Choreographer(choreographer)->getFd();
260 }
261
AChoreographer_handlePendingEvents(AChoreographer * choreographer,void * data)262 void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
263 // Pass dummy fd and events args to handleEvent, since the underlying
264 // DisplayEventDispatcher doesn't need them outside of validating that a
265 // Looper instance didn't break, but these args circumvent those checks.
266 Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
267 impl->handleEvent(-1, Looper::EVENT_INPUT, data);
268 }
269