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 #define LOG_TAG "Choreographer"
18 //#define LOG_NDEBUG 0
19
20 #include <android-base/thread_annotations.h>
21 #include <gui/DisplayEventDispatcher.h>
22 #include <gui/ISurfaceComposer.h>
23 #include <jni.h>
24 #include <private/android/choreographer.h>
25 #include <utils/Looper.h>
26 #include <utils/Timers.h>
27
28 #include <cinttypes>
29 #include <mutex>
30 #include <optional>
31 #include <queue>
32 #include <thread>
33
34 namespace {
35 struct {
36 // Global JVM that is provided by zygote
37 JavaVM* jvm = nullptr;
38 struct {
39 jclass clazz;
40 jmethodID getInstance;
41 jmethodID registerNativeChoreographerForRefreshRateCallbacks;
42 jmethodID unregisterNativeChoreographerForRefreshRateCallbacks;
43 } displayManagerGlobal;
44 } gJni;
45
46 // Gets the JNIEnv* for this thread, and performs one-off initialization if we
47 // have never retrieved a JNIEnv* pointer before.
getJniEnv()48 JNIEnv* getJniEnv() {
49 if (gJni.jvm == nullptr) {
50 ALOGW("AChoreographer: No JVM provided!");
51 return nullptr;
52 }
53
54 JNIEnv* env = nullptr;
55 if (gJni.jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
56 ALOGD("Attaching thread to JVM for AChoreographer");
57 JavaVMAttachArgs args = {JNI_VERSION_1_4, "AChoreographer_env", NULL};
58 jint attachResult = gJni.jvm->AttachCurrentThreadAsDaemon(&env, (void*)&args);
59 if (attachResult != JNI_OK) {
60 ALOGE("Unable to attach thread. Error: %d", attachResult);
61 return nullptr;
62 }
63 }
64 if (env == nullptr) {
65 ALOGW("AChoreographer: No JNI env available!");
66 }
67 return env;
68 }
69
toString(bool value)70 inline const char* toString(bool value) {
71 return value ? "true" : "false";
72 }
73 } // namespace
74
75 namespace android {
76 using gui::VsyncEventData;
77
78 struct FrameCallback {
79 AChoreographer_frameCallback callback;
80 AChoreographer_frameCallback64 callback64;
81 AChoreographer_vsyncCallback vsyncCallback;
82 void* data;
83 nsecs_t dueTime;
84
operator <android::FrameCallback85 inline bool operator<(const FrameCallback& rhs) const {
86 // Note that this is intentionally flipped because we want callbacks due sooner to be at
87 // the head of the queue
88 return dueTime > rhs.dueTime;
89 }
90 };
91
92 struct RefreshRateCallback {
93 AChoreographer_refreshRateCallback callback;
94 void* data;
95 bool firstCallbackFired = false;
96 };
97
98 class Choreographer;
99
100 /**
101 * Implementation of AChoreographerFrameCallbackData.
102 */
103 struct ChoreographerFrameCallbackDataImpl {
104 int64_t frameTimeNanos{0};
105
106 VsyncEventData vsyncEventData;
107
108 const Choreographer* choreographer;
109 };
110
111 struct {
112 std::mutex lock;
113 std::vector<Choreographer*> ptrs GUARDED_BY(lock);
114 std::map<AVsyncId, int64_t> startTimes GUARDED_BY(lock);
115 bool registeredToDisplayManager GUARDED_BY(lock) = false;
116
117 std::atomic<nsecs_t> mLastKnownVsync = -1;
118 } gChoreographers;
119
120 class Choreographer : public DisplayEventDispatcher, public MessageHandler {
121 public:
122 explicit Choreographer(const sp<Looper>& looper) EXCLUDES(gChoreographers.lock);
123 void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
124 AChoreographer_frameCallback64 cb64,
125 AChoreographer_vsyncCallback vsyncCallback, void* data,
126 nsecs_t delay);
127 void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
128 EXCLUDES(gChoreographers.lock);
129 void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
130 // Drains the queue of pending vsync periods and dispatches refresh rate
131 // updates to callbacks.
132 // The assumption is that this method is only called on a single
133 // processing thread, either by looper or by AChoreographer_handleEvents
134 void handleRefreshRateUpdates();
135 void scheduleLatestConfigRequest();
136
137 enum {
138 MSG_SCHEDULE_CALLBACKS = 0,
139 MSG_SCHEDULE_VSYNC = 1,
140 MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
141 };
142 virtual void handleMessage(const Message& message) override;
143
144 static Choreographer* getForThread();
145 virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
146 int64_t getFrameInterval() const;
147 bool inCallback() const;
148
149 private:
150 Choreographer(const Choreographer&) = delete;
151
152 void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
153 VsyncEventData vsyncEventData) override;
154 void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
155 void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
156 nsecs_t vsyncPeriod) override;
157 void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
158 void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
159 std::vector<FrameRateOverride> overrides) override;
160
161 void scheduleCallbacks();
162
163 ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
164 void registerStartTime() const;
165
166 std::mutex mLock;
167 // Protected by mLock
168 std::priority_queue<FrameCallback> mFrameCallbacks;
169 std::vector<RefreshRateCallback> mRefreshRateCallbacks;
170
171 nsecs_t mLatestVsyncPeriod = -1;
172 VsyncEventData mLastVsyncEventData;
173 bool mInCallback = false;
174
175 const sp<Looper> mLooper;
176 const std::thread::id mThreadId;
177
178 // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
179 static constexpr size_t kMaxStartTimes = 250;
180 };
181
182 static thread_local Choreographer* gChoreographer;
getForThread()183 Choreographer* Choreographer::getForThread() {
184 if (gChoreographer == nullptr) {
185 sp<Looper> looper = Looper::getForThread();
186 if (!looper.get()) {
187 ALOGW("No looper prepared for thread");
188 return nullptr;
189 }
190 gChoreographer = new Choreographer(looper);
191 status_t result = gChoreographer->initialize();
192 if (result != OK) {
193 ALOGW("Failed to initialize");
194 return nullptr;
195 }
196 }
197 return gChoreographer;
198 }
199
Choreographer(const sp<Looper> & looper)200 Choreographer::Choreographer(const sp<Looper>& looper)
201 : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp),
202 mLooper(looper),
203 mThreadId(std::this_thread::get_id()) {
204 std::lock_guard<std::mutex> _l(gChoreographers.lock);
205 gChoreographers.ptrs.push_back(this);
206 }
207
~Choreographer()208 Choreographer::~Choreographer() {
209 std::lock_guard<std::mutex> _l(gChoreographers.lock);
210 gChoreographers.ptrs.erase(std::remove_if(gChoreographers.ptrs.begin(),
211 gChoreographers.ptrs.end(),
212 [=](Choreographer* c) { return c == this; }),
213 gChoreographers.ptrs.end());
214 // Only poke DisplayManagerGlobal to unregister if we previously registered
215 // callbacks.
216 if (gChoreographers.ptrs.empty() && gChoreographers.registeredToDisplayManager) {
217 gChoreographers.registeredToDisplayManager = false;
218 JNIEnv* env = getJniEnv();
219 if (env == nullptr) {
220 ALOGW("JNI environment is unavailable, skipping choreographer cleanup");
221 return;
222 }
223 jobject dmg = env->CallStaticObjectMethod(gJni.displayManagerGlobal.clazz,
224 gJni.displayManagerGlobal.getInstance);
225 if (dmg == nullptr) {
226 ALOGW("DMS is not initialized yet, skipping choreographer cleanup");
227 } else {
228 env->CallVoidMethod(dmg,
229 gJni.displayManagerGlobal
230 .unregisterNativeChoreographerForRefreshRateCallbacks);
231 env->DeleteLocalRef(dmg);
232 }
233 }
234 }
235
postFrameCallbackDelayed(AChoreographer_frameCallback cb,AChoreographer_frameCallback64 cb64,AChoreographer_vsyncCallback vsyncCallback,void * data,nsecs_t delay)236 void Choreographer::postFrameCallbackDelayed(AChoreographer_frameCallback cb,
237 AChoreographer_frameCallback64 cb64,
238 AChoreographer_vsyncCallback vsyncCallback, void* data,
239 nsecs_t delay) {
240 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
241 FrameCallback callback{cb, cb64, vsyncCallback, data, now + delay};
242 {
243 std::lock_guard<std::mutex> _l{mLock};
244 mFrameCallbacks.push(callback);
245 }
246 if (callback.dueTime <= now) {
247 if (std::this_thread::get_id() != mThreadId) {
248 if (mLooper != nullptr) {
249 Message m{MSG_SCHEDULE_VSYNC};
250 mLooper->sendMessage(this, m);
251 } else {
252 scheduleVsync();
253 }
254 } else {
255 scheduleVsync();
256 }
257 } else {
258 if (mLooper != nullptr) {
259 Message m{MSG_SCHEDULE_CALLBACKS};
260 mLooper->sendMessageDelayed(delay, this, m);
261 } else {
262 scheduleCallbacks();
263 }
264 }
265 }
266
registerRefreshRateCallback(AChoreographer_refreshRateCallback cb,void * data)267 void Choreographer::registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) {
268 std::lock_guard<std::mutex> _l{mLock};
269 for (const auto& callback : mRefreshRateCallbacks) {
270 // Don't re-add callbacks.
271 if (cb == callback.callback && data == callback.data) {
272 return;
273 }
274 }
275 mRefreshRateCallbacks.emplace_back(
276 RefreshRateCallback{.callback = cb, .data = data, .firstCallbackFired = false});
277 bool needsRegistration = false;
278 {
279 std::lock_guard<std::mutex> _l2(gChoreographers.lock);
280 needsRegistration = !gChoreographers.registeredToDisplayManager;
281 }
282 if (needsRegistration) {
283 JNIEnv* env = getJniEnv();
284 if (env == nullptr) {
285 ALOGW("JNI environment is unavailable, skipping registration");
286 return;
287 }
288 jobject dmg = env->CallStaticObjectMethod(gJni.displayManagerGlobal.clazz,
289 gJni.displayManagerGlobal.getInstance);
290 if (dmg == nullptr) {
291 ALOGW("DMS is not initialized yet: skipping registration");
292 return;
293 } else {
294 env->CallVoidMethod(dmg,
295 gJni.displayManagerGlobal
296 .registerNativeChoreographerForRefreshRateCallbacks,
297 reinterpret_cast<int64_t>(this));
298 env->DeleteLocalRef(dmg);
299 {
300 std::lock_guard<std::mutex> _l2(gChoreographers.lock);
301 gChoreographers.registeredToDisplayManager = true;
302 }
303 }
304 } else {
305 scheduleLatestConfigRequest();
306 }
307 }
308
unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb,void * data)309 void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb,
310 void* data) {
311 std::lock_guard<std::mutex> _l{mLock};
312 mRefreshRateCallbacks.erase(std::remove_if(mRefreshRateCallbacks.begin(),
313 mRefreshRateCallbacks.end(),
314 [&](const RefreshRateCallback& callback) {
315 return cb == callback.callback &&
316 data == callback.data;
317 }),
318 mRefreshRateCallbacks.end());
319 }
320
scheduleLatestConfigRequest()321 void Choreographer::scheduleLatestConfigRequest() {
322 if (mLooper != nullptr) {
323 Message m{MSG_HANDLE_REFRESH_RATE_UPDATES};
324 mLooper->sendMessage(this, m);
325 } else {
326 // If the looper thread is detached from Choreographer, then refresh rate
327 // changes will be handled in AChoreographer_handlePendingEvents, so we
328 // need to wake up the looper thread by writing to the write-end of the
329 // socket the looper is listening on.
330 // Fortunately, these events are small so sending packets across the
331 // socket should be atomic across processes.
332 DisplayEventReceiver::Event event;
333 event.header =
334 DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL,
335 PhysicalDisplayId::fromPort(0), systemTime()};
336 injectEvent(event);
337 }
338 }
339
scheduleCallbacks()340 void Choreographer::scheduleCallbacks() {
341 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
342 nsecs_t dueTime;
343 {
344 std::lock_guard<std::mutex> _l{mLock};
345 // If there are no pending callbacks then don't schedule a vsync
346 if (mFrameCallbacks.empty()) {
347 return;
348 }
349 dueTime = mFrameCallbacks.top().dueTime;
350 }
351
352 if (dueTime <= now) {
353 ALOGV("choreographer %p ~ scheduling vsync", this);
354 scheduleVsync();
355 return;
356 }
357 }
358
handleRefreshRateUpdates()359 void Choreographer::handleRefreshRateUpdates() {
360 std::vector<RefreshRateCallback> callbacks{};
361 const nsecs_t pendingPeriod = gChoreographers.mLastKnownVsync.load();
362 const nsecs_t lastPeriod = mLatestVsyncPeriod;
363 if (pendingPeriod > 0) {
364 mLatestVsyncPeriod = pendingPeriod;
365 }
366 {
367 std::lock_guard<std::mutex> _l{mLock};
368 for (auto& cb : mRefreshRateCallbacks) {
369 callbacks.push_back(cb);
370 cb.firstCallbackFired = true;
371 }
372 }
373
374 for (auto& cb : callbacks) {
375 if (!cb.firstCallbackFired || (pendingPeriod > 0 && pendingPeriod != lastPeriod)) {
376 cb.callback(pendingPeriod, cb.data);
377 }
378 }
379 }
380
381 // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the
382 // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for
383 // the internal display implicitly.
dispatchVsync(nsecs_t timestamp,PhysicalDisplayId,uint32_t,VsyncEventData vsyncEventData)384 void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t,
385 VsyncEventData vsyncEventData) {
386 std::vector<FrameCallback> callbacks{};
387 {
388 std::lock_guard<std::mutex> _l{mLock};
389 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
390 while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) {
391 callbacks.push_back(mFrameCallbacks.top());
392 mFrameCallbacks.pop();
393 }
394 }
395 mLastVsyncEventData = vsyncEventData;
396 for (const auto& cb : callbacks) {
397 if (cb.vsyncCallback != nullptr) {
398 const ChoreographerFrameCallbackDataImpl frameCallbackData =
399 createFrameCallbackData(timestamp);
400 registerStartTime();
401 mInCallback = true;
402 cb.vsyncCallback(reinterpret_cast<const AChoreographerFrameCallbackData*>(
403 &frameCallbackData),
404 cb.data);
405 mInCallback = false;
406 } else if (cb.callback64 != nullptr) {
407 cb.callback64(timestamp, cb.data);
408 } else if (cb.callback != nullptr) {
409 cb.callback(timestamp, cb.data);
410 }
411 }
412 }
413
dispatchHotplug(nsecs_t,PhysicalDisplayId displayId,bool connected)414 void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) {
415 ALOGV("choreographer %p ~ received hotplug event (displayId=%s, connected=%s), ignoring.", this,
416 to_string(displayId).c_str(), toString(connected));
417 }
418
dispatchModeChanged(nsecs_t,PhysicalDisplayId,int32_t,nsecs_t)419 void Choreographer::dispatchModeChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
420 LOG_ALWAYS_FATAL("dispatchModeChanged was called but was never registered");
421 }
422
dispatchFrameRateOverrides(nsecs_t,PhysicalDisplayId,std::vector<FrameRateOverride>)423 void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId,
424 std::vector<FrameRateOverride>) {
425 LOG_ALWAYS_FATAL("dispatchFrameRateOverrides was called but was never registered");
426 }
427
dispatchNullEvent(nsecs_t,PhysicalDisplayId)428 void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) {
429 ALOGV("choreographer %p ~ received null event.", this);
430 handleRefreshRateUpdates();
431 }
432
handleMessage(const Message & message)433 void Choreographer::handleMessage(const Message& message) {
434 switch (message.what) {
435 case MSG_SCHEDULE_CALLBACKS:
436 scheduleCallbacks();
437 break;
438 case MSG_SCHEDULE_VSYNC:
439 scheduleVsync();
440 break;
441 case MSG_HANDLE_REFRESH_RATE_UPDATES:
442 handleRefreshRateUpdates();
443 break;
444 }
445 }
446
getFrameInterval() const447 int64_t Choreographer::getFrameInterval() const {
448 return mLastVsyncEventData.frameInterval;
449 }
450
inCallback() const451 bool Choreographer::inCallback() const {
452 return mInCallback;
453 }
454
createFrameCallbackData(nsecs_t timestamp) const455 ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) const {
456 return {.frameTimeNanos = timestamp,
457 .vsyncEventData = mLastVsyncEventData,
458 .choreographer = this};
459 }
460
registerStartTime() const461 void Choreographer::registerStartTime() const {
462 std::scoped_lock _l(gChoreographers.lock);
463 for (VsyncEventData::FrameTimeline frameTimeline : mLastVsyncEventData.frameTimelines) {
464 while (gChoreographers.startTimes.size() >= kMaxStartTimes) {
465 gChoreographers.startTimes.erase(gChoreographers.startTimes.begin());
466 }
467 gChoreographers.startTimes[frameTimeline.vsyncId] = systemTime(SYSTEM_TIME_MONOTONIC);
468 }
469 }
470
471 } // namespace android
472 using namespace android;
473
AChoreographer_to_Choreographer(AChoreographer * choreographer)474 static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
475 return reinterpret_cast<Choreographer*>(choreographer);
476 }
477
AChoreographer_to_Choreographer(const AChoreographer * choreographer)478 static inline const Choreographer* AChoreographer_to_Choreographer(
479 const AChoreographer* choreographer) {
480 return reinterpret_cast<const Choreographer*>(choreographer);
481 }
482
483 static inline const ChoreographerFrameCallbackDataImpl*
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(const AChoreographerFrameCallbackData * data)484 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(
485 const AChoreographerFrameCallbackData* data) {
486 return reinterpret_cast<const ChoreographerFrameCallbackDataImpl*>(data);
487 }
488
489 // Glue for private C api
490 namespace android {
AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod)491 void AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock) {
492 std::lock_guard<std::mutex> _l(gChoreographers.lock);
493 gChoreographers.mLastKnownVsync.store(vsyncPeriod);
494 for (auto c : gChoreographers.ptrs) {
495 c->scheduleLatestConfigRequest();
496 }
497 }
498
AChoreographer_initJVM(JNIEnv * env)499 void AChoreographer_initJVM(JNIEnv* env) {
500 env->GetJavaVM(&gJni.jvm);
501 // Now we need to find the java classes.
502 jclass dmgClass = env->FindClass("android/hardware/display/DisplayManagerGlobal");
503 gJni.displayManagerGlobal.clazz = static_cast<jclass>(env->NewGlobalRef(dmgClass));
504 gJni.displayManagerGlobal.getInstance =
505 env->GetStaticMethodID(dmgClass, "getInstance",
506 "()Landroid/hardware/display/DisplayManagerGlobal;");
507 gJni.displayManagerGlobal.registerNativeChoreographerForRefreshRateCallbacks =
508 env->GetMethodID(dmgClass, "registerNativeChoreographerForRefreshRateCallbacks", "()V");
509 gJni.displayManagerGlobal.unregisterNativeChoreographerForRefreshRateCallbacks =
510 env->GetMethodID(dmgClass, "unregisterNativeChoreographerForRefreshRateCallbacks",
511 "()V");
512 }
513
AChoreographer_routeGetInstance()514 AChoreographer* AChoreographer_routeGetInstance() {
515 return AChoreographer_getInstance();
516 }
AChoreographer_routePostFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)517 void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
518 AChoreographer_frameCallback callback, void* data) {
519 #pragma clang diagnostic push
520 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
521 return AChoreographer_postFrameCallback(choreographer, callback, data);
522 #pragma clang diagnostic pop
523 }
AChoreographer_routePostFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)524 void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
525 AChoreographer_frameCallback callback, void* data,
526 long delayMillis) {
527 #pragma clang diagnostic push
528 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
529 return AChoreographer_postFrameCallbackDelayed(choreographer, callback, data, delayMillis);
530 #pragma clang diagnostic pop
531 }
AChoreographer_routePostFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)532 void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
533 AChoreographer_frameCallback64 callback, void* data) {
534 return AChoreographer_postFrameCallback64(choreographer, callback, data);
535 }
AChoreographer_routePostFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)536 void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
537 AChoreographer_frameCallback64 callback,
538 void* data, uint32_t delayMillis) {
539 return AChoreographer_postFrameCallbackDelayed64(choreographer, callback, data, delayMillis);
540 }
AChoreographer_routePostVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)541 void AChoreographer_routePostVsyncCallback(AChoreographer* choreographer,
542 AChoreographer_vsyncCallback callback, void* data) {
543 return AChoreographer_postVsyncCallback(choreographer, callback, data);
544 }
AChoreographer_routeRegisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)545 void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
546 AChoreographer_refreshRateCallback callback,
547 void* data) {
548 return AChoreographer_registerRefreshRateCallback(choreographer, callback, data);
549 }
AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)550 void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
551 AChoreographer_refreshRateCallback callback,
552 void* data) {
553 return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data);
554 }
AChoreographerFrameCallbackData_routeGetFrameTimeNanos(const AChoreographerFrameCallbackData * data)555 int64_t AChoreographerFrameCallbackData_routeGetFrameTimeNanos(
556 const AChoreographerFrameCallbackData* data) {
557 return AChoreographerFrameCallbackData_getFrameTimeNanos(data);
558 }
AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(const AChoreographerFrameCallbackData * data)559 size_t AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(
560 const AChoreographerFrameCallbackData* data) {
561 return AChoreographerFrameCallbackData_getFrameTimelinesLength(data);
562 }
AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)563 size_t AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(
564 const AChoreographerFrameCallbackData* data) {
565 return AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(data);
566 }
AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)567 AVsyncId AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(
568 const AChoreographerFrameCallbackData* data, size_t index) {
569 return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index);
570 }
AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)571 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(
572 const AChoreographerFrameCallbackData* data, size_t index) {
573 return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(data,
574 index);
575 }
AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)576 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
577 const AChoreographerFrameCallbackData* data, size_t index) {
578 return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index);
579 }
580
AChoreographer_getFrameInterval(const AChoreographer * choreographer)581 int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
582 return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
583 }
584
AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId)585 int64_t AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId) {
586 std::scoped_lock _l(gChoreographers.lock);
587 const auto iter = gChoreographers.startTimes.find(vsyncId);
588 if (iter == gChoreographers.startTimes.end()) {
589 ALOGW("Start time was not found for vsync id: %" PRId64, vsyncId);
590 return 0;
591 }
592 return iter->second;
593 }
594
595 } // namespace android
596
597 /* Glue for the NDK interface */
598
Choreographer_to_AChoreographer(Choreographer * choreographer)599 static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) {
600 return reinterpret_cast<AChoreographer*>(choreographer);
601 }
602
AChoreographer_getInstance()603 AChoreographer* AChoreographer_getInstance() {
604 return Choreographer_to_AChoreographer(Choreographer::getForThread());
605 }
606
AChoreographer_postFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)607 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
608 AChoreographer_frameCallback callback, void* data) {
609 AChoreographer_to_Choreographer(choreographer)
610 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, 0);
611 }
AChoreographer_postFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)612 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
613 AChoreographer_frameCallback callback, void* data,
614 long delayMillis) {
615 AChoreographer_to_Choreographer(choreographer)
616 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, ms2ns(delayMillis));
617 }
AChoreographer_postVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)618 void AChoreographer_postVsyncCallback(AChoreographer* choreographer,
619 AChoreographer_vsyncCallback callback, void* data) {
620 AChoreographer_to_Choreographer(choreographer)
621 ->postFrameCallbackDelayed(nullptr, nullptr, callback, data, 0);
622 }
AChoreographer_postFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)623 void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
624 AChoreographer_frameCallback64 callback, void* data) {
625 AChoreographer_to_Choreographer(choreographer)
626 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, 0);
627 }
AChoreographer_postFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)628 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
629 AChoreographer_frameCallback64 callback, void* data,
630 uint32_t delayMillis) {
631 AChoreographer_to_Choreographer(choreographer)
632 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, ms2ns(delayMillis));
633 }
AChoreographer_registerRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)634 void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
635 AChoreographer_refreshRateCallback callback,
636 void* data) {
637 AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
638 }
AChoreographer_unregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)639 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
640 AChoreographer_refreshRateCallback callback,
641 void* data) {
642 AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
643 }
644
AChoreographerFrameCallbackData_getFrameTimeNanos(const AChoreographerFrameCallbackData * data)645 int64_t AChoreographerFrameCallbackData_getFrameTimeNanos(
646 const AChoreographerFrameCallbackData* data) {
647 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
648 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
649 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
650 "Data is only valid in callback");
651 return frameCallbackData->frameTimeNanos;
652 }
AChoreographerFrameCallbackData_getFrameTimelinesLength(const AChoreographerFrameCallbackData * data)653 size_t AChoreographerFrameCallbackData_getFrameTimelinesLength(
654 const AChoreographerFrameCallbackData* data) {
655 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
656 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
657 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
658 "Data is only valid in callback");
659 return VsyncEventData::kFrameTimelinesLength;
660 }
AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)661 size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
662 const AChoreographerFrameCallbackData* data) {
663 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
664 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
665 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
666 "Data is only valid in callback");
667 return frameCallbackData->vsyncEventData.preferredFrameTimelineIndex;
668 }
AChoreographerFrameCallbackData_getFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)669 AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
670 const AChoreographerFrameCallbackData* data, size_t index) {
671 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
672 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
673 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
674 "Data is only valid in callback");
675 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
676 return frameCallbackData->vsyncEventData.frameTimelines[index].vsyncId;
677 }
AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)678 int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
679 const AChoreographerFrameCallbackData* data, size_t index) {
680 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
681 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
682 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
683 "Data is only valid in callback");
684 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
685 return frameCallbackData->vsyncEventData.frameTimelines[index].expectedPresentationTime;
686 }
AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)687 int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
688 const AChoreographerFrameCallbackData* data, size_t index) {
689 const ChoreographerFrameCallbackDataImpl* frameCallbackData =
690 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
691 LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
692 "Data is only valid in callback");
693 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
694 return frameCallbackData->vsyncEventData.frameTimelines[index].deadlineTimestamp;
695 }
696
AChoreographer_create()697 AChoreographer* AChoreographer_create() {
698 Choreographer* choreographer = new Choreographer(nullptr);
699 status_t result = choreographer->initialize();
700 if (result != OK) {
701 ALOGW("Failed to initialize");
702 return nullptr;
703 }
704 return Choreographer_to_AChoreographer(choreographer);
705 }
706
AChoreographer_destroy(AChoreographer * choreographer)707 void AChoreographer_destroy(AChoreographer* choreographer) {
708 if (choreographer == nullptr) {
709 return;
710 }
711
712 delete AChoreographer_to_Choreographer(choreographer);
713 }
714
AChoreographer_getFd(const AChoreographer * choreographer)715 int AChoreographer_getFd(const AChoreographer* choreographer) {
716 return AChoreographer_to_Choreographer(choreographer)->getFd();
717 }
718
AChoreographer_handlePendingEvents(AChoreographer * choreographer,void * data)719 void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
720 // Pass dummy fd and events args to handleEvent, since the underlying
721 // DisplayEventDispatcher doesn't need them outside of validating that a
722 // Looper instance didn't break, but these args circumvent those checks.
723 Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
724 impl->handleEvent(-1, Looper::EVENT_INPUT, data);
725 }
726