blob: 539cbaa341c6c086f52edcafd000da4ba6363f83 [file] [log] [blame]
Alec Mouricc445222019-10-22 10:19:17 -07001/*
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
Alec Mouri271de042020-04-27 22:38:19 -070020#include <android-base/thread_annotations.h>
Huihong Luo1b0c49f2022-03-15 19:18:21 -070021#include <android/gui/ISurfaceComposer.h>
Alec Mouri77a53872019-10-28 16:44:36 -070022#include <gui/DisplayEventDispatcher.h>
Orion Hodsone53587b2021-02-02 15:33:33 +000023#include <jni.h>
Alec Mouri271de042020-04-27 22:38:19 -070024#include <private/android/choreographer.h>
Alec Mouricc445222019-10-22 10:19:17 -070025#include <utils/Looper.h>
Alec Mouricc445222019-10-22 10:19:17 -070026#include <utils/Timers.h>
27
Alec Mouri60aee1c2019-10-28 16:18:59 -070028#include <cinttypes>
Alec Mouri271de042020-04-27 22:38:19 -070029#include <mutex>
Alec Mouri60aee1c2019-10-28 16:18:59 -070030#include <optional>
31#include <queue>
32#include <thread>
33
Alec Mouri271de042020-04-27 22:38:19 -070034namespace {
35struct {
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;
Alec Mouricc445222019-10-22 10:19:17 -070045
Alec Mouri271de042020-04-27 22:38:19 -070046// Gets the JNIEnv* for this thread, and performs one-off initialization if we
47// have never retrieved a JNIEnv* pointer before.
48JNIEnv* 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
70inline const char* toString(bool value) {
Alec Mouricc445222019-10-22 10:19:17 -070071 return value ? "true" : "false";
72}
Alec Mouri271de042020-04-27 22:38:19 -070073} // namespace
74
75namespace android {
Rachel Lee18c34372022-01-20 13:57:18 -080076using gui::VsyncEventData;
Alec Mouricc445222019-10-22 10:19:17 -070077
78struct FrameCallback {
79 AChoreographer_frameCallback callback;
80 AChoreographer_frameCallback64 callback64;
Rachel Leef4dc39f2022-02-15 18:30:59 -080081 AChoreographer_vsyncCallback vsyncCallback;
Alec Mouricc445222019-10-22 10:19:17 -070082 void* data;
83 nsecs_t dueTime;
84
85 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
Alec Mouri60aee1c2019-10-28 16:18:59 -070092struct RefreshRateCallback {
93 AChoreographer_refreshRateCallback callback;
94 void* data;
Alec Mouri271de042020-04-27 22:38:19 -070095 bool firstCallbackFired = false;
Alec Mouri60aee1c2019-10-28 16:18:59 -070096};
Alec Mouricc445222019-10-22 10:19:17 -070097
Alec Mouri271de042020-04-27 22:38:19 -070098class Choreographer;
99
Rachel Lee4879d812021-08-25 11:50:11 -0700100/**
101 * Implementation of AChoreographerFrameCallbackData.
102 */
103struct ChoreographerFrameCallbackDataImpl {
Rachel Lee4879d812021-08-25 11:50:11 -0700104 int64_t frameTimeNanos{0};
105
Rachel Leeb9c5a772022-02-04 21:17:37 -0800106 VsyncEventData vsyncEventData;
Rachel Lee4879d812021-08-25 11:50:11 -0700107
108 const Choreographer* choreographer;
109};
110
Alec Mouri271de042020-04-27 22:38:19 -0700111struct {
112 std::mutex lock;
113 std::vector<Choreographer*> ptrs GUARDED_BY(lock);
Rachel Lee103a58a2022-02-22 15:51:05 -0800114 std::map<AVsyncId, int64_t> startTimes GUARDED_BY(lock);
Alec Mouri271de042020-04-27 22:38:19 -0700115 bool registeredToDisplayManager GUARDED_BY(lock) = false;
116
117 std::atomic<nsecs_t> mLastKnownVsync = -1;
118} gChoreographers;
119
Alec Mouricc445222019-10-22 10:19:17 -0700120class Choreographer : public DisplayEventDispatcher, public MessageHandler {
121public:
Alec Mouri271de042020-04-27 22:38:19 -0700122 explicit Choreographer(const sp<Looper>& looper) EXCLUDES(gChoreographers.lock);
Alec Mouricc445222019-10-22 10:19:17 -0700123 void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
Rachel Lee4879d812021-08-25 11:50:11 -0700124 AChoreographer_frameCallback64 cb64,
Rachel Leef4dc39f2022-02-15 18:30:59 -0800125 AChoreographer_vsyncCallback vsyncCallback, void* data,
Rachel Lee4879d812021-08-25 11:50:11 -0700126 nsecs_t delay);
Alec Mouri271de042020-04-27 22:38:19 -0700127 void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
128 EXCLUDES(gChoreographers.lock);
Alec Mouri33682e92020-01-10 15:11:15 -0800129 void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
Alec Mouri271de042020-04-27 22:38:19 -0700130 // 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();
Alec Mouricc445222019-10-22 10:19:17 -0700136
137 enum {
138 MSG_SCHEDULE_CALLBACKS = 0,
Alec Mouri271de042020-04-27 22:38:19 -0700139 MSG_SCHEDULE_VSYNC = 1,
140 MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
Alec Mouricc445222019-10-22 10:19:17 -0700141 };
142 virtual void handleMessage(const Message& message) override;
143
144 static Choreographer* getForThread();
Alec Mouri271de042020-04-27 22:38:19 -0700145 virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
Jorim Jaggic0086af2021-02-12 18:18:11 +0100146 int64_t getFrameInterval() const;
Rachel Lee4879d812021-08-25 11:50:11 -0700147 bool inCallback() const;
Alec Mouricc445222019-10-22 10:19:17 -0700148
149private:
Alec Mouricc445222019-10-22 10:19:17 -0700150 Choreographer(const Choreographer&) = delete;
151
Ady Abraham74e17562020-08-24 18:18:19 -0700152 void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
Ady Abraham0d28d762020-10-05 17:50:41 -0700153 VsyncEventData vsyncEventData) override;
Alec Mouricc445222019-10-22 10:19:17 -0700154 void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100155 void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
156 nsecs_t vsyncPeriod) override;
Alec Mouri967d5d72020-08-05 12:50:03 -0700157 void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
Ady Abraham62f216c2020-10-13 19:07:23 -0700158 void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
159 std::vector<FrameRateOverride> overrides) override;
Alec Mouricc445222019-10-22 10:19:17 -0700160
161 void scheduleCallbacks();
162
Rachel Lee4879d812021-08-25 11:50:11 -0700163 ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
Rachel Lee103a58a2022-02-22 15:51:05 -0800164 void registerStartTime() const;
Rachel Lee4879d812021-08-25 11:50:11 -0700165
Alec Mouri271de042020-04-27 22:38:19 -0700166 std::mutex mLock;
Alec Mouricc445222019-10-22 10:19:17 -0700167 // Protected by mLock
Alec Mouri60aee1c2019-10-28 16:18:59 -0700168 std::priority_queue<FrameCallback> mFrameCallbacks;
Alec Mouri60aee1c2019-10-28 16:18:59 -0700169 std::vector<RefreshRateCallback> mRefreshRateCallbacks;
Alec Mouricc445222019-10-22 10:19:17 -0700170
Alec Mouri271de042020-04-27 22:38:19 -0700171 nsecs_t mLatestVsyncPeriod = -1;
Ady Abraham0d28d762020-10-05 17:50:41 -0700172 VsyncEventData mLastVsyncEventData;
Rachel Lee4879d812021-08-25 11:50:11 -0700173 bool mInCallback = false;
Alec Mouricc445222019-10-22 10:19:17 -0700174
175 const sp<Looper> mLooper;
176 const std::thread::id mThreadId;
Rachel Lee103a58a2022-02-22 15:51:05 -0800177
178 // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
179 static constexpr size_t kMaxStartTimes = 250;
Alec Mouricc445222019-10-22 10:19:17 -0700180};
181
Alec Mouricc445222019-10-22 10:19:17 -0700182static thread_local Choreographer* gChoreographer;
183Choreographer* 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
Alec Mouri60aee1c2019-10-28 16:18:59 -0700200Choreographer::Choreographer(const sp<Looper>& looper)
Huihong Luo1b0c49f2022-03-15 19:18:21 -0700201 : DisplayEventDispatcher(looper, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp),
Alec Mouri60aee1c2019-10-28 16:18:59 -0700202 mLooper(looper),
Alec Mouri271de042020-04-27 22:38:19 -0700203 mThreadId(std::this_thread::get_id()) {
204 std::lock_guard<std::mutex> _l(gChoreographers.lock);
205 gChoreographers.ptrs.push_back(this);
206}
207
208Choreographer::~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) {
Ady Abraham6a8986b2021-08-18 13:44:14 -0700217 gChoreographers.registeredToDisplayManager = false;
Alec Mouri271de042020-04-27 22:38:19 -0700218 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}
Alec Mouricc445222019-10-22 10:19:17 -0700235
Rachel Lee4879d812021-08-25 11:50:11 -0700236void Choreographer::postFrameCallbackDelayed(AChoreographer_frameCallback cb,
237 AChoreographer_frameCallback64 cb64,
Rachel Leef4dc39f2022-02-15 18:30:59 -0800238 AChoreographer_vsyncCallback vsyncCallback, void* data,
239 nsecs_t delay) {
Alec Mouricc445222019-10-22 10:19:17 -0700240 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Rachel Leef4dc39f2022-02-15 18:30:59 -0800241 FrameCallback callback{cb, cb64, vsyncCallback, data, now + delay};
Alec Mouricc445222019-10-22 10:19:17 -0700242 {
Alec Mouri271de042020-04-27 22:38:19 -0700243 std::lock_guard<std::mutex> _l{mLock};
Alec Mouri60aee1c2019-10-28 16:18:59 -0700244 mFrameCallbacks.push(callback);
Alec Mouricc445222019-10-22 10:19:17 -0700245 }
246 if (callback.dueTime <= now) {
247 if (std::this_thread::get_id() != mThreadId) {
Alec Mouri50a931d2019-11-19 16:23:59 -0800248 if (mLooper != nullptr) {
249 Message m{MSG_SCHEDULE_VSYNC};
250 mLooper->sendMessage(this, m);
251 } else {
252 scheduleVsync();
253 }
Alec Mouricc445222019-10-22 10:19:17 -0700254 } else {
255 scheduleVsync();
256 }
257 } else {
Alec Mouri50a931d2019-11-19 16:23:59 -0800258 if (mLooper != nullptr) {
259 Message m{MSG_SCHEDULE_CALLBACKS};
260 mLooper->sendMessageDelayed(delay, this, m);
261 } else {
262 scheduleCallbacks();
263 }
Alec Mouricc445222019-10-22 10:19:17 -0700264 }
265}
266
Alec Mouri60aee1c2019-10-28 16:18:59 -0700267void Choreographer::registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data) {
Alec Mouri271de042020-04-27 22:38:19 -0700268 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;
Alec Mouri60aee1c2019-10-28 16:18:59 -0700278 {
Alec Mouri271de042020-04-27 22:38:19 -0700279 std::lock_guard<std::mutex> _l2(gChoreographers.lock);
280 needsRegistration = !gChoreographers.registeredToDisplayManager;
281 }
282 if (needsRegistration) {
283 JNIEnv* env = getJniEnv();
Alec Mouri271de042020-04-27 22:38:19 -0700284 if (env == nullptr) {
Greg Kaiserb66d04b2020-05-11 06:52:15 -0700285 ALOGW("JNI environment is unavailable, skipping registration");
Alec Mouri271de042020-04-27 22:38:19 -0700286 return;
287 }
Greg Kaiserb66d04b2020-05-11 06:52:15 -0700288 jobject dmg = env->CallStaticObjectMethod(gJni.displayManagerGlobal.clazz,
289 gJni.displayManagerGlobal.getInstance);
Alec Mouri271de042020-04-27 22:38:19 -0700290 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;
Alec Mouri33682e92020-01-10 15:11:15 -0800302 }
303 }
Alec Mouri271de042020-04-27 22:38:19 -0700304 } else {
305 scheduleLatestConfigRequest();
Alec Mouri60aee1c2019-10-28 16:18:59 -0700306 }
307}
308
Alec Mouri33682e92020-01-10 15:11:15 -0800309void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb,
310 void* data) {
Alec Mouri271de042020-04-27 22:38:19 -0700311 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
321void 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
Alec Mouri967d5d72020-08-05 12:50:03 -0700328 // 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;
Dominik Laskowskif1833852021-03-23 15:06:50 -0700333 event.header =
334 DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL,
335 PhysicalDisplayId::fromPort(0), systemTime()};
Alec Mouri967d5d72020-08-05 12:50:03 -0700336 injectEvent(event);
Alec Mouri60aee1c2019-10-28 16:18:59 -0700337 }
338}
339
Alec Mouricc445222019-10-22 10:19:17 -0700340void Choreographer::scheduleCallbacks() {
Alec Mouri134266b2020-03-03 19:22:29 -0800341 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
342 nsecs_t dueTime;
343 {
Alec Mouri271de042020-04-27 22:38:19 -0700344 std::lock_guard<std::mutex> _l{mLock};
Alec Mouri134266b2020-03-03 19:22:29 -0800345 // 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) {
Alec Mouricc445222019-10-22 10:19:17 -0700353 ALOGV("choreographer %p ~ scheduling vsync", this);
354 scheduleVsync();
355 return;
356 }
357}
358
Alec Mouri271de042020-04-27 22:38:19 -0700359void 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
Alec Mouricc445222019-10-22 10:19:17 -0700381// 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.
Ady Abraham0d28d762020-10-05 17:50:41 -0700384void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t,
385 VsyncEventData vsyncEventData) {
Alec Mouricc445222019-10-22 10:19:17 -0700386 std::vector<FrameCallback> callbacks{};
387 {
Alec Mouri271de042020-04-27 22:38:19 -0700388 std::lock_guard<std::mutex> _l{mLock};
Alec Mouricc445222019-10-22 10:19:17 -0700389 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Alec Mouri60aee1c2019-10-28 16:18:59 -0700390 while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) {
391 callbacks.push_back(mFrameCallbacks.top());
392 mFrameCallbacks.pop();
Alec Mouricc445222019-10-22 10:19:17 -0700393 }
394 }
Ady Abraham0d28d762020-10-05 17:50:41 -0700395 mLastVsyncEventData = vsyncEventData;
Alec Mouricc445222019-10-22 10:19:17 -0700396 for (const auto& cb : callbacks) {
Rachel Leef4dc39f2022-02-15 18:30:59 -0800397 if (cb.vsyncCallback != nullptr) {
Rachel Lee4879d812021-08-25 11:50:11 -0700398 const ChoreographerFrameCallbackDataImpl frameCallbackData =
399 createFrameCallbackData(timestamp);
Rachel Lee103a58a2022-02-22 15:51:05 -0800400 registerStartTime();
Rachel Lee4879d812021-08-25 11:50:11 -0700401 mInCallback = true;
Rachel Leef4dc39f2022-02-15 18:30:59 -0800402 cb.vsyncCallback(reinterpret_cast<const AChoreographerFrameCallbackData*>(
403 &frameCallbackData),
404 cb.data);
Rachel Lee4879d812021-08-25 11:50:11 -0700405 mInCallback = false;
406 } else if (cb.callback64 != nullptr) {
Alec Mouricc445222019-10-22 10:19:17 -0700407 cb.callback64(timestamp, cb.data);
408 } else if (cb.callback != nullptr) {
409 cb.callback(timestamp, cb.data);
410 }
411 }
412}
413
414void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) {
Rachel Lee4879d812021-08-25 11:50:11 -0700415 ALOGV("choreographer %p ~ received hotplug event (displayId=%s, connected=%s), ignoring.", this,
416 to_string(displayId).c_str(), toString(connected));
Alec Mouricc445222019-10-22 10:19:17 -0700417}
418
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100419void Choreographer::dispatchModeChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
420 LOG_ALWAYS_FATAL("dispatchModeChanged was called but was never registered");
Ady Abraham62f216c2020-10-13 19:07:23 -0700421}
422
423void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId,
424 std::vector<FrameRateOverride>) {
425 LOG_ALWAYS_FATAL("dispatchFrameRateOverrides was called but was never registered");
Alec Mouri967d5d72020-08-05 12:50:03 -0700426}
Alec Mouri271de042020-04-27 22:38:19 -0700427
Alec Mouri967d5d72020-08-05 12:50:03 -0700428void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) {
429 ALOGV("choreographer %p ~ received null event.", this);
430 handleRefreshRateUpdates();
Alec Mouricc445222019-10-22 10:19:17 -0700431}
432
433void Choreographer::handleMessage(const Message& message) {
434 switch (message.what) {
Rachel Lee4879d812021-08-25 11:50:11 -0700435 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;
Alec Mouricc445222019-10-22 10:19:17 -0700444 }
445}
446
Jorim Jaggic0086af2021-02-12 18:18:11 +0100447int64_t Choreographer::getFrameInterval() const {
448 return mLastVsyncEventData.frameInterval;
449}
450
Rachel Lee4879d812021-08-25 11:50:11 -0700451bool Choreographer::inCallback() const {
452 return mInCallback;
453}
454
455ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) const {
Rachel Lee4879d812021-08-25 11:50:11 -0700456 return {.frameTimeNanos = timestamp,
Rachel Leeb9c5a772022-02-04 21:17:37 -0800457 .vsyncEventData = mLastVsyncEventData,
Rachel Lee4879d812021-08-25 11:50:11 -0700458 .choreographer = this};
459}
460
Rachel Lee103a58a2022-02-22 15:51:05 -0800461void 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
Alec Mouri271de042020-04-27 22:38:19 -0700471} // namespace android
Alec Mouri50a931d2019-11-19 16:23:59 -0800472using namespace android;
Alec Mouricc445222019-10-22 10:19:17 -0700473
474static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
475 return reinterpret_cast<Choreographer*>(choreographer);
476}
477
Ady Abraham74e17562020-08-24 18:18:19 -0700478static inline const Choreographer* AChoreographer_to_Choreographer(
479 const AChoreographer* choreographer) {
480 return reinterpret_cast<const Choreographer*>(choreographer);
481}
482
Rachel Lee4879d812021-08-25 11:50:11 -0700483static inline const ChoreographerFrameCallbackDataImpl*
484AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(
485 const AChoreographerFrameCallbackData* data) {
486 return reinterpret_cast<const ChoreographerFrameCallbackDataImpl*>(data);
487}
488
Alec Mouri271de042020-04-27 22:38:19 -0700489// Glue for private C api
490namespace android {
491void 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
499void 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
514AChoreographer* AChoreographer_routeGetInstance() {
515 return AChoreographer_getInstance();
516}
517void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
518 AChoreographer_frameCallback callback, void* data) {
Jiyong Park8cdf0762020-08-13 20:21:57 +0900519#pragma clang diagnostic push
520#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Alec Mouri271de042020-04-27 22:38:19 -0700521 return AChoreographer_postFrameCallback(choreographer, callback, data);
Jiyong Park8cdf0762020-08-13 20:21:57 +0900522#pragma clang diagnostic pop
Alec Mouri271de042020-04-27 22:38:19 -0700523}
524void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
525 AChoreographer_frameCallback callback, void* data,
526 long delayMillis) {
Jiyong Park8cdf0762020-08-13 20:21:57 +0900527#pragma clang diagnostic push
528#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Alec Mouri271de042020-04-27 22:38:19 -0700529 return AChoreographer_postFrameCallbackDelayed(choreographer, callback, data, delayMillis);
Jiyong Park8cdf0762020-08-13 20:21:57 +0900530#pragma clang diagnostic pop
Alec Mouri271de042020-04-27 22:38:19 -0700531}
532void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
533 AChoreographer_frameCallback64 callback, void* data) {
534 return AChoreographer_postFrameCallback64(choreographer, callback, data);
535}
536void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
537 AChoreographer_frameCallback64 callback,
538 void* data, uint32_t delayMillis) {
539 return AChoreographer_postFrameCallbackDelayed64(choreographer, callback, data, delayMillis);
540}
Rachel Leef4dc39f2022-02-15 18:30:59 -0800541void AChoreographer_routePostVsyncCallback(AChoreographer* choreographer,
542 AChoreographer_vsyncCallback callback, void* data) {
543 return AChoreographer_postVsyncCallback(choreographer, callback, data);
Rachel Lee4879d812021-08-25 11:50:11 -0700544}
Alec Mouri271de042020-04-27 22:38:19 -0700545void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
546 AChoreographer_refreshRateCallback callback,
547 void* data) {
548 return AChoreographer_registerRefreshRateCallback(choreographer, callback, data);
549}
550void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
551 AChoreographer_refreshRateCallback callback,
552 void* data) {
553 return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data);
554}
Rachel Lee4879d812021-08-25 11:50:11 -0700555int64_t AChoreographerFrameCallbackData_routeGetFrameTimeNanos(
556 const AChoreographerFrameCallbackData* data) {
557 return AChoreographerFrameCallbackData_getFrameTimeNanos(data);
558}
559size_t AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(
560 const AChoreographerFrameCallbackData* data) {
561 return AChoreographerFrameCallbackData_getFrameTimelinesLength(data);
562}
563size_t AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(
564 const AChoreographerFrameCallbackData* data) {
565 return AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(data);
566}
Rachel Lee1fb2ddc2022-01-12 14:33:07 -0800567AVsyncId AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(
Rachel Lee4879d812021-08-25 11:50:11 -0700568 const AChoreographerFrameCallbackData* data, size_t index) {
569 return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index);
570}
Rachel Leef4dc39f2022-02-15 18:30:59 -0800571int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(
Rachel Lee4879d812021-08-25 11:50:11 -0700572 const AChoreographerFrameCallbackData* data, size_t index) {
Rachel Leef4dc39f2022-02-15 18:30:59 -0800573 return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(data,
574 index);
Rachel Lee4879d812021-08-25 11:50:11 -0700575}
Rachel Lee2825fa22022-01-12 17:35:16 -0800576int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
Rachel Lee4879d812021-08-25 11:50:11 -0700577 const AChoreographerFrameCallbackData* data, size_t index) {
Rachel Lee2825fa22022-01-12 17:35:16 -0800578 return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index);
Rachel Lee4879d812021-08-25 11:50:11 -0700579}
Alec Mouri271de042020-04-27 22:38:19 -0700580
Jorim Jaggic0086af2021-02-12 18:18:11 +0100581int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
582 return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
583}
584
Rachel Lee103a58a2022-02-22 15:51:05 -0800585int64_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
Alec Mouri271de042020-04-27 22:38:19 -0700595} // namespace android
596
597/* Glue for the NDK interface */
598
Alec Mouricc445222019-10-22 10:19:17 -0700599static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) {
600 return reinterpret_cast<AChoreographer*>(choreographer);
601}
602
603AChoreographer* AChoreographer_getInstance() {
604 return Choreographer_to_AChoreographer(Choreographer::getForThread());
605}
606
607void AChoreographer_postFrameCallback(AChoreographer* choreographer,
Rachel Lee4879d812021-08-25 11:50:11 -0700608 AChoreographer_frameCallback callback, void* data) {
609 AChoreographer_to_Choreographer(choreographer)
610 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, 0);
Alec Mouricc445222019-10-22 10:19:17 -0700611}
612void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
Rachel Lee4879d812021-08-25 11:50:11 -0700613 AChoreographer_frameCallback callback, void* data,
614 long delayMillis) {
615 AChoreographer_to_Choreographer(choreographer)
616 ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, ms2ns(delayMillis));
617}
Rachel Leef4dc39f2022-02-15 18:30:59 -0800618void AChoreographer_postVsyncCallback(AChoreographer* choreographer,
619 AChoreographer_vsyncCallback callback, void* data) {
Rachel Lee4879d812021-08-25 11:50:11 -0700620 AChoreographer_to_Choreographer(choreographer)
621 ->postFrameCallbackDelayed(nullptr, nullptr, callback, data, 0);
Alec Mouricc445222019-10-22 10:19:17 -0700622}
623void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
Rachel Lee4879d812021-08-25 11:50:11 -0700624 AChoreographer_frameCallback64 callback, void* data) {
625 AChoreographer_to_Choreographer(choreographer)
626 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, 0);
Alec Mouricc445222019-10-22 10:19:17 -0700627}
628void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
Rachel Lee4879d812021-08-25 11:50:11 -0700629 AChoreographer_frameCallback64 callback, void* data,
630 uint32_t delayMillis) {
631 AChoreographer_to_Choreographer(choreographer)
632 ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, ms2ns(delayMillis));
Alec Mouricc445222019-10-22 10:19:17 -0700633}
Alec Mouri60aee1c2019-10-28 16:18:59 -0700634void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
635 AChoreographer_refreshRateCallback callback,
636 void* data) {
637 AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
638}
639void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
Alec Mouri33682e92020-01-10 15:11:15 -0800640 AChoreographer_refreshRateCallback callback,
641 void* data) {
642 AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
Alec Mouri60aee1c2019-10-28 16:18:59 -0700643}
Alec Mouri50a931d2019-11-19 16:23:59 -0800644
Rachel Lee4879d812021-08-25 11:50:11 -0700645int64_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}
653size_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");
Rachel Leeb9c5a772022-02-04 21:17:37 -0800659 return VsyncEventData::kFrameTimelinesLength;
Rachel Lee4879d812021-08-25 11:50:11 -0700660}
661size_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");
Rachel Leeb9c5a772022-02-04 21:17:37 -0800667 return frameCallbackData->vsyncEventData.preferredFrameTimelineIndex;
Rachel Lee4879d812021-08-25 11:50:11 -0700668}
Rachel Lee1fb2ddc2022-01-12 14:33:07 -0800669AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
Rachel Lee4879d812021-08-25 11:50:11 -0700670 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");
Rachel Leeb9c5a772022-02-04 21:17:37 -0800675 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
676 return frameCallbackData->vsyncEventData.frameTimelines[index].vsyncId;
Rachel Lee4879d812021-08-25 11:50:11 -0700677}
Rachel Leef4dc39f2022-02-15 18:30:59 -0800678int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
Rachel Lee4879d812021-08-25 11:50:11 -0700679 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");
Rachel Leeb9c5a772022-02-04 21:17:37 -0800684 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
685 return frameCallbackData->vsyncEventData.frameTimelines[index].expectedPresentationTime;
Rachel Lee4879d812021-08-25 11:50:11 -0700686}
Rachel Lee2825fa22022-01-12 17:35:16 -0800687int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
Rachel Lee4879d812021-08-25 11:50:11 -0700688 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");
Rachel Leeb9c5a772022-02-04 21:17:37 -0800693 LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesLength, "Index out of bounds");
694 return frameCallbackData->vsyncEventData.frameTimelines[index].deadlineTimestamp;
Rachel Lee4879d812021-08-25 11:50:11 -0700695}
696
Alec Mouri50a931d2019-11-19 16:23:59 -0800697AChoreographer* 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
707void AChoreographer_destroy(AChoreographer* choreographer) {
708 if (choreographer == nullptr) {
709 return;
710 }
711
712 delete AChoreographer_to_Choreographer(choreographer);
713}
714
Alec Mouri921b2772020-02-05 19:03:28 -0800715int AChoreographer_getFd(const AChoreographer* choreographer) {
Alec Mouri50a931d2019-11-19 16:23:59 -0800716 return AChoreographer_to_Choreographer(choreographer)->getFd();
717}
718
719void 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.
Alec Mouri271de042020-04-27 22:38:19 -0700723 Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
724 impl->handleEvent(-1, Looper::EVENT_INPUT, data);
Alec Mouri50a931d2019-11-19 16:23:59 -0800725}