• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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