1 /*
2 * Copyright 2018 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 #undef LOG_TAG
18 #define LOG_TAG "Scheduler"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21 #include "Scheduler.h"
22
23 #include <android-base/properties.h>
24 #include <android-base/stringprintf.h>
25 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
26 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
27 #include <configstore/Utils.h>
28 #include <ftl/fake_guard.h>
29 #include <gui/WindowInfo.h>
30 #include <system/window.h>
31 #include <ui/DisplayStatInfo.h>
32 #include <utils/Timers.h>
33 #include <utils/Trace.h>
34
35 #include <FrameTimeline/FrameTimeline.h>
36 #include <algorithm>
37 #include <cinttypes>
38 #include <cstdint>
39 #include <functional>
40 #include <memory>
41 #include <numeric>
42
43 #include "../Layer.h"
44 #include "DispSyncSource.h"
45 #include "EventThread.h"
46 #include "FrameRateOverrideMappings.h"
47 #include "InjectVSyncSource.h"
48 #include "OneShotTimer.h"
49 #include "SurfaceFlingerProperties.h"
50 #include "VSyncPredictor.h"
51 #include "VSyncReactor.h"
52
53 #define RETURN_IF_INVALID_HANDLE(handle, ...) \
54 do { \
55 if (mConnections.count(handle) == 0) { \
56 ALOGE("Invalid connection handle %" PRIuPTR, handle.id); \
57 return __VA_ARGS__; \
58 } \
59 } while (false)
60
61 namespace android::scheduler {
62
Scheduler(ICompositor & compositor,ISchedulerCallback & callback,FeatureFlags features)63 Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
64 : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
65
~Scheduler()66 Scheduler::~Scheduler() {
67 // Stop timers and wait for their threads to exit.
68 mDisplayPowerTimer.reset();
69 mTouchTimer.reset();
70
71 // Stop idle timer and clear callbacks, as the RefreshRateConfigs may outlive the Scheduler.
72 setRefreshRateConfigs(nullptr);
73 }
74
startTimers()75 void Scheduler::startTimers() {
76 using namespace sysprop;
77 using namespace std::string_literals;
78
79 if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
80 // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
81 mTouchTimer.emplace(
82 "TouchTimer", std::chrono::milliseconds(millis),
83 [this] { touchTimerCallback(TimerState::Reset); },
84 [this] { touchTimerCallback(TimerState::Expired); });
85 mTouchTimer->start();
86 }
87
88 if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
89 mDisplayPowerTimer.emplace(
90 "DisplayPowerTimer", std::chrono::milliseconds(millis),
91 [this] { displayPowerTimerCallback(TimerState::Reset); },
92 [this] { displayPowerTimerCallback(TimerState::Expired); });
93 mDisplayPowerTimer->start();
94 }
95 }
96
setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs)97 void Scheduler::setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs) {
98 // The current RefreshRateConfigs instance may outlive this call, so unbind its idle timer.
99 {
100 // mRefreshRateConfigsLock is not locked here to avoid the deadlock
101 // as the callback can attempt to acquire the lock before stopIdleTimer can finish
102 // the execution. It's safe to FakeGuard as main thread is the only thread that
103 // writes to the mRefreshRateConfigs.
104 ftl::FakeGuard guard(mRefreshRateConfigsLock);
105 if (mRefreshRateConfigs) {
106 mRefreshRateConfigs->stopIdleTimer();
107 mRefreshRateConfigs->clearIdleTimerCallbacks();
108 }
109 }
110 {
111 // Clear state that depends on the current instance.
112 std::scoped_lock lock(mPolicyLock);
113 mPolicy = {};
114 }
115
116 std::scoped_lock lock(mRefreshRateConfigsLock);
117 mRefreshRateConfigs = std::move(configs);
118 if (!mRefreshRateConfigs) return;
119
120 mRefreshRateConfigs->setIdleTimerCallbacks(
121 {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
122 .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
123 .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
124 .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}});
125
126 mRefreshRateConfigs->startIdleTimer();
127 }
128
run()129 void Scheduler::run() {
130 while (true) {
131 waitMessage();
132 }
133 }
134
createVsyncSchedule(FeatureFlags features)135 void Scheduler::createVsyncSchedule(FeatureFlags features) {
136 mVsyncSchedule.emplace(features);
137 }
138
makePrimaryDispSyncSource(const char * name,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration,bool traceVsync)139 std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
140 const char* name, std::chrono::nanoseconds workDuration,
141 std::chrono::nanoseconds readyDuration, bool traceVsync) {
142 return std::make_unique<scheduler::DispSyncSource>(mVsyncSchedule->getDispatch(),
143 mVsyncSchedule->getTracker(), workDuration,
144 readyDuration, traceVsync, name);
145 }
146
getFrameRateOverride(uid_t uid) const147 std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
148 const auto refreshRateConfigs = holdRefreshRateConfigs();
149 const bool supportsFrameRateOverrideByContent =
150 refreshRateConfigs->supportsFrameRateOverrideByContent();
151 return mFrameRateOverrideMappings
152 .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
153 }
154
isVsyncValid(nsecs_t expectedVsyncTimestamp,uid_t uid) const155 bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
156 const auto frameRate = getFrameRateOverride(uid);
157 if (!frameRate.has_value()) {
158 return true;
159 }
160
161 return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
162 }
163
makeThrottleVsyncCallback() const164 impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
165 std::scoped_lock lock(mRefreshRateConfigsLock);
166
167 return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
168 return !isVsyncValid(expectedVsyncTimestamp, uid);
169 };
170 }
171
makeGetVsyncPeriodFunction() const172 impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
173 return [this](uid_t uid) {
174 const Fps refreshRate = holdRefreshRateConfigs()->getActiveMode()->getFps();
175 const auto currentPeriod =
176 mVsyncSchedule->getTracker().currentPeriod() ?: refreshRate.getPeriodNsecs();
177
178 const auto frameRate = getFrameRateOverride(uid);
179 if (!frameRate.has_value()) {
180 return currentPeriod;
181 }
182
183 const auto divisor = RefreshRateConfigs::getFrameRateDivisor(refreshRate, *frameRate);
184 if (divisor <= 1) {
185 return currentPeriod;
186 }
187 return currentPeriod * divisor;
188 };
189 }
190
createConnection(const char * connectionName,frametimeline::TokenManager * tokenManager,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration,impl::EventThread::InterceptVSyncsCallback interceptCallback)191 ConnectionHandle Scheduler::createConnection(
192 const char* connectionName, frametimeline::TokenManager* tokenManager,
193 std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
194 impl::EventThread::InterceptVSyncsCallback interceptCallback) {
195 auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
196 auto throttleVsync = makeThrottleVsyncCallback();
197 auto getVsyncPeriod = makeGetVsyncPeriodFunction();
198 auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
199 std::move(interceptCallback),
200 std::move(throttleVsync),
201 std::move(getVsyncPeriod));
202 return createConnection(std::move(eventThread));
203 }
204
createConnection(std::unique_ptr<EventThread> eventThread)205 ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
206 const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
207 ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
208
209 auto connection = createConnectionInternal(eventThread.get());
210
211 std::lock_guard<std::mutex> lock(mConnectionsLock);
212 mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
213 return handle;
214 }
215
createConnectionInternal(EventThread * eventThread,ISurfaceComposer::EventRegistrationFlags eventRegistration)216 sp<EventThreadConnection> Scheduler::createConnectionInternal(
217 EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
218 return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
219 }
220
createDisplayEventConnection(ConnectionHandle handle,ISurfaceComposer::EventRegistrationFlags eventRegistration)221 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
222 ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
223 std::lock_guard<std::mutex> lock(mConnectionsLock);
224 RETURN_IF_INVALID_HANDLE(handle, nullptr);
225 return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
226 }
227
getEventConnection(ConnectionHandle handle)228 sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
229 std::lock_guard<std::mutex> lock(mConnectionsLock);
230 RETURN_IF_INVALID_HANDLE(handle, nullptr);
231 return mConnections[handle].connection;
232 }
233
onHotplugReceived(ConnectionHandle handle,PhysicalDisplayId displayId,bool connected)234 void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId displayId,
235 bool connected) {
236 android::EventThread* thread;
237 {
238 std::lock_guard<std::mutex> lock(mConnectionsLock);
239 RETURN_IF_INVALID_HANDLE(handle);
240 thread = mConnections[handle].thread.get();
241 }
242
243 thread->onHotplugReceived(displayId, connected);
244 }
245
onScreenAcquired(ConnectionHandle handle)246 void Scheduler::onScreenAcquired(ConnectionHandle handle) {
247 android::EventThread* thread;
248 {
249 std::lock_guard<std::mutex> lock(mConnectionsLock);
250 RETURN_IF_INVALID_HANDLE(handle);
251 thread = mConnections[handle].thread.get();
252 }
253 thread->onScreenAcquired();
254 mScreenAcquired = true;
255 }
256
onScreenReleased(ConnectionHandle handle)257 void Scheduler::onScreenReleased(ConnectionHandle handle) {
258 android::EventThread* thread;
259 {
260 std::lock_guard<std::mutex> lock(mConnectionsLock);
261 RETURN_IF_INVALID_HANDLE(handle);
262 thread = mConnections[handle].thread.get();
263 }
264 thread->onScreenReleased();
265 mScreenAcquired = false;
266 }
267
onFrameRateOverridesChanged(ConnectionHandle handle,PhysicalDisplayId displayId)268 void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
269 const auto refreshRateConfigs = holdRefreshRateConfigs();
270 const bool supportsFrameRateOverrideByContent =
271 refreshRateConfigs->supportsFrameRateOverrideByContent();
272
273 std::vector<FrameRateOverride> overrides =
274 mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
275
276 android::EventThread* thread;
277 {
278 std::lock_guard lock(mConnectionsLock);
279 RETURN_IF_INVALID_HANDLE(handle);
280 thread = mConnections[handle].thread.get();
281 }
282 thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
283 }
284
onPrimaryDisplayModeChanged(ConnectionHandle handle,DisplayModePtr mode)285 void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
286 {
287 std::lock_guard<std::mutex> lock(mPolicyLock);
288 // Cache the last reported modes for primary display.
289 mPolicy.cachedModeChangedParams = {handle, mode};
290
291 // Invalidate content based refresh rate selection so it could be calculated
292 // again for the new refresh rate.
293 mPolicy.contentRequirements.clear();
294 }
295 onNonPrimaryDisplayModeChanged(handle, mode);
296 }
297
dispatchCachedReportedMode()298 void Scheduler::dispatchCachedReportedMode() {
299 // Check optional fields first.
300 if (!mPolicy.mode) {
301 ALOGW("No mode ID found, not dispatching cached mode.");
302 return;
303 }
304 if (!mPolicy.cachedModeChangedParams) {
305 ALOGW("No mode changed params found, not dispatching cached mode.");
306 return;
307 }
308
309 // If the mode is not the current mode, this means that a
310 // mode change is in progress. In that case we shouldn't dispatch an event
311 // as it will be dispatched when the current mode changes.
312 if (std::scoped_lock lock(mRefreshRateConfigsLock);
313 mRefreshRateConfigs->getActiveMode() != mPolicy.mode) {
314 return;
315 }
316
317 // If there is no change from cached mode, there is no need to dispatch an event
318 if (mPolicy.mode == mPolicy.cachedModeChangedParams->mode) {
319 return;
320 }
321
322 mPolicy.cachedModeChangedParams->mode = mPolicy.mode;
323 onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle,
324 mPolicy.cachedModeChangedParams->mode);
325 }
326
onNonPrimaryDisplayModeChanged(ConnectionHandle handle,DisplayModePtr mode)327 void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
328 android::EventThread* thread;
329 {
330 std::lock_guard<std::mutex> lock(mConnectionsLock);
331 RETURN_IF_INVALID_HANDLE(handle);
332 thread = mConnections[handle].thread.get();
333 }
334 thread->onModeChanged(mode);
335 }
336
getEventThreadConnectionCount(ConnectionHandle handle)337 size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) {
338 std::lock_guard<std::mutex> lock(mConnectionsLock);
339 RETURN_IF_INVALID_HANDLE(handle, 0);
340 return mConnections[handle].thread->getEventThreadConnectionCount();
341 }
342
dump(ConnectionHandle handle,std::string & result) const343 void Scheduler::dump(ConnectionHandle handle, std::string& result) const {
344 android::EventThread* thread;
345 {
346 std::lock_guard<std::mutex> lock(mConnectionsLock);
347 RETURN_IF_INVALID_HANDLE(handle);
348 thread = mConnections.at(handle).thread.get();
349 }
350 thread->dump(result);
351 }
352
setDuration(ConnectionHandle handle,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)353 void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
354 std::chrono::nanoseconds readyDuration) {
355 android::EventThread* thread;
356 {
357 std::lock_guard<std::mutex> lock(mConnectionsLock);
358 RETURN_IF_INVALID_HANDLE(handle);
359 thread = mConnections[handle].thread.get();
360 }
361 thread->setDuration(workDuration, readyDuration);
362 }
363
getDisplayStatInfo(nsecs_t now)364 DisplayStatInfo Scheduler::getDisplayStatInfo(nsecs_t now) {
365 const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(now);
366 const auto vsyncPeriod = mVsyncSchedule->getTracker().currentPeriod();
367 return DisplayStatInfo{.vsyncTime = vsyncTime, .vsyncPeriod = vsyncPeriod};
368 }
369
enableVSyncInjection(bool enable)370 ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
371 if (mInjectVSyncs == enable) {
372 return {};
373 }
374
375 ALOGV("%s VSYNC injection", enable ? "Enabling" : "Disabling");
376
377 if (!mInjectorConnectionHandle) {
378 auto vsyncSource = std::make_unique<InjectVSyncSource>();
379 mVSyncInjector = vsyncSource.get();
380
381 auto eventThread =
382 std::make_unique<impl::EventThread>(std::move(vsyncSource),
383 /*tokenManager=*/nullptr,
384 impl::EventThread::InterceptVSyncsCallback(),
385 impl::EventThread::ThrottleVsyncCallback(),
386 impl::EventThread::GetVsyncPeriodFunction());
387
388 // EventThread does not dispatch VSYNC unless the display is connected and powered on.
389 eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true);
390 eventThread->onScreenAcquired();
391
392 mInjectorConnectionHandle = createConnection(std::move(eventThread));
393 }
394
395 mInjectVSyncs = enable;
396 return mInjectorConnectionHandle;
397 }
398
injectVSync(nsecs_t when,nsecs_t expectedVSyncTime,nsecs_t deadlineTimestamp)399 bool Scheduler::injectVSync(nsecs_t when, nsecs_t expectedVSyncTime, nsecs_t deadlineTimestamp) {
400 if (!mInjectVSyncs || !mVSyncInjector) {
401 return false;
402 }
403
404 mVSyncInjector->onInjectSyncEvent(when, expectedVSyncTime, deadlineTimestamp);
405 return true;
406 }
407
enableHardwareVsync()408 void Scheduler::enableHardwareVsync() {
409 std::lock_guard<std::mutex> lock(mHWVsyncLock);
410 if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
411 mVsyncSchedule->getTracker().resetModel();
412 mSchedulerCallback.setVsyncEnabled(true);
413 mPrimaryHWVsyncEnabled = true;
414 }
415 }
416
disableHardwareVsync(bool makeUnavailable)417 void Scheduler::disableHardwareVsync(bool makeUnavailable) {
418 std::lock_guard<std::mutex> lock(mHWVsyncLock);
419 if (mPrimaryHWVsyncEnabled) {
420 mSchedulerCallback.setVsyncEnabled(false);
421 mPrimaryHWVsyncEnabled = false;
422 }
423 if (makeUnavailable) {
424 mHWVsyncAvailable = false;
425 }
426 }
427
resyncToHardwareVsync(bool makeAvailable,Fps refreshRate)428 void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
429 {
430 std::lock_guard<std::mutex> lock(mHWVsyncLock);
431 if (makeAvailable) {
432 mHWVsyncAvailable = makeAvailable;
433 } else if (!mHWVsyncAvailable) {
434 // Hardware vsync is not currently available, so abort the resync
435 // attempt for now
436 return;
437 }
438 }
439
440 setVsyncPeriod(refreshRate.getPeriodNsecs());
441 }
442
resync()443 void Scheduler::resync() {
444 static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
445
446 const nsecs_t now = systemTime();
447 const nsecs_t last = mLastResyncTime.exchange(now);
448
449 if (now - last > kIgnoreDelay) {
450 const auto refreshRate = [&] {
451 std::scoped_lock lock(mRefreshRateConfigsLock);
452 return mRefreshRateConfigs->getActiveMode()->getFps();
453 }();
454 resyncToHardwareVsync(false, refreshRate);
455 }
456 }
457
setVsyncPeriod(nsecs_t period)458 void Scheduler::setVsyncPeriod(nsecs_t period) {
459 if (period <= 0) return;
460
461 std::lock_guard<std::mutex> lock(mHWVsyncLock);
462 mVsyncSchedule->getController().startPeriodTransition(period);
463
464 if (!mPrimaryHWVsyncEnabled) {
465 mVsyncSchedule->getTracker().resetModel();
466 mSchedulerCallback.setVsyncEnabled(true);
467 mPrimaryHWVsyncEnabled = true;
468 }
469 }
470
addResyncSample(nsecs_t timestamp,std::optional<nsecs_t> hwcVsyncPeriod,bool * periodFlushed)471 void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
472 bool* periodFlushed) {
473 bool needsHwVsync = false;
474 *periodFlushed = false;
475 { // Scope for the lock
476 std::lock_guard<std::mutex> lock(mHWVsyncLock);
477 if (mPrimaryHWVsyncEnabled) {
478 needsHwVsync =
479 mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
480 periodFlushed);
481 }
482 }
483
484 if (needsHwVsync) {
485 enableHardwareVsync();
486 } else {
487 disableHardwareVsync(false);
488 }
489 }
490
addPresentFence(std::shared_ptr<FenceTime> fence)491 void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
492 if (mVsyncSchedule->getController().addPresentFence(std::move(fence))) {
493 enableHardwareVsync();
494 } else {
495 disableHardwareVsync(false);
496 }
497 }
498
registerLayer(Layer * layer)499 void Scheduler::registerLayer(Layer* layer) {
500 using WindowType = gui::WindowInfo::Type;
501
502 scheduler::LayerHistory::LayerVoteType voteType;
503
504 if (!mFeatures.test(Feature::kContentDetection) ||
505 layer->getWindowType() == WindowType::STATUS_BAR) {
506 voteType = scheduler::LayerHistory::LayerVoteType::NoVote;
507 } else if (layer->getWindowType() == WindowType::WALLPAPER) {
508 // Running Wallpaper at Min is considered as part of content detection.
509 voteType = scheduler::LayerHistory::LayerVoteType::Min;
510 } else {
511 voteType = scheduler::LayerHistory::LayerVoteType::Heuristic;
512 }
513
514 // If the content detection feature is off, we still keep the layer history,
515 // since we use it for other features (like Frame Rate API), so layers
516 // still need to be registered.
517 mLayerHistory.registerLayer(layer, voteType);
518 }
519
deregisterLayer(Layer * layer)520 void Scheduler::deregisterLayer(Layer* layer) {
521 mLayerHistory.deregisterLayer(layer);
522 }
523
recordLayerHistory(Layer * layer,nsecs_t presentTime,LayerHistory::LayerUpdateType updateType)524 void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
525 LayerHistory::LayerUpdateType updateType) {
526 {
527 std::scoped_lock lock(mRefreshRateConfigsLock);
528 if (!mRefreshRateConfigs->canSwitch()) return;
529 }
530
531 mLayerHistory.record(layer, presentTime, systemTime(), updateType);
532 }
533
setModeChangePending(bool pending)534 void Scheduler::setModeChangePending(bool pending) {
535 mLayerHistory.setModeChangePending(pending);
536 }
537
chooseRefreshRateForContent()538 void Scheduler::chooseRefreshRateForContent() {
539 const auto configs = holdRefreshRateConfigs();
540 if (!configs->canSwitch()) return;
541
542 ATRACE_CALL();
543
544 LayerHistory::Summary summary = mLayerHistory.summarize(*configs, systemTime());
545 applyPolicy(&Policy::contentRequirements, std::move(summary));
546 }
547
resetIdleTimer()548 void Scheduler::resetIdleTimer() {
549 std::scoped_lock lock(mRefreshRateConfigsLock);
550 mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ false);
551 }
552
onTouchHint()553 void Scheduler::onTouchHint() {
554 if (mTouchTimer) {
555 mTouchTimer->reset();
556
557 std::scoped_lock lock(mRefreshRateConfigsLock);
558 mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ true);
559 }
560 }
561
setDisplayPowerMode(hal::PowerMode powerMode)562 void Scheduler::setDisplayPowerMode(hal::PowerMode powerMode) {
563 {
564 std::lock_guard<std::mutex> lock(mPolicyLock);
565 mPolicy.displayPowerMode = powerMode;
566 }
567 mVsyncSchedule->getController().setDisplayPowerMode(powerMode);
568
569 if (mDisplayPowerTimer) {
570 mDisplayPowerTimer->reset();
571 }
572
573 // Display Power event will boost the refresh rate to performance.
574 // Clear Layer History to get fresh FPS detection
575 mLayerHistory.clear();
576 }
577
kernelIdleTimerCallback(TimerState state)578 void Scheduler::kernelIdleTimerCallback(TimerState state) {
579 ATRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
580
581 // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
582 // magic number
583 const Fps refreshRate = [&] {
584 std::scoped_lock lock(mRefreshRateConfigsLock);
585 return mRefreshRateConfigs->getActiveMode()->getFps();
586 }();
587
588 constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
589 using namespace fps_approx_ops;
590
591 if (state == TimerState::Reset && refreshRate > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
592 // If we're not in performance mode then the kernel timer shouldn't do
593 // anything, as the refresh rate during DPU power collapse will be the
594 // same.
595 resyncToHardwareVsync(true /* makeAvailable */, refreshRate);
596 } else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
597 // Disable HW VSYNC if the timer expired, as we don't need it enabled if
598 // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
599 // need to update the VsyncController model anyway.
600 disableHardwareVsync(false /* makeUnavailable */);
601 }
602
603 mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
604 }
605
idleTimerCallback(TimerState state)606 void Scheduler::idleTimerCallback(TimerState state) {
607 applyPolicy(&Policy::idleTimer, state);
608 ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
609 }
610
touchTimerCallback(TimerState state)611 void Scheduler::touchTimerCallback(TimerState state) {
612 const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
613 // Touch event will boost the refresh rate to performance.
614 // Clear layer history to get fresh FPS detection.
615 // NOTE: Instead of checking all the layers, we should be checking the layer
616 // that is currently on top. b/142507166 will give us this capability.
617 if (applyPolicy(&Policy::touch, touch).touch) {
618 mLayerHistory.clear();
619 }
620 ATRACE_INT("TouchState", static_cast<int>(touch));
621 }
622
displayPowerTimerCallback(TimerState state)623 void Scheduler::displayPowerTimerCallback(TimerState state) {
624 applyPolicy(&Policy::displayPowerTimer, state);
625 ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
626 }
627
dump(std::string & result) const628 void Scheduler::dump(std::string& result) const {
629 using base::StringAppendF;
630
631 StringAppendF(&result, "+ Touch timer: %s\n",
632 mTouchTimer ? mTouchTimer->dump().c_str() : "off");
633 StringAppendF(&result, "+ Content detection: %s %s\n\n",
634 mFeatures.test(Feature::kContentDetection) ? "on" : "off",
635 mLayerHistory.dump().c_str());
636
637 mFrameRateOverrideMappings.dump(result);
638
639 {
640 std::lock_guard lock(mHWVsyncLock);
641 StringAppendF(&result,
642 "mScreenAcquired=%d mPrimaryHWVsyncEnabled=%d mHWVsyncAvailable=%d\n",
643 mScreenAcquired.load(), mPrimaryHWVsyncEnabled, mHWVsyncAvailable);
644 }
645 }
646
dumpVsync(std::string & out) const647 void Scheduler::dumpVsync(std::string& out) const {
648 mVsyncSchedule->dump(out);
649 }
650
updateFrameRateOverrides(GlobalSignals consideredSignals,Fps displayRefreshRate)651 bool Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
652 const auto refreshRateConfigs = holdRefreshRateConfigs();
653
654 // we always update mFrameRateOverridesByContent here
655 // supportsFrameRateOverridesByContent will be checked
656 // when getting FrameRateOverrides from mFrameRateOverrideMappings
657 if (!consideredSignals.idle) {
658 const auto frameRateOverrides =
659 refreshRateConfigs->getFrameRateOverrides(mPolicy.contentRequirements,
660 displayRefreshRate, consideredSignals);
661 return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
662 }
663 return false;
664 }
665
666 template <typename S, typename T>
applyPolicy(S Policy::* statePtr,T && newState)667 auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals {
668 DisplayModePtr newMode;
669 GlobalSignals consideredSignals;
670
671 bool refreshRateChanged = false;
672 bool frameRateOverridesChanged;
673
674 const auto refreshRateConfigs = holdRefreshRateConfigs();
675 {
676 std::lock_guard<std::mutex> lock(mPolicyLock);
677
678 auto& currentState = mPolicy.*statePtr;
679 if (currentState == newState) return {};
680 currentState = std::forward<T>(newState);
681
682 std::tie(newMode, consideredSignals) = chooseDisplayMode();
683 frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());
684
685 if (mPolicy.mode == newMode) {
686 // We don't need to change the display mode, but we might need to send an event
687 // about a mode change, since it was suppressed if previously considered idle.
688 if (!consideredSignals.idle) {
689 dispatchCachedReportedMode();
690 }
691 } else {
692 mPolicy.mode = newMode;
693 refreshRateChanged = true;
694 }
695 }
696 if (refreshRateChanged) {
697 mSchedulerCallback.requestDisplayMode(std::move(newMode),
698 consideredSignals.idle ? DisplayModeEvent::None
699 : DisplayModeEvent::Changed);
700 }
701 if (frameRateOverridesChanged) {
702 mSchedulerCallback.triggerOnFrameRateOverridesChanged();
703 }
704 return consideredSignals;
705 }
706
chooseDisplayMode()707 auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> {
708 ATRACE_CALL();
709
710 const auto configs = holdRefreshRateConfigs();
711
712 // If Display Power is not in normal operation we want to be in performance mode. When coming
713 // back to normal mode, a grace period is given with DisplayPowerTimer.
714 if (mDisplayPowerTimer &&
715 (mPolicy.displayPowerMode != hal::PowerMode::ON ||
716 mPolicy.displayPowerTimer == TimerState::Reset)) {
717 constexpr GlobalSignals kNoSignals;
718 return {configs->getMaxRefreshRateByPolicy(), kNoSignals};
719 }
720
721 const GlobalSignals signals{.touch = mTouchTimer && mPolicy.touch == TouchState::Active,
722 .idle = mPolicy.idleTimer == TimerState::Expired};
723
724 return configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
725 }
726
getPreferredDisplayMode()727 DisplayModePtr Scheduler::getPreferredDisplayMode() {
728 std::lock_guard<std::mutex> lock(mPolicyLock);
729 // Make sure the stored mode is up to date.
730 mPolicy.mode = chooseDisplayMode().first;
731 return mPolicy.mode;
732 }
733
onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline & timeline)734 void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
735 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
736 mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);
737
738 const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
739 if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
740 mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
741 }
742 }
743
onPostComposition(nsecs_t presentTime)744 bool Scheduler::onPostComposition(nsecs_t presentTime) {
745 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
746 if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
747 if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
748 // We need to composite again as refreshTimeNanos is still in the future.
749 return true;
750 }
751
752 mLastVsyncPeriodChangeTimeline->refreshRequired = false;
753 }
754 return false;
755 }
756
onActiveDisplayAreaChanged(uint32_t displayArea)757 void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {
758 mLayerHistory.setDisplayArea(displayArea);
759 }
760
setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride)761 void Scheduler::setGameModeRefreshRateForUid(FrameRateOverride frameRateOverride) {
762 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
763 return;
764 }
765
766 mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
767 }
768
setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride)769 void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
770 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
771 return;
772 }
773
774 mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
775 }
776
getPreviousVsyncFrom(nsecs_t expectedPresentTime) const777 std::chrono::steady_clock::time_point Scheduler::getPreviousVsyncFrom(
778 nsecs_t expectedPresentTime) const {
779 const auto presentTime = std::chrono::nanoseconds(expectedPresentTime);
780 const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule->getTracker().currentPeriod());
781 return std::chrono::steady_clock::time_point(presentTime - vsyncPeriod);
782 }
783
784 } // namespace android::scheduler
785