blob: c4c9fa56ffeb78725a1f1c91bfbd49332a3672fa [file] [log] [blame]
Kevin DuBois305bef12019-10-09 13:23:27 -07001/*
2 * Copyright 2019 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
Dominik Laskowski62eff352021-12-06 09:59:41 -080018
Kevin DuBois305bef12019-10-09 13:23:27 -070019#include <vector>
20
Dominik Laskowski62eff352021-12-06 09:59:41 -080021#include <android-base/stringprintf.h>
22#include <ftl/concat.h>
23#include <utils/Trace.h>
Leon Scroggins III07738132023-04-24 11:43:53 -040024#include <log/log_main.h>
Dominik Laskowski62eff352021-12-06 09:59:41 -080025
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080026#include <scheduler/TimeKeeper.h>
27
Kevin DuBoise4f27a82019-11-12 11:41:41 -080028#include "VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070029#include "VSyncTracker.h"
30
Ady Abraham529bd9f2023-10-05 14:55:30 -070031#include <com_android_graphics_surfaceflinger_flags.h>
32
Leon Scroggins III07738132023-04-24 11:43:53 -040033#undef LOG_TAG
34#define LOG_TAG "VSyncDispatch"
35
Kevin DuBois305bef12019-10-09 13:23:27 -070036namespace android::scheduler {
Ady Abraham529bd9f2023-10-05 14:55:30 -070037using namespace com::android::graphics::surfaceflinger;
Dominik Laskowski62eff352021-12-06 09:59:41 -080038
Ady Abraham5e7371c2020-03-24 14:47:24 -070039using base::StringAppendF;
Kevin DuBois305bef12019-10-09 13:23:27 -070040
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070041namespace {
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080042
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070043nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
44 const VSyncDispatch::ScheduleTiming& timing) {
45 return nextVsyncTime - timing.readyDuration - timing.workDuration;
46}
47
48nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now,
49 const VSyncDispatch::ScheduleTiming& timing) {
50 const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
51 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
52 return getExpectedCallbackTime(nextVsyncTime, timing);
53}
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080054
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070055} // namespace
56
Kevin DuBoise4f27a82019-11-12 11:41:41 -080057VSyncDispatch::~VSyncDispatch() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070058VSyncTracker::~VSyncTracker() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070059
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080060VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string name,
61 VSyncDispatch::Callback callback,
Kevin DuBoisc94ca832019-11-26 12:56:24 -080062 nsecs_t minVsyncDistance)
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080063 : mName(std::move(name)),
64 mCallback(std::move(callback)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -080065 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -070066
Kevin DuBoise4f27a82019-11-12 11:41:41 -080067std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::lastExecutedVsyncTarget() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070068 return mLastDispatchTime;
69}
70
Kevin DuBoise4f27a82019-11-12 11:41:41 -080071std::string_view VSyncDispatchTimerQueueEntry::name() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070072 return mName;
73}
74
Kevin DuBoise4f27a82019-11-12 11:41:41 -080075std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::wakeupTime() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070076 if (!mArmedInfo) {
77 return {};
78 }
79 return {mArmedInfo->mActualWakeupTime};
80}
81
Ady Abraham9c53ee72020-07-22 21:16:18 -070082std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::readyTime() const {
83 if (!mArmedInfo) {
84 return {};
85 }
86 return {mArmedInfo->mActualReadyTime};
87}
88
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -080089std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::targetVsync() const {
90 if (!mArmedInfo) {
91 return {};
92 }
93 return {mArmedInfo->mActualVsyncTime};
94}
95
Ady Abraham9c53ee72020-07-22 21:16:18 -070096ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
Kevin DuBois2311b1a2019-11-18 16:19:08 -080097 VSyncTracker& tracker, nsecs_t now) {
Ady Abraham9c53ee72020-07-22 21:16:18 -070098 auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
99 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
Ady Abraham69b9e622021-07-19 12:24:31 -0700100 auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800101
102 bool const wouldSkipAVsyncTarget =
103 mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
Ady Abraham69b9e622021-07-19 12:24:31 -0700104 bool const wouldSkipAWakeup =
105 mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
Ady Abraham529bd9f2023-10-05 14:55:30 -0700106 if (flags::dont_skip_on_early()) {
107 if (wouldSkipAVsyncTarget || wouldSkipAWakeup) {
108 return getExpectedCallbackTime(mArmedInfo->mActualVsyncTime, timing);
109 }
110 } else {
111 if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
112 return getExpectedCallbackTime(nextVsyncTime, timing);
113 }
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800114 }
115
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700116 nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
117 nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800118
Ady Abraham9c53ee72020-07-22 21:16:18 -0700119 auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
120 mScheduleTiming = timing;
121 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700122 return getExpectedCallbackTime(nextVsyncTime, timing);
Kevin DuBois305bef12019-10-09 13:23:27 -0700123}
124
Ady Abraham9c53ee72020-07-22 21:16:18 -0700125void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) {
126 mWorkloadUpdateInfo = timing;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700127}
128
129bool VSyncDispatchTimerQueueEntry::hasPendingWorkloadUpdate() const {
130 return mWorkloadUpdateInfo.has_value();
131}
132
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700133nsecs_t VSyncDispatchTimerQueueEntry::adjustVsyncIfNeeded(VSyncTracker& tracker,
134 nsecs_t nextVsyncTime) const {
135 bool const alreadyDispatchedForVsync = mLastDispatchTime &&
136 ((*mLastDispatchTime + mMinVsyncDistance) >= nextVsyncTime &&
137 (*mLastDispatchTime - mMinVsyncDistance) <= nextVsyncTime);
138 const nsecs_t currentPeriod = tracker.currentPeriod();
139 bool const nextVsyncTooClose = mLastDispatchTime &&
140 (nextVsyncTime - *mLastDispatchTime + mMinVsyncDistance) <= currentPeriod;
141 if (alreadyDispatchedForVsync) {
142 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance);
143 }
144
145 if (nextVsyncTooClose) {
146 return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + currentPeriod);
147 }
148
149 return nextVsyncTime;
150}
151
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800152void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700153 if (!mArmedInfo && !mWorkloadUpdateInfo) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700154 return;
155 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700156
157 if (mWorkloadUpdateInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700158 mScheduleTiming = *mWorkloadUpdateInfo;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700159 mWorkloadUpdateInfo.reset();
160 }
161
Ady Abraham9c53ee72020-07-22 21:16:18 -0700162 const auto earliestReadyBy = now + mScheduleTiming.workDuration + mScheduleTiming.readyDuration;
163 const auto earliestVsync = std::max(earliestReadyBy, mScheduleTiming.earliestVsync);
164
Ady Abraham3fcfd8b2022-07-12 12:31:00 -0700165 const auto nextVsyncTime =
166 adjustVsyncIfNeeded(tracker, /*nextVsyncTime*/
167 tracker.nextAnticipatedVSyncTimeFrom(earliestVsync));
Ady Abraham9c53ee72020-07-22 21:16:18 -0700168 const auto nextReadyTime = nextVsyncTime - mScheduleTiming.readyDuration;
169 const auto nextWakeupTime = nextReadyTime - mScheduleTiming.workDuration;
170
171 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Kevin DuBois305bef12019-10-09 13:23:27 -0700172}
173
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800174void VSyncDispatchTimerQueueEntry::disarm() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700175 mArmedInfo.reset();
176}
177
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800178nsecs_t VSyncDispatchTimerQueueEntry::executing() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700179 mLastDispatchTime = mArmedInfo->mActualVsyncTime;
180 disarm();
181 return *mLastDispatchTime;
182}
183
Ady Abraham9c53ee72020-07-22 21:16:18 -0700184void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
185 nsecs_t deadlineTimestamp) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700186 {
187 std::lock_guard<std::mutex> lk(mRunningMutex);
188 mRunning = true;
189 }
190
Ady Abraham9c53ee72020-07-22 21:16:18 -0700191 mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700192
193 std::lock_guard<std::mutex> lk(mRunningMutex);
194 mRunning = false;
195 mCv.notify_all();
196}
197
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800198void VSyncDispatchTimerQueueEntry::ensureNotRunning() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700199 std::unique_lock<std::mutex> lk(mRunningMutex);
200 mCv.wait(lk, [this]() REQUIRES(mRunningMutex) { return !mRunning; });
201}
202
Ady Abraham5e7371c2020-03-24 14:47:24 -0700203void VSyncDispatchTimerQueueEntry::dump(std::string& result) const {
204 std::lock_guard<std::mutex> lk(mRunningMutex);
205 std::string armedInfo;
206 if (mArmedInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700207 StringAppendF(&armedInfo,
208 "[wake up in %.2fms deadline in %.2fms for vsync %.2fms from now]",
Ady Abraham5e7371c2020-03-24 14:47:24 -0700209 (mArmedInfo->mActualWakeupTime - systemTime()) / 1e6f,
Ady Abraham9c53ee72020-07-22 21:16:18 -0700210 (mArmedInfo->mActualReadyTime - systemTime()) / 1e6f,
Ady Abraham5e7371c2020-03-24 14:47:24 -0700211 (mArmedInfo->mActualVsyncTime - systemTime()) / 1e6f);
212 }
213
214 StringAppendF(&result, "\t\t%s: %s %s\n", mName.c_str(),
215 mRunning ? "(in callback function)" : "", armedInfo.c_str());
Ady Abraham9c53ee72020-07-22 21:16:18 -0700216 StringAppendF(&result,
217 "\t\t\tworkDuration: %.2fms readyDuration: %.2fms earliestVsync: %.2fms relative "
218 "to now\n",
219 mScheduleTiming.workDuration / 1e6f, mScheduleTiming.readyDuration / 1e6f,
220 (mScheduleTiming.earliestVsync - systemTime()) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700221
222 if (mLastDispatchTime) {
223 StringAppendF(&result, "\t\t\tmLastDispatchTime: %.2fms ago\n",
224 (systemTime() - *mLastDispatchTime) / 1e6f);
225 } else {
226 StringAppendF(&result, "\t\t\tmLastDispatchTime unknown\n");
227 }
228}
229
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800230VSyncDispatchTimerQueue::VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper> tk,
Leon Scroggins III67388622023-02-06 20:36:20 -0500231 VsyncSchedule::TrackerPtr tracker,
232 nsecs_t timerSlack, nsecs_t minVsyncDistance)
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800233 : mTimeKeeper(std::move(tk)),
Leon Scroggins III67388622023-02-06 20:36:20 -0500234 mTracker(std::move(tracker)),
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800235 mTimerSlack(timerSlack),
236 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700237
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800238VSyncDispatchTimerQueue::~VSyncDispatchTimerQueue() {
Ady Abraham8cb21882020-08-26 18:22:05 -0700239 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700240 cancelTimer();
Leon Scroggins III07738132023-04-24 11:43:53 -0400241 for (auto& [_, entry] : mCallbacks) {
242 ALOGE("Forgot to unregister a callback on VSyncDispatch!");
243 entry->ensureNotRunning();
244 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700245}
246
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800247void VSyncDispatchTimerQueue::cancelTimer() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700248 mIntendedWakeupTime = kInvalidTime;
249 mTimeKeeper->alarmCancel();
250}
251
Ady Abrahamb491c902020-08-15 15:47:56 -0700252void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700253 mIntendedWakeupTime = targetTime;
Ady Abrahamb491c902020-08-15 15:47:56 -0700254 mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
255 mIntendedWakeupTime);
Ady Abraham75398722020-04-07 14:08:45 -0700256 mLastTimerSchedule = mTimeKeeper->now();
Kevin DuBois305bef12019-10-09 13:23:27 -0700257}
258
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800259void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700260 rearmTimerSkippingUpdateFor(now, mCallbacks.end());
261}
262
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800263void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
264 nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700265 std::optional<nsecs_t> min;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800266 std::optional<nsecs_t> targetVsync;
267 std::optional<std::string_view> nextWakeupName;
Kevin DuBois305bef12019-10-09 13:23:27 -0700268 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
269 auto& callback = it->second;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700270 if (!callback->wakeupTime() && !callback->hasPendingWorkloadUpdate()) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700271 continue;
272 }
273
274 if (it != skipUpdateIt) {
Leon Scroggins III67388622023-02-06 20:36:20 -0500275 callback->update(*mTracker, now);
Kevin DuBois305bef12019-10-09 13:23:27 -0700276 }
277 auto const wakeupTime = *callback->wakeupTime();
Dominik Laskowski62eff352021-12-06 09:59:41 -0800278 if (!min || *min > wakeupTime) {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800279 nextWakeupName = callback->name();
Kevin DuBois305bef12019-10-09 13:23:27 -0700280 min = wakeupTime;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800281 targetVsync = callback->targetVsync();
Kevin DuBois305bef12019-10-09 13:23:27 -0700282 }
283 }
284
Dominik Laskowski62eff352021-12-06 09:59:41 -0800285 if (min && min < mIntendedWakeupTime) {
286 if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
287 ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
288 "us; VSYNC in ", ns2us(*targetVsync - now), "us");
289 ATRACE_NAME(trace.c_str());
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800290 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700291 setTimer(*min, now);
292 } else {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800293 ATRACE_NAME("cancel timer");
Kevin DuBois305bef12019-10-09 13:23:27 -0700294 cancelTimer();
295 }
296}
297
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800298void VSyncDispatchTimerQueue::timerCallback() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700299 struct Invocation {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800300 std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800301 nsecs_t vsyncTimestamp;
302 nsecs_t wakeupTimestamp;
Ady Abraham9c53ee72020-07-22 21:16:18 -0700303 nsecs_t deadlineTimestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700304 };
305 std::vector<Invocation> invocations;
306 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700307 std::lock_guard lock(mMutex);
Kevin DuBoisf9477832020-07-16 10:21:36 -0700308 auto const now = mTimeKeeper->now();
309 mLastTimerCallback = now;
Kevin DuBois305bef12019-10-09 13:23:27 -0700310 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
311 auto& callback = it->second;
312 auto const wakeupTime = callback->wakeupTime();
313 if (!wakeupTime) {
314 continue;
315 }
316
Ady Abraham9c53ee72020-07-22 21:16:18 -0700317 auto const readyTime = callback->readyTime();
318
Kevin DuBoisf9477832020-07-16 10:21:36 -0700319 auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
320 if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700321 callback->executing();
Ady Abraham9c53ee72020-07-22 21:16:18 -0700322 invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
323 *wakeupTime, *readyTime});
Kevin DuBois305bef12019-10-09 13:23:27 -0700324 }
325 }
326
327 mIntendedWakeupTime = kInvalidTime;
328 rearmTimer(mTimeKeeper->now());
329 }
330
331 for (auto const& invocation : invocations) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700332 invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
333 invocation.deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700334 }
335}
336
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800337VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800338 Callback callback, std::string callbackName) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700339 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700340 return CallbackToken{
341 mCallbacks
342 .emplace(++mCallbackToken,
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800343 std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
344 std::move(callback),
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800345 mMinVsyncDistance))
Kevin DuBois305bef12019-10-09 13:23:27 -0700346 .first->first};
347}
348
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800349void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) {
350 std::shared_ptr<VSyncDispatchTimerQueueEntry> entry = nullptr;
Kevin DuBois305bef12019-10-09 13:23:27 -0700351 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700352 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700353 auto it = mCallbacks.find(token);
354 if (it != mCallbacks.end()) {
355 entry = it->second;
356 mCallbacks.erase(it);
357 }
358 }
359
360 if (entry) {
361 entry->ensureNotRunning();
362 }
363}
364
Ady Abraham9c53ee72020-07-22 21:16:18 -0700365ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
366 ScheduleTiming scheduleTiming) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800367 std::lock_guard lock(mMutex);
368 return scheduleLocked(token, scheduleTiming);
369}
Kevin DuBois305bef12019-10-09 13:23:27 -0700370
Ady Abraham011f8ba2022-11-22 15:09:07 -0800371ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
372 ScheduleTiming scheduleTiming) {
373 auto it = mCallbacks.find(token);
374 if (it == mCallbacks.end()) {
375 return {};
376 }
377 auto& callback = it->second;
378 auto const now = mTimeKeeper->now();
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700379
Ady Abraham011f8ba2022-11-22 15:09:07 -0800380 /* If the timer thread will run soon, we'll apply this work update via the callback
381 * timer recalculation to avoid cancelling a callback that is about to fire. */
382 auto const rearmImminent = now > mIntendedWakeupTime;
383 if (CC_UNLIKELY(rearmImminent)) {
384 callback->addPendingWorkloadUpdate(scheduleTiming);
Leon Scroggins III67388622023-02-06 20:36:20 -0500385 return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800386 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700387
Leon Scroggins III67388622023-02-06 20:36:20 -0500388 const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800389 if (!result.has_value()) {
390 return {};
391 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700392
Ady Abraham011f8ba2022-11-22 15:09:07 -0800393 if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
394 rearmTimerSkippingUpdateFor(now, it);
Kevin DuBois305bef12019-10-09 13:23:27 -0700395 }
396
397 return result;
398}
399
Ady Abraham011f8ba2022-11-22 15:09:07 -0800400ScheduleResult VSyncDispatchTimerQueue::update(CallbackToken token, ScheduleTiming scheduleTiming) {
401 std::lock_guard lock(mMutex);
402 const auto it = mCallbacks.find(token);
403 if (it == mCallbacks.end()) {
404 return {};
405 }
406
407 auto& callback = it->second;
408 if (!callback->targetVsync().has_value()) {
409 return {};
410 }
411
412 return scheduleLocked(token, scheduleTiming);
413}
414
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800415CancelResult VSyncDispatchTimerQueue::cancel(CallbackToken token) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700416 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700417
418 auto it = mCallbacks.find(token);
419 if (it == mCallbacks.end()) {
420 return CancelResult::Error;
421 }
422 auto& callback = it->second;
423
Kevin DuBoisb340b732020-06-16 09:07:35 -0700424 auto const wakeupTime = callback->wakeupTime();
425 if (wakeupTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700426 callback->disarm();
Kevin DuBoisb340b732020-06-16 09:07:35 -0700427
428 if (*wakeupTime == mIntendedWakeupTime) {
429 mIntendedWakeupTime = kInvalidTime;
430 rearmTimer(mTimeKeeper->now());
431 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700432 return CancelResult::Cancelled;
433 }
434 return CancelResult::TooLate;
435}
436
Ady Abraham5e7371c2020-03-24 14:47:24 -0700437void VSyncDispatchTimerQueue::dump(std::string& result) const {
Ady Abraham8cb21882020-08-26 18:22:05 -0700438 std::lock_guard lock(mMutex);
Ady Abraham75398722020-04-07 14:08:45 -0700439 StringAppendF(&result, "\tTimer:\n");
440 mTimeKeeper->dump(result);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700441 StringAppendF(&result, "\tmTimerSlack: %.2fms mMinVsyncDistance: %.2fms\n", mTimerSlack / 1e6f,
442 mMinVsyncDistance / 1e6f);
443 StringAppendF(&result, "\tmIntendedWakeupTime: %.2fms from now\n",
Ady Abraham75398722020-04-07 14:08:45 -0700444 (mIntendedWakeupTime - mTimeKeeper->now()) / 1e6f);
445 StringAppendF(&result, "\tmLastTimerCallback: %.2fms ago mLastTimerSchedule: %.2fms ago\n",
446 (mTimeKeeper->now() - mLastTimerCallback) / 1e6f,
447 (mTimeKeeper->now() - mLastTimerSchedule) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700448 StringAppendF(&result, "\tCallbacks:\n");
449 for (const auto& [token, entry] : mCallbacks) {
450 entry->dump(result);
451 }
452}
453
Leon Scroggins III67388622023-02-06 20:36:20 -0500454VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800455 VSyncDispatch::Callback callback,
456 std::string callbackName)
Leon Scroggins III67388622023-02-06 20:36:20 -0500457 : mDispatch(std::move(dispatch)),
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400458 mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700459
460VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncCallbackRegistration&& other)
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400461 : mDispatch(std::move(other.mDispatch)), mToken(std::exchange(other.mToken, std::nullopt)) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700462
463VSyncCallbackRegistration& VSyncCallbackRegistration::operator=(VSyncCallbackRegistration&& other) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400464 if (this == &other) return *this;
465 if (mToken) {
466 mDispatch->unregisterCallback(*mToken);
467 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700468 mDispatch = std::move(other.mDispatch);
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400469 mToken = std::exchange(other.mToken, std::nullopt);
Kevin DuBois305bef12019-10-09 13:23:27 -0700470 return *this;
471}
472
473VSyncCallbackRegistration::~VSyncCallbackRegistration() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400474 if (mToken) mDispatch->unregisterCallback(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700475}
476
Ady Abraham9c53ee72020-07-22 21:16:18 -0700477ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400478 if (!mToken) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700479 return std::nullopt;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800480 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400481 return mDispatch->schedule(*mToken, scheduleTiming);
Kevin DuBois305bef12019-10-09 13:23:27 -0700482}
483
Ady Abraham011f8ba2022-11-22 15:09:07 -0800484ScheduleResult VSyncCallbackRegistration::update(VSyncDispatch::ScheduleTiming scheduleTiming) {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400485 if (!mToken) {
Ady Abraham011f8ba2022-11-22 15:09:07 -0800486 return std::nullopt;
487 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400488 return mDispatch->update(*mToken, scheduleTiming);
Ady Abraham011f8ba2022-11-22 15:09:07 -0800489}
490
Kevin DuBois305bef12019-10-09 13:23:27 -0700491CancelResult VSyncCallbackRegistration::cancel() {
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400492 if (!mToken) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800493 return CancelResult::Error;
494 }
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400495 return mDispatch->cancel(*mToken);
Kevin DuBois305bef12019-10-09 13:23:27 -0700496}
497
498} // namespace android::scheduler