blob: c0646adead3afc026413b52451d0e80643569e52 [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>
24
Kevin DuBois305bef12019-10-09 13:23:27 -070025#include "TimeKeeper.h"
Kevin DuBoise4f27a82019-11-12 11:41:41 -080026#include "VSyncDispatchTimerQueue.h"
Kevin DuBois305bef12019-10-09 13:23:27 -070027#include "VSyncTracker.h"
28
29namespace android::scheduler {
Dominik Laskowski62eff352021-12-06 09:59:41 -080030
Ady Abraham5e7371c2020-03-24 14:47:24 -070031using base::StringAppendF;
Kevin DuBois305bef12019-10-09 13:23:27 -070032
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070033namespace {
34nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
35 const VSyncDispatch::ScheduleTiming& timing) {
36 return nextVsyncTime - timing.readyDuration - timing.workDuration;
37}
38
39nsecs_t getExpectedCallbackTime(VSyncTracker& tracker, nsecs_t now,
40 const VSyncDispatch::ScheduleTiming& timing) {
41 const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
42 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
43 return getExpectedCallbackTime(nextVsyncTime, timing);
44}
45} // namespace
46
Kevin DuBoise4f27a82019-11-12 11:41:41 -080047VSyncDispatch::~VSyncDispatch() = default;
Kevin DuBois305bef12019-10-09 13:23:27 -070048VSyncTracker::~VSyncTracker() = default;
49TimeKeeper::~TimeKeeper() = default;
50
Kevin DuBoise4f27a82019-11-12 11:41:41 -080051VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string const& name,
Kevin DuBois2968afc2020-01-14 09:48:50 -080052 VSyncDispatch::Callback const& cb,
Kevin DuBoisc94ca832019-11-26 12:56:24 -080053 nsecs_t minVsyncDistance)
54 : mName(name),
55 mCallback(cb),
Kevin DuBoisc94ca832019-11-26 12:56:24 -080056 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -070057
Kevin DuBoise4f27a82019-11-12 11:41:41 -080058std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::lastExecutedVsyncTarget() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070059 return mLastDispatchTime;
60}
61
Kevin DuBoise4f27a82019-11-12 11:41:41 -080062std::string_view VSyncDispatchTimerQueueEntry::name() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070063 return mName;
64}
65
Kevin DuBoise4f27a82019-11-12 11:41:41 -080066std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::wakeupTime() const {
Kevin DuBois305bef12019-10-09 13:23:27 -070067 if (!mArmedInfo) {
68 return {};
69 }
70 return {mArmedInfo->mActualWakeupTime};
71}
72
Ady Abraham9c53ee72020-07-22 21:16:18 -070073std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::readyTime() const {
74 if (!mArmedInfo) {
75 return {};
76 }
77 return {mArmedInfo->mActualReadyTime};
78}
79
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -080080std::optional<nsecs_t> VSyncDispatchTimerQueueEntry::targetVsync() const {
81 if (!mArmedInfo) {
82 return {};
83 }
84 return {mArmedInfo->mActualVsyncTime};
85}
86
Ady Abraham9c53ee72020-07-22 21:16:18 -070087ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
Kevin DuBois2311b1a2019-11-18 16:19:08 -080088 VSyncTracker& tracker, nsecs_t now) {
Ady Abraham9c53ee72020-07-22 21:16:18 -070089 auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
90 std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
Ady Abraham69b9e622021-07-19 12:24:31 -070091 auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBoisc94ca832019-11-26 12:56:24 -080092
93 bool const wouldSkipAVsyncTarget =
94 mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
Ady Abraham69b9e622021-07-19 12:24:31 -070095 bool const wouldSkipAWakeup =
96 mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
97 if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070098 return getExpectedCallbackTime(nextVsyncTime, timing);
Kevin DuBoisc94ca832019-11-26 12:56:24 -080099 }
100
101 bool const alreadyDispatchedForVsync = mLastDispatchTime &&
102 ((*mLastDispatchTime + mMinVsyncDistance) >= nextVsyncTime &&
103 (*mLastDispatchTime - mMinVsyncDistance) <= nextVsyncTime);
104 if (alreadyDispatchedForVsync) {
105 nextVsyncTime =
106 tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance);
Ady Abraham69b9e622021-07-19 12:24:31 -0700107 nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800108 }
109
Ady Abraham9c53ee72020-07-22 21:16:18 -0700110 auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
111 mScheduleTiming = timing;
112 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700113 return getExpectedCallbackTime(nextVsyncTime, timing);
Kevin DuBois305bef12019-10-09 13:23:27 -0700114}
115
Ady Abraham9c53ee72020-07-22 21:16:18 -0700116void VSyncDispatchTimerQueueEntry::addPendingWorkloadUpdate(VSyncDispatch::ScheduleTiming timing) {
117 mWorkloadUpdateInfo = timing;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700118}
119
120bool VSyncDispatchTimerQueueEntry::hasPendingWorkloadUpdate() const {
121 return mWorkloadUpdateInfo.has_value();
122}
123
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800124void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) {
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700125 if (!mArmedInfo && !mWorkloadUpdateInfo) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700126 return;
127 }
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700128
129 if (mWorkloadUpdateInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700130 mScheduleTiming = *mWorkloadUpdateInfo;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700131 mWorkloadUpdateInfo.reset();
132 }
133
Ady Abraham9c53ee72020-07-22 21:16:18 -0700134 const auto earliestReadyBy = now + mScheduleTiming.workDuration + mScheduleTiming.readyDuration;
135 const auto earliestVsync = std::max(earliestReadyBy, mScheduleTiming.earliestVsync);
136
137 const auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(earliestVsync);
138 const auto nextReadyTime = nextVsyncTime - mScheduleTiming.readyDuration;
139 const auto nextWakeupTime = nextReadyTime - mScheduleTiming.workDuration;
140
141 mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
Kevin DuBois305bef12019-10-09 13:23:27 -0700142}
143
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800144void VSyncDispatchTimerQueueEntry::disarm() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700145 mArmedInfo.reset();
146}
147
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800148nsecs_t VSyncDispatchTimerQueueEntry::executing() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700149 mLastDispatchTime = mArmedInfo->mActualVsyncTime;
150 disarm();
151 return *mLastDispatchTime;
152}
153
Ady Abraham9c53ee72020-07-22 21:16:18 -0700154void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
155 nsecs_t deadlineTimestamp) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700156 {
157 std::lock_guard<std::mutex> lk(mRunningMutex);
158 mRunning = true;
159 }
160
Ady Abraham9c53ee72020-07-22 21:16:18 -0700161 mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700162
163 std::lock_guard<std::mutex> lk(mRunningMutex);
164 mRunning = false;
165 mCv.notify_all();
166}
167
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800168void VSyncDispatchTimerQueueEntry::ensureNotRunning() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700169 std::unique_lock<std::mutex> lk(mRunningMutex);
170 mCv.wait(lk, [this]() REQUIRES(mRunningMutex) { return !mRunning; });
171}
172
Ady Abraham5e7371c2020-03-24 14:47:24 -0700173void VSyncDispatchTimerQueueEntry::dump(std::string& result) const {
174 std::lock_guard<std::mutex> lk(mRunningMutex);
175 std::string armedInfo;
176 if (mArmedInfo) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700177 StringAppendF(&armedInfo,
178 "[wake up in %.2fms deadline in %.2fms for vsync %.2fms from now]",
Ady Abraham5e7371c2020-03-24 14:47:24 -0700179 (mArmedInfo->mActualWakeupTime - systemTime()) / 1e6f,
Ady Abraham9c53ee72020-07-22 21:16:18 -0700180 (mArmedInfo->mActualReadyTime - systemTime()) / 1e6f,
Ady Abraham5e7371c2020-03-24 14:47:24 -0700181 (mArmedInfo->mActualVsyncTime - systemTime()) / 1e6f);
182 }
183
184 StringAppendF(&result, "\t\t%s: %s %s\n", mName.c_str(),
185 mRunning ? "(in callback function)" : "", armedInfo.c_str());
Ady Abraham9c53ee72020-07-22 21:16:18 -0700186 StringAppendF(&result,
187 "\t\t\tworkDuration: %.2fms readyDuration: %.2fms earliestVsync: %.2fms relative "
188 "to now\n",
189 mScheduleTiming.workDuration / 1e6f, mScheduleTiming.readyDuration / 1e6f,
190 (mScheduleTiming.earliestVsync - systemTime()) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700191
192 if (mLastDispatchTime) {
193 StringAppendF(&result, "\t\t\tmLastDispatchTime: %.2fms ago\n",
194 (systemTime() - *mLastDispatchTime) / 1e6f);
195 } else {
196 StringAppendF(&result, "\t\t\tmLastDispatchTime unknown\n");
197 }
198}
199
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800200VSyncDispatchTimerQueue::VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper> tk,
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800201 VSyncTracker& tracker, nsecs_t timerSlack,
202 nsecs_t minVsyncDistance)
203 : mTimeKeeper(std::move(tk)),
204 mTracker(tracker),
205 mTimerSlack(timerSlack),
206 mMinVsyncDistance(minVsyncDistance) {}
Kevin DuBois305bef12019-10-09 13:23:27 -0700207
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800208VSyncDispatchTimerQueue::~VSyncDispatchTimerQueue() {
Ady Abraham8cb21882020-08-26 18:22:05 -0700209 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700210 cancelTimer();
211}
212
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800213void VSyncDispatchTimerQueue::cancelTimer() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700214 mIntendedWakeupTime = kInvalidTime;
215 mTimeKeeper->alarmCancel();
216}
217
Ady Abrahamb491c902020-08-15 15:47:56 -0700218void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700219 mIntendedWakeupTime = targetTime;
Ady Abrahamb491c902020-08-15 15:47:56 -0700220 mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
221 mIntendedWakeupTime);
Ady Abraham75398722020-04-07 14:08:45 -0700222 mLastTimerSchedule = mTimeKeeper->now();
Kevin DuBois305bef12019-10-09 13:23:27 -0700223}
224
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800225void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700226 rearmTimerSkippingUpdateFor(now, mCallbacks.end());
227}
228
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800229void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
230 nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700231 std::optional<nsecs_t> min;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800232 std::optional<nsecs_t> targetVsync;
233 std::optional<std::string_view> nextWakeupName;
Kevin DuBois305bef12019-10-09 13:23:27 -0700234 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
235 auto& callback = it->second;
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700236 if (!callback->wakeupTime() && !callback->hasPendingWorkloadUpdate()) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700237 continue;
238 }
239
240 if (it != skipUpdateIt) {
241 callback->update(mTracker, now);
242 }
243 auto const wakeupTime = *callback->wakeupTime();
Dominik Laskowski62eff352021-12-06 09:59:41 -0800244 if (!min || *min > wakeupTime) {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800245 nextWakeupName = callback->name();
Kevin DuBois305bef12019-10-09 13:23:27 -0700246 min = wakeupTime;
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800247 targetVsync = callback->targetVsync();
Kevin DuBois305bef12019-10-09 13:23:27 -0700248 }
249 }
250
Dominik Laskowski62eff352021-12-06 09:59:41 -0800251 if (min && min < mIntendedWakeupTime) {
252 if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
253 ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
254 "us; VSYNC in ", ns2us(*targetVsync - now), "us");
255 ATRACE_NAME(trace.c_str());
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800256 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700257 setTimer(*min, now);
258 } else {
Kevin DuBoisecb1f0d2019-12-12 10:47:41 -0800259 ATRACE_NAME("cancel timer");
Kevin DuBois305bef12019-10-09 13:23:27 -0700260 cancelTimer();
261 }
262}
263
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800264void VSyncDispatchTimerQueue::timerCallback() {
Kevin DuBois305bef12019-10-09 13:23:27 -0700265 struct Invocation {
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800266 std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
Kevin DuBois2968afc2020-01-14 09:48:50 -0800267 nsecs_t vsyncTimestamp;
268 nsecs_t wakeupTimestamp;
Ady Abraham9c53ee72020-07-22 21:16:18 -0700269 nsecs_t deadlineTimestamp;
Kevin DuBois305bef12019-10-09 13:23:27 -0700270 };
271 std::vector<Invocation> invocations;
272 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700273 std::lock_guard lock(mMutex);
Kevin DuBoisf9477832020-07-16 10:21:36 -0700274 auto const now = mTimeKeeper->now();
275 mLastTimerCallback = now;
Kevin DuBois305bef12019-10-09 13:23:27 -0700276 for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
277 auto& callback = it->second;
278 auto const wakeupTime = callback->wakeupTime();
279 if (!wakeupTime) {
280 continue;
281 }
282
Ady Abraham9c53ee72020-07-22 21:16:18 -0700283 auto const readyTime = callback->readyTime();
284
Kevin DuBoisf9477832020-07-16 10:21:36 -0700285 auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
286 if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700287 callback->executing();
Ady Abraham9c53ee72020-07-22 21:16:18 -0700288 invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
289 *wakeupTime, *readyTime});
Kevin DuBois305bef12019-10-09 13:23:27 -0700290 }
291 }
292
293 mIntendedWakeupTime = kInvalidTime;
294 rearmTimer(mTimeKeeper->now());
295 }
296
297 for (auto const& invocation : invocations) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700298 invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
299 invocation.deadlineTimestamp);
Kevin DuBois305bef12019-10-09 13:23:27 -0700300 }
301}
302
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800303VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Kevin DuBois2968afc2020-01-14 09:48:50 -0800304 Callback const& callbackFn, std::string callbackName) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700305 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700306 return CallbackToken{
307 mCallbacks
308 .emplace(++mCallbackToken,
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800309 std::make_shared<VSyncDispatchTimerQueueEntry>(callbackName,
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800310 callbackFn,
311 mMinVsyncDistance))
Kevin DuBois305bef12019-10-09 13:23:27 -0700312 .first->first};
313}
314
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800315void VSyncDispatchTimerQueue::unregisterCallback(CallbackToken token) {
316 std::shared_ptr<VSyncDispatchTimerQueueEntry> entry = nullptr;
Kevin DuBois305bef12019-10-09 13:23:27 -0700317 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700318 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700319 auto it = mCallbacks.find(token);
320 if (it != mCallbacks.end()) {
321 entry = it->second;
322 mCallbacks.erase(it);
323 }
324 }
325
326 if (entry) {
327 entry->ensureNotRunning();
328 }
329}
330
Ady Abraham9c53ee72020-07-22 21:16:18 -0700331ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
332 ScheduleTiming scheduleTiming) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700333 ScheduleResult result;
Kevin DuBois305bef12019-10-09 13:23:27 -0700334 {
Ady Abraham8cb21882020-08-26 18:22:05 -0700335 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700336
337 auto it = mCallbacks.find(token);
338 if (it == mCallbacks.end()) {
339 return result;
340 }
341 auto& callback = it->second;
Kevin DuBois305bef12019-10-09 13:23:27 -0700342 auto const now = mTimeKeeper->now();
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700343
344 /* If the timer thread will run soon, we'll apply this work update via the callback
345 * timer recalculation to avoid cancelling a callback that is about to fire. */
346 auto const rearmImminent = now > mIntendedWakeupTime;
347 if (CC_UNLIKELY(rearmImminent)) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700348 callback->addPendingWorkloadUpdate(scheduleTiming);
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700349 return getExpectedCallbackTime(mTracker, now, scheduleTiming);
Kevin DuBois5c18c1c2020-05-27 15:50:50 -0700350 }
351
Ady Abraham9c53ee72020-07-22 21:16:18 -0700352 result = callback->schedule(scheduleTiming, mTracker, now);
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700353 if (!result.has_value()) {
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800354 return result;
Kevin DuBois305bef12019-10-09 13:23:27 -0700355 }
356
Kevin DuBois2311b1a2019-11-18 16:19:08 -0800357 if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700358 rearmTimerSkippingUpdateFor(now, it);
359 }
360 }
361
362 return result;
363}
364
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800365CancelResult VSyncDispatchTimerQueue::cancel(CallbackToken token) {
Ady Abraham8cb21882020-08-26 18:22:05 -0700366 std::lock_guard lock(mMutex);
Kevin DuBois305bef12019-10-09 13:23:27 -0700367
368 auto it = mCallbacks.find(token);
369 if (it == mCallbacks.end()) {
370 return CancelResult::Error;
371 }
372 auto& callback = it->second;
373
Kevin DuBoisb340b732020-06-16 09:07:35 -0700374 auto const wakeupTime = callback->wakeupTime();
375 if (wakeupTime) {
Kevin DuBois305bef12019-10-09 13:23:27 -0700376 callback->disarm();
Kevin DuBoisb340b732020-06-16 09:07:35 -0700377
378 if (*wakeupTime == mIntendedWakeupTime) {
379 mIntendedWakeupTime = kInvalidTime;
380 rearmTimer(mTimeKeeper->now());
381 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700382 return CancelResult::Cancelled;
383 }
384 return CancelResult::TooLate;
385}
386
Ady Abraham5e7371c2020-03-24 14:47:24 -0700387void VSyncDispatchTimerQueue::dump(std::string& result) const {
Ady Abraham8cb21882020-08-26 18:22:05 -0700388 std::lock_guard lock(mMutex);
Ady Abraham75398722020-04-07 14:08:45 -0700389 StringAppendF(&result, "\tTimer:\n");
390 mTimeKeeper->dump(result);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700391 StringAppendF(&result, "\tmTimerSlack: %.2fms mMinVsyncDistance: %.2fms\n", mTimerSlack / 1e6f,
392 mMinVsyncDistance / 1e6f);
393 StringAppendF(&result, "\tmIntendedWakeupTime: %.2fms from now\n",
Ady Abraham75398722020-04-07 14:08:45 -0700394 (mIntendedWakeupTime - mTimeKeeper->now()) / 1e6f);
395 StringAppendF(&result, "\tmLastTimerCallback: %.2fms ago mLastTimerSchedule: %.2fms ago\n",
396 (mTimeKeeper->now() - mLastTimerCallback) / 1e6f,
397 (mTimeKeeper->now() - mLastTimerSchedule) / 1e6f);
Ady Abraham5e7371c2020-03-24 14:47:24 -0700398 StringAppendF(&result, "\tCallbacks:\n");
399 for (const auto& [token, entry] : mCallbacks) {
400 entry->dump(result);
401 }
402}
403
Kevin DuBois305bef12019-10-09 13:23:27 -0700404VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
Kevin DuBois2968afc2020-01-14 09:48:50 -0800405 VSyncDispatch::Callback const& callbackFn,
Kevin DuBois305bef12019-10-09 13:23:27 -0700406 std::string const& callbackName)
407 : mDispatch(dispatch),
408 mToken(dispatch.registerCallback(callbackFn, callbackName)),
409 mValidToken(true) {}
410
411VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncCallbackRegistration&& other)
412 : mDispatch(other.mDispatch),
413 mToken(std::move(other.mToken)),
414 mValidToken(std::move(other.mValidToken)) {
415 other.mValidToken = false;
416}
417
418VSyncCallbackRegistration& VSyncCallbackRegistration::operator=(VSyncCallbackRegistration&& other) {
419 mDispatch = std::move(other.mDispatch);
420 mToken = std::move(other.mToken);
421 mValidToken = std::move(other.mValidToken);
422 other.mValidToken = false;
423 return *this;
424}
425
426VSyncCallbackRegistration::~VSyncCallbackRegistration() {
427 if (mValidToken) mDispatch.get().unregisterCallback(mToken);
428}
429
Ady Abraham9c53ee72020-07-22 21:16:18 -0700430ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800431 if (!mValidToken) {
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700432 return std::nullopt;
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800433 }
Ady Abraham9c53ee72020-07-22 21:16:18 -0700434 return mDispatch.get().schedule(mToken, scheduleTiming);
Kevin DuBois305bef12019-10-09 13:23:27 -0700435}
436
437CancelResult VSyncCallbackRegistration::cancel() {
Kevin DuBoisc94ca832019-11-26 12:56:24 -0800438 if (!mValidToken) {
439 return CancelResult::Error;
440 }
Kevin DuBois305bef12019-10-09 13:23:27 -0700441 return mDispatch.get().cancel(mToken);
442}
443
444} // namespace android::scheduler