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 <common/trace.h>
28 #include <configstore/Utils.h>
29 #include <ftl/concat.h>
30 #include <ftl/enum.h>
31 #include <ftl/fake_guard.h>
32 #include <ftl/small_map.h>
33 #include <gui/WindowInfo.h>
34 #include <system/window.h>
35 #include <ui/DisplayMap.h>
36 #include <utils/Timers.h>
37
38 #include <FrameTimeline/FrameTimeline.h>
39 #include <scheduler/interface/ICompositor.h>
40
41 #include <cinttypes>
42 #include <cstdint>
43 #include <functional>
44 #include <memory>
45 #include <numeric>
46
47 #include <common/FlagManager.h>
48 #include "EventThread.h"
49 #include "FrameRateOverrideMappings.h"
50 #include "FrontEnd/LayerHandle.h"
51 #include "Layer.h"
52 #include "OneShotTimer.h"
53 #include "RefreshRateStats.h"
54 #include "SurfaceFlingerFactory.h"
55 #include "SurfaceFlingerProperties.h"
56 #include "TimeStats/TimeStats.h"
57 #include "VsyncConfiguration.h"
58 #include "VsyncController.h"
59 #include "VsyncSchedule.h"
60
61 namespace android::scheduler {
62
Scheduler(ICompositor & compositor,ISchedulerCallback & callback,FeatureFlags features,surfaceflinger::Factory & factory,Fps activeRefreshRate,TimeStats & timeStats)63 Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
64 surfaceflinger::Factory& factory, Fps activeRefreshRate, TimeStats& timeStats)
65 : android::impl::MessageQueue(compositor),
66 mFeatures(features),
67 mVsyncConfiguration(factory.createVsyncConfiguration(activeRefreshRate)),
68 mVsyncModulator(sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs())),
69 mRefreshRateStats(std::make_unique<RefreshRateStats>(timeStats, activeRefreshRate)),
70 mSchedulerCallback(callback) {}
71
~Scheduler()72 Scheduler::~Scheduler() {
73 // MessageQueue depends on VsyncSchedule, so first destroy it.
74 // Otherwise, MessageQueue will get destroyed after Scheduler's dtor,
75 // which will cause a use-after-free issue.
76 Impl::destroyVsync();
77
78 // Stop timers and wait for their threads to exit.
79 mDisplayPowerTimer.reset();
80 mTouchTimer.reset();
81
82 // Stop idle timer and clear callbacks, as the RefreshRateSelector may outlive the Scheduler.
83 demotePacesetterDisplay({.toggleIdleTimer = true});
84 }
85
initVsync(frametimeline::TokenManager & tokenManager,std::chrono::nanoseconds workDuration)86 void Scheduler::initVsync(frametimeline::TokenManager& tokenManager,
87 std::chrono::nanoseconds workDuration) {
88 Impl::initVsyncInternal(getVsyncSchedule()->getDispatch(), tokenManager, workDuration);
89 }
90
startTimers()91 void Scheduler::startTimers() {
92 using namespace sysprop;
93 using namespace std::string_literals;
94
95 const int32_t defaultTouchTimerValue =
96 FlagManager::getInstance().enable_fro_dependent_features() &&
97 sysprop::enable_frame_rate_override(true)
98 ? 200
99 : 0;
100 if (const int32_t millis = set_touch_timer_ms(defaultTouchTimerValue); millis > 0) {
101 // Touch events are coming to SF every 100ms, so the timer needs to be higher than that
102 mTouchTimer.emplace(
103 "TouchTimer", std::chrono::milliseconds(millis),
104 [this] { touchTimerCallback(TimerState::Reset); },
105 [this] { touchTimerCallback(TimerState::Expired); });
106 mTouchTimer->start();
107 }
108
109 if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
110 mDisplayPowerTimer.emplace(
111 "DisplayPowerTimer", std::chrono::milliseconds(millis),
112 [this] { displayPowerTimerCallback(TimerState::Reset); },
113 [this] { displayPowerTimerCallback(TimerState::Expired); });
114 mDisplayPowerTimer->start();
115 }
116 }
117
setPacesetterDisplay(PhysicalDisplayId pacesetterId)118 void Scheduler::setPacesetterDisplay(PhysicalDisplayId pacesetterId) {
119 constexpr PromotionParams kPromotionParams = {.toggleIdleTimer = true};
120
121 demotePacesetterDisplay(kPromotionParams);
122 promotePacesetterDisplay(pacesetterId, kPromotionParams);
123
124 // Cancel the pending refresh rate change, if any, before updating the phase configuration.
125 mVsyncModulator->cancelRefreshRateChange();
126
127 mVsyncConfiguration->reset();
128 updatePhaseConfiguration(pacesetterId, pacesetterSelectorPtr()->getActiveMode().fps);
129 }
130
registerDisplay(PhysicalDisplayId displayId,RefreshRateSelectorPtr selectorPtr,PhysicalDisplayId activeDisplayId)131 void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
132 PhysicalDisplayId activeDisplayId) {
133 auto schedulePtr =
134 std::make_shared<VsyncSchedule>(selectorPtr->getActiveMode().modePtr, mFeatures,
135 [this](PhysicalDisplayId id, bool enable) {
136 onHardwareVsyncRequest(id, enable);
137 });
138
139 registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr),
140 activeDisplayId);
141 }
142
registerDisplayInternal(PhysicalDisplayId displayId,RefreshRateSelectorPtr selectorPtr,VsyncSchedulePtr schedulePtr,PhysicalDisplayId activeDisplayId)143 void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
144 RefreshRateSelectorPtr selectorPtr,
145 VsyncSchedulePtr schedulePtr,
146 PhysicalDisplayId activeDisplayId) {
147 const bool isPrimary = (ftl::FakeGuard(mDisplayLock), !mPacesetterDisplayId);
148
149 // Start the idle timer for the first registered (i.e. primary) display.
150 const PromotionParams promotionParams = {.toggleIdleTimer = isPrimary};
151
152 demotePacesetterDisplay(promotionParams);
153
154 auto [pacesetterVsyncSchedule, isNew] = [&]() REQUIRES(kMainThreadContext) {
155 std::scoped_lock lock(mDisplayLock);
156 const bool isNew = mDisplays
157 .emplace_or_replace(displayId, displayId, std::move(selectorPtr),
158 std::move(schedulePtr), mFeatures)
159 .second;
160
161 return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId, promotionParams),
162 isNew);
163 }();
164
165 applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
166
167 // Disable hardware VSYNC if the registration is new, as opposed to a renewal.
168 if (isNew) {
169 onHardwareVsyncRequest(displayId, false);
170 }
171
172 dispatchHotplug(displayId, Hotplug::Connected);
173 }
174
unregisterDisplay(PhysicalDisplayId displayId,PhysicalDisplayId activeDisplayId)175 void Scheduler::unregisterDisplay(PhysicalDisplayId displayId, PhysicalDisplayId activeDisplayId) {
176 LOG_ALWAYS_FATAL_IF(displayId == activeDisplayId, "Cannot unregister the active display!");
177
178 dispatchHotplug(displayId, Hotplug::Disconnected);
179
180 constexpr PromotionParams kPromotionParams = {.toggleIdleTimer = false};
181 demotePacesetterDisplay(kPromotionParams);
182
183 std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
184 {
185 std::scoped_lock lock(mDisplayLock);
186 mDisplays.erase(displayId);
187
188 // Do not allow removing the final display. Code in the scheduler expects
189 // there to be at least one display. (This may be relaxed in the future with
190 // headless virtual display.)
191 LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!");
192
193 pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId, kPromotionParams);
194 }
195 applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
196 }
197
run()198 void Scheduler::run() {
199 while (true) {
200 waitMessage();
201 }
202 }
203
onFrameSignal(ICompositor & compositor,VsyncId vsyncId,TimePoint expectedVsyncTime)204 void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
205 TimePoint expectedVsyncTime) {
206 const auto debugPresentDelay = mDebugPresentDelay.load();
207 mDebugPresentDelay.store(std::nullopt);
208
209 const FrameTargeter::BeginFrameArgs beginFrameArgs =
210 {.frameBeginTime = SchedulerClock::now(),
211 .vsyncId = vsyncId,
212 .expectedVsyncTime = expectedVsyncTime,
213 .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
214 .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration,
215 .debugPresentTimeDelay = debugPresentDelay};
216
217 ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked();
218 pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);
219
220 {
221 FrameTargets targets;
222 targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target());
223
224 // TODO (b/256196556): Followers should use the next VSYNC after the frontrunner, not the
225 // pacesetter.
226 // Update expectedVsyncTime, which may have been adjusted by beginFrame.
227 expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime();
228
229 for (const auto& [id, display] : mDisplays) {
230 if (id == pacesetterPtr->displayId) continue;
231
232 auto followerBeginFrameArgs = beginFrameArgs;
233 followerBeginFrameArgs.expectedVsyncTime =
234 display.schedulePtr->vsyncDeadlineAfter(expectedVsyncTime);
235
236 FrameTargeter& targeter = *display.targeterPtr;
237 targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr);
238 targets.try_emplace(id, &targeter.target());
239 }
240
241 if (!compositor.commit(pacesetterPtr->displayId, targets)) {
242 if (FlagManager::getInstance().vrr_config()) {
243 compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
244 }
245 mSchedulerCallback.onCommitNotComposited();
246 return;
247 }
248 }
249
250 // The pacesetter may have changed or been registered anew during commit.
251 pacesetterPtr = pacesetterPtrLocked();
252
253 // TODO(b/256196556): Choose the frontrunner display.
254 FrameTargeters targeters;
255 targeters.try_emplace(pacesetterPtr->displayId, pacesetterPtr->targeterPtr.get());
256
257 for (auto& [id, display] : mDisplays) {
258 if (id == pacesetterPtr->displayId) continue;
259
260 FrameTargeter& targeter = *display.targeterPtr;
261 targeters.try_emplace(id, &targeter);
262 }
263
264 if (FlagManager::getInstance().vrr_config() &&
265 CC_UNLIKELY(mPacesetterFrameDurationFractionToSkip > 0.f)) {
266 const auto period = pacesetterPtr->targeterPtr->target().expectedFrameDuration();
267 const auto skipDuration = Duration::fromNs(
268 static_cast<nsecs_t>(period.ns() * mPacesetterFrameDurationFractionToSkip));
269 SFTRACE_FORMAT("Injecting jank for %f%% of the frame (%" PRId64 " ns)",
270 mPacesetterFrameDurationFractionToSkip * 100, skipDuration.ns());
271 std::this_thread::sleep_for(skipDuration);
272 mPacesetterFrameDurationFractionToSkip = 0.f;
273 }
274
275 const auto resultsPerDisplay = compositor.composite(pacesetterPtr->displayId, targeters);
276 if (FlagManager::getInstance().vrr_config()) {
277 compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
278 }
279 compositor.sample();
280
281 for (const auto& [id, targeter] : targeters) {
282 const auto resultOpt = resultsPerDisplay.get(id);
283 LOG_ALWAYS_FATAL_IF(!resultOpt);
284 targeter->endFrame(*resultOpt);
285 }
286 }
287
getFrameRateOverride(uid_t uid) const288 std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
289 const bool supportsFrameRateOverrideByContent =
290 pacesetterSelectorPtr()->supportsAppFrameRateOverrideByContent();
291 return mFrameRateOverrideMappings
292 .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
293 }
294
isVsyncValid(TimePoint expectedVsyncTime,uid_t uid) const295 bool Scheduler::isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const {
296 const auto frameRate = getFrameRateOverride(uid);
297 if (!frameRate.has_value()) {
298 return true;
299 }
300
301 SFTRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str());
302 return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), *frameRate);
303 }
304
isVsyncInPhase(TimePoint expectedVsyncTime,Fps frameRate) const305 bool Scheduler::isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const {
306 return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), frameRate);
307 }
308
throttleVsync(android::TimePoint expectedPresentTime,uid_t uid)309 bool Scheduler::throttleVsync(android::TimePoint expectedPresentTime, uid_t uid) {
310 return !isVsyncValid(expectedPresentTime, uid);
311 }
312
getVsyncPeriod(uid_t uid)313 Period Scheduler::getVsyncPeriod(uid_t uid) {
314 const auto [refreshRate, period] = [this] {
315 std::scoped_lock lock(mDisplayLock);
316 const auto pacesetterOpt = pacesetterDisplayLocked();
317 LOG_ALWAYS_FATAL_IF(!pacesetterOpt);
318 const Display& pacesetter = *pacesetterOpt;
319 const FrameRateMode& frameRateMode = pacesetter.selectorPtr->getActiveMode();
320 const auto refreshRate = frameRateMode.fps;
321 const auto displayVsync = frameRateMode.modePtr->getVsyncRate();
322 const auto numPeriod = RefreshRateSelector::getFrameRateDivisor(displayVsync, refreshRate);
323 return std::make_pair(refreshRate, numPeriod * pacesetter.schedulePtr->period());
324 }();
325
326 const Period currentPeriod = period != Period::zero() ? period : refreshRate.getPeriod();
327
328 const auto frameRate = getFrameRateOverride(uid);
329 if (!frameRate.has_value()) {
330 return currentPeriod;
331 }
332
333 const auto divisor = RefreshRateSelector::getFrameRateDivisor(refreshRate, *frameRate);
334 if (divisor <= 1) {
335 return currentPeriod;
336 }
337
338 // TODO(b/299378819): the casting is not needed, but we need a flag as it might change
339 // behaviour.
340 return Period::fromNs(currentPeriod.ns() * divisor);
341 }
onExpectedPresentTimePosted(TimePoint expectedPresentTime)342 void Scheduler::onExpectedPresentTimePosted(TimePoint expectedPresentTime) {
343 const auto frameRateMode = [this] {
344 std::scoped_lock lock(mDisplayLock);
345 const auto pacesetterOpt = pacesetterDisplayLocked();
346 const Display& pacesetter = *pacesetterOpt;
347 return pacesetter.selectorPtr->getActiveMode();
348 }();
349
350 if (frameRateMode.modePtr->getVrrConfig()) {
351 mSchedulerCallback.onExpectedPresentTimePosted(expectedPresentTime, frameRateMode.modePtr,
352 frameRateMode.fps);
353 }
354 }
355
createEventThread(Cycle cycle,frametimeline::TokenManager * tokenManager,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)356 void Scheduler::createEventThread(Cycle cycle, frametimeline::TokenManager* tokenManager,
357 std::chrono::nanoseconds workDuration,
358 std::chrono::nanoseconds readyDuration) {
359 auto eventThread =
360 std::make_unique<android::impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
361 getVsyncSchedule(), tokenManager, *this,
362 workDuration, readyDuration);
363
364 if (cycle == Cycle::Render) {
365 mRenderEventThread = std::move(eventThread);
366 } else {
367 mLastCompositeEventThread = std::move(eventThread);
368 }
369 }
370
createDisplayEventConnection(Cycle cycle,EventRegistrationFlags eventRegistration,const sp<IBinder> & layerHandle)371 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
372 Cycle cycle, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) {
373 const auto connection = eventThreadFor(cycle).createEventConnection(eventRegistration);
374 const auto layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
375
376 if (layerId != static_cast<int32_t>(UNASSIGNED_LAYER_ID)) {
377 // TODO(b/290409668): Moving the choreographer attachment to be a transaction that will be
378 // processed on the main thread.
379 mSchedulerCallback.onChoreographerAttached();
380
381 std::scoped_lock lock(mChoreographerLock);
382 const auto [iter, emplaced] =
383 mAttachedChoreographers.emplace(layerId,
384 AttachedChoreographers{Fps(), {connection}});
385 if (!emplaced) {
386 iter->second.connections.emplace(connection);
387 connection->frameRate = iter->second.frameRate;
388 }
389 }
390 return connection;
391 }
392
dispatchHotplug(PhysicalDisplayId displayId,Hotplug hotplug)393 void Scheduler::dispatchHotplug(PhysicalDisplayId displayId, Hotplug hotplug) {
394 if (hasEventThreads()) {
395 const bool connected = hotplug == Hotplug::Connected;
396 eventThreadFor(Cycle::Render).onHotplugReceived(displayId, connected);
397 eventThreadFor(Cycle::LastComposite).onHotplugReceived(displayId, connected);
398 }
399 }
400
dispatchHotplugError(int32_t errorCode)401 void Scheduler::dispatchHotplugError(int32_t errorCode) {
402 if (hasEventThreads()) {
403 eventThreadFor(Cycle::Render).onHotplugConnectionError(errorCode);
404 eventThreadFor(Cycle::LastComposite).onHotplugConnectionError(errorCode);
405 }
406 }
407
enableSyntheticVsync(bool enable)408 void Scheduler::enableSyntheticVsync(bool enable) {
409 eventThreadFor(Cycle::Render).enableSyntheticVsync(enable);
410 }
411
omitVsyncDispatching(bool omitted)412 void Scheduler::omitVsyncDispatching(bool omitted) {
413 eventThreadFor(Cycle::Render).omitVsyncDispatching(omitted);
414 // Note: If we don't couple Cycle::LastComposite event thread, there is a black screen
415 // after boot. This is most likely sysui or system_server dependency on sf instance
416 // Choreographer
417 eventThreadFor(Cycle::LastComposite).omitVsyncDispatching(omitted);
418 }
419
onFrameRateOverridesChanged()420 void Scheduler::onFrameRateOverridesChanged() {
421 const auto [pacesetterId, supportsFrameRateOverrideByContent] = [this] {
422 std::scoped_lock lock(mDisplayLock);
423 const auto pacesetterOpt = pacesetterDisplayLocked();
424 LOG_ALWAYS_FATAL_IF(!pacesetterOpt);
425 const Display& pacesetter = *pacesetterOpt;
426 return std::make_pair(FTL_FAKE_GUARD(kMainThreadContext, *mPacesetterDisplayId),
427 pacesetter.selectorPtr->supportsAppFrameRateOverrideByContent());
428 }();
429
430 std::vector<FrameRateOverride> overrides =
431 mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
432
433 eventThreadFor(Cycle::Render).onFrameRateOverridesChanged(pacesetterId, std::move(overrides));
434 }
435
onHdcpLevelsChanged(Cycle cycle,PhysicalDisplayId displayId,int32_t connectedLevel,int32_t maxLevel)436 void Scheduler::onHdcpLevelsChanged(Cycle cycle, PhysicalDisplayId displayId,
437 int32_t connectedLevel, int32_t maxLevel) {
438 eventThreadFor(cycle).onHdcpLevelsChanged(displayId, connectedLevel, maxLevel);
439 }
440
441 #pragma clang diagnostic push
442 #pragma clang diagnostic ignored "-Wunused-value" // b/369277774
onDisplayModeChanged(PhysicalDisplayId displayId,const FrameRateMode & mode,bool clearContentRequirements)443 bool Scheduler::onDisplayModeChanged(PhysicalDisplayId displayId, const FrameRateMode& mode,
444 bool clearContentRequirements) {
445 const bool isPacesetter =
446 FTL_FAKE_GUARD(kMainThreadContext,
447 (std::scoped_lock(mDisplayLock), displayId == mPacesetterDisplayId));
448
449 if (isPacesetter) {
450 std::lock_guard<std::mutex> lock(mPolicyLock);
451 mPolicy.emittedModeOpt = mode;
452
453 if (clearContentRequirements) {
454 // Invalidate content based refresh rate selection so it could be calculated
455 // again for the new refresh rate.
456 mPolicy.contentRequirements.clear();
457 }
458 }
459
460 if (hasEventThreads()) {
461 eventThreadFor(Cycle::Render).onModeChanged(mode);
462 }
463
464 return isPacesetter;
465 }
466 #pragma clang diagnostic pop
467
onDisplayModeRejected(PhysicalDisplayId displayId,DisplayModeId modeId)468 void Scheduler::onDisplayModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) {
469 if (hasEventThreads()) {
470 eventThreadFor(Cycle::Render).onModeRejected(displayId, modeId);
471 }
472 }
473
emitModeChangeIfNeeded()474 void Scheduler::emitModeChangeIfNeeded() {
475 if (!mPolicy.modeOpt || !mPolicy.emittedModeOpt) {
476 ALOGW("No mode change to emit");
477 return;
478 }
479
480 const auto& mode = *mPolicy.modeOpt;
481
482 if (mode != pacesetterSelectorPtr()->getActiveMode()) {
483 // A mode change is pending. The event will be emitted when the mode becomes active.
484 return;
485 }
486
487 if (mode == *mPolicy.emittedModeOpt) {
488 // The event was already emitted.
489 return;
490 }
491
492 mPolicy.emittedModeOpt = mode;
493
494 if (hasEventThreads()) {
495 eventThreadFor(Cycle::Render).onModeChanged(mode);
496 }
497 }
498
dump(Cycle cycle,std::string & result) const499 void Scheduler::dump(Cycle cycle, std::string& result) const {
500 eventThreadFor(cycle).dump(result);
501 }
502
setDuration(Cycle cycle,std::chrono::nanoseconds workDuration,std::chrono::nanoseconds readyDuration)503 void Scheduler::setDuration(Cycle cycle, std::chrono::nanoseconds workDuration,
504 std::chrono::nanoseconds readyDuration) {
505 if (hasEventThreads()) {
506 eventThreadFor(cycle).setDuration(workDuration, readyDuration);
507 }
508 }
509
510 #pragma clang diagnostic push
511 #pragma clang diagnostic ignored "-Wunused-value" // b/369277774
updatePhaseConfiguration(PhysicalDisplayId displayId,Fps refreshRate)512 void Scheduler::updatePhaseConfiguration(PhysicalDisplayId displayId, Fps refreshRate) {
513 const bool isPacesetter =
514 FTL_FAKE_GUARD(kMainThreadContext,
515 (std::scoped_lock(mDisplayLock), displayId == mPacesetterDisplayId));
516 if (!isPacesetter) return;
517
518 mRefreshRateStats->setRefreshRate(refreshRate);
519 mVsyncConfiguration->setRefreshRateFps(refreshRate);
520 setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()),
521 refreshRate.getPeriod());
522 }
523 #pragma clang diagnostic pop
524
setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powerMode)525 void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powerMode) {
526 mRefreshRateStats->setPowerMode(powerMode);
527 }
528
setVsyncConfig(const VsyncConfig & config,Period vsyncPeriod)529 void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
530 setDuration(Cycle::Render,
531 /* workDuration */ config.appWorkDuration,
532 /* readyDuration */ config.sfWorkDuration);
533 setDuration(Cycle::LastComposite,
534 /* workDuration */ vsyncPeriod,
535 /* readyDuration */ config.sfWorkDuration);
536 setDuration(config.sfWorkDuration);
537 }
538
enableHardwareVsync(PhysicalDisplayId id)539 void Scheduler::enableHardwareVsync(PhysicalDisplayId id) {
540 auto schedule = getVsyncSchedule(id);
541 LOG_ALWAYS_FATAL_IF(!schedule);
542 schedule->enableHardwareVsync();
543 }
544
disableHardwareVsync(PhysicalDisplayId id,bool disallow)545 void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) {
546 auto schedule = getVsyncSchedule(id);
547 LOG_ALWAYS_FATAL_IF(!schedule);
548 schedule->disableHardwareVsync(disallow);
549 }
550
resyncAllToHardwareVsync(bool allowToEnable)551 void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
552 SFTRACE_CALL();
553 std::scoped_lock lock(mDisplayLock);
554 ftl::FakeGuard guard(kMainThreadContext);
555
556 for (const auto& [id, display] : mDisplays) {
557 if (display.powerMode != hal::PowerMode::OFF ||
558 !FlagManager::getInstance().multithreaded_present()) {
559 resyncToHardwareVsyncLocked(id, allowToEnable);
560 }
561 }
562 }
563
resyncToHardwareVsyncLocked(PhysicalDisplayId id,bool allowToEnable,DisplayModePtr modePtr)564 void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEnable,
565 DisplayModePtr modePtr) {
566 const auto displayOpt = mDisplays.get(id);
567 if (!displayOpt) {
568 ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
569 return;
570 }
571 const Display& display = *displayOpt;
572
573 if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) {
574 if (!modePtr) {
575 modePtr = display.selectorPtr->getActiveMode().modePtr.get();
576 }
577 if (modePtr->getVsyncRate().isValid()) {
578 constexpr bool kForce = false;
579 display.schedulePtr->onDisplayModeChanged(ftl::as_non_null(modePtr), kForce);
580 }
581 }
582 }
583
onHardwareVsyncRequest(PhysicalDisplayId id,bool enabled)584 void Scheduler::onHardwareVsyncRequest(PhysicalDisplayId id, bool enabled) {
585 static const auto& whence = __func__;
586 SFTRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str());
587
588 // On main thread to serialize reads/writes of pending hardware VSYNC state.
589 static_cast<void>(
590 schedule([=, this]() FTL_FAKE_GUARD(mDisplayLock) FTL_FAKE_GUARD(kMainThreadContext) {
591 SFTRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str());
592
593 if (const auto displayOpt = mDisplays.get(id)) {
594 auto& display = displayOpt->get();
595 display.schedulePtr->setPendingHardwareVsyncState(enabled);
596
597 if (display.powerMode != hal::PowerMode::OFF) {
598 mSchedulerCallback.requestHardwareVsync(id, enabled);
599 }
600 }
601 }));
602 }
603
setRenderRate(PhysicalDisplayId id,Fps renderFrameRate,bool applyImmediately)604 void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate, bool applyImmediately) {
605 std::scoped_lock lock(mDisplayLock);
606 ftl::FakeGuard guard(kMainThreadContext);
607
608 const auto displayOpt = mDisplays.get(id);
609 if (!displayOpt) {
610 ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
611 return;
612 }
613 const Display& display = *displayOpt;
614 const auto mode = display.selectorPtr->getActiveMode();
615
616 using fps_approx_ops::operator!=;
617 LOG_ALWAYS_FATAL_IF(renderFrameRate != mode.fps,
618 "Mismatch in render frame rates. Selector: %s, Scheduler: %s, Display: "
619 "%" PRIu64,
620 to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str(), id.value);
621
622 ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
623 to_string(mode.modePtr->getVsyncRate()).c_str());
624
625 display.schedulePtr->getTracker().setRenderRate(renderFrameRate, applyImmediately);
626 }
627
getNextFrameInterval(PhysicalDisplayId id,TimePoint currentExpectedPresentTime) const628 Fps Scheduler::getNextFrameInterval(PhysicalDisplayId id,
629 TimePoint currentExpectedPresentTime) const {
630 std::scoped_lock lock(mDisplayLock);
631 ftl::FakeGuard guard(kMainThreadContext);
632
633 const auto displayOpt = mDisplays.get(id);
634 if (!displayOpt) {
635 ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
636 return Fps{};
637 }
638 const Display& display = *displayOpt;
639 const Duration threshold =
640 display.selectorPtr->getActiveMode().modePtr->getVsyncRate().getPeriod() / 2;
641 const TimePoint nextVsyncTime =
642 display.schedulePtr->vsyncDeadlineAfter(currentExpectedPresentTime + threshold,
643 currentExpectedPresentTime);
644 const Duration frameInterval = nextVsyncTime - currentExpectedPresentTime;
645 return Fps::fromPeriodNsecs(frameInterval.ns());
646 }
647
resync()648 void Scheduler::resync() {
649 static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
650
651 const nsecs_t now = systemTime();
652 const nsecs_t last = mLastResyncTime.exchange(now);
653
654 if (now - last > kIgnoreDelay) {
655 resyncAllToHardwareVsync(false /* allowToEnable */);
656 }
657 }
658
addResyncSample(PhysicalDisplayId id,nsecs_t timestamp,std::optional<nsecs_t> hwcVsyncPeriodIn)659 bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
660 std::optional<nsecs_t> hwcVsyncPeriodIn) {
661 const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
662 return Period::fromNs(nanos);
663 });
664 auto schedule = getVsyncSchedule(id);
665 if (!schedule) {
666 ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
667 return false;
668 }
669 return schedule->addResyncSample(TimePoint::fromNs(timestamp), hwcVsyncPeriod);
670 }
671
addPresentFence(PhysicalDisplayId id,std::shared_ptr<FenceTime> fence)672 void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
673 SFTRACE_NAME(ftl::Concat(__func__, ' ', id.value).c_str());
674 const auto scheduleOpt =
675 (ftl::FakeGuard(mDisplayLock), mDisplays.get(id)).and_then([](const Display& display) {
676 return display.powerMode == hal::PowerMode::OFF
677 ? std::nullopt
678 : std::make_optional(display.schedulePtr);
679 });
680
681 if (!scheduleOpt) return;
682 const auto& schedule = scheduleOpt->get();
683
684 const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence));
685 if (needMoreSignals) {
686 schedule->enableHardwareVsync();
687 } else {
688 constexpr bool kDisallow = false;
689 schedule->disableHardwareVsync(kDisallow);
690 }
691 }
692
registerLayer(Layer * layer,FrameRateCompatibility frameRateCompatibility)693 void Scheduler::registerLayer(Layer* layer, FrameRateCompatibility frameRateCompatibility) {
694 // If the content detection feature is off, we still keep the layer history,
695 // since we use it for other features (like Frame Rate API), so layers
696 // still need to be registered.
697 mLayerHistory.registerLayer(layer, mFeatures.test(Feature::kContentDetection),
698 frameRateCompatibility);
699 }
700
deregisterLayer(Layer * layer)701 void Scheduler::deregisterLayer(Layer* layer) {
702 mLayerHistory.deregisterLayer(layer);
703 }
704
onLayerDestroyed(Layer * layer)705 void Scheduler::onLayerDestroyed(Layer* layer) {
706 std::scoped_lock lock(mChoreographerLock);
707 mAttachedChoreographers.erase(layer->getSequence());
708 }
709
recordLayerHistory(int32_t id,const LayerProps & layerProps,nsecs_t presentTime,nsecs_t now,LayerHistory::LayerUpdateType updateType)710 void Scheduler::recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime,
711 nsecs_t now, LayerHistory::LayerUpdateType updateType) {
712 if (pacesetterSelectorPtr()->canSwitch()) {
713 mLayerHistory.record(id, layerProps, presentTime, now, updateType);
714 }
715 }
716
setModeChangePending(bool pending)717 void Scheduler::setModeChangePending(bool pending) {
718 mLayerHistory.setModeChangePending(pending);
719 }
720
setDefaultFrameRateCompatibility(int32_t id,scheduler::FrameRateCompatibility frameRateCompatibility)721 void Scheduler::setDefaultFrameRateCompatibility(
722 int32_t id, scheduler::FrameRateCompatibility frameRateCompatibility) {
723 mLayerHistory.setDefaultFrameRateCompatibility(id, frameRateCompatibility,
724 mFeatures.test(Feature::kContentDetection));
725 }
726
setLayerProperties(int32_t id,const android::scheduler::LayerProps & properties)727 void Scheduler::setLayerProperties(int32_t id, const android::scheduler::LayerProps& properties) {
728 mLayerHistory.setLayerProperties(id, properties);
729 }
730
chooseRefreshRateForContent(const surfaceflinger::frontend::LayerHierarchy * hierarchy,bool updateAttachedChoreographer)731 void Scheduler::chooseRefreshRateForContent(
732 const surfaceflinger::frontend::LayerHierarchy* hierarchy,
733 bool updateAttachedChoreographer) {
734 const auto selectorPtr = pacesetterSelectorPtr();
735 if (!selectorPtr->canSwitch()) return;
736
737 SFTRACE_CALL();
738
739 LayerHistory::Summary summary = mLayerHistory.summarize(*selectorPtr, systemTime());
740 applyPolicy(&Policy::contentRequirements, std::move(summary));
741
742 if (updateAttachedChoreographer) {
743 LOG_ALWAYS_FATAL_IF(!hierarchy);
744
745 // update the attached choreographers after we selected the render rate.
746 const ftl::Optional<FrameRateMode> modeOpt = [&] {
747 std::scoped_lock lock(mPolicyLock);
748 return mPolicy.modeOpt;
749 }();
750
751 if (modeOpt) {
752 updateAttachedChoreographers(*hierarchy, modeOpt->fps);
753 }
754 }
755 }
756
resetIdleTimer()757 void Scheduler::resetIdleTimer() {
758 pacesetterSelectorPtr()->resetIdleTimer();
759 }
760
onTouchHint()761 void Scheduler::onTouchHint() {
762 if (mTouchTimer) {
763 mTouchTimer->reset();
764 pacesetterSelectorPtr()->resetKernelIdleTimer();
765 }
766 }
767
setDisplayPowerMode(PhysicalDisplayId id,hal::PowerMode powerMode)768 void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMode) {
769 const bool isPacesetter = [this, id]() REQUIRES(kMainThreadContext) {
770 ftl::FakeGuard guard(mDisplayLock);
771 return id == mPacesetterDisplayId;
772 }();
773 if (isPacesetter) {
774 // TODO (b/255657128): This needs to be handled per display.
775 std::lock_guard<std::mutex> lock(mPolicyLock);
776 mPolicy.displayPowerMode = powerMode;
777 }
778 {
779 std::scoped_lock lock(mDisplayLock);
780
781 const auto displayOpt = mDisplays.get(id);
782 LOG_ALWAYS_FATAL_IF(!displayOpt);
783 auto& display = displayOpt->get();
784
785 display.powerMode = powerMode;
786 display.schedulePtr->getController().setDisplayPowerMode(powerMode);
787 }
788 if (!isPacesetter) return;
789
790 if (mDisplayPowerTimer) {
791 mDisplayPowerTimer->reset();
792 }
793
794 // Display Power event will boost the refresh rate to performance.
795 // Clear Layer History to get fresh FPS detection
796 mLayerHistory.clear();
797 }
798
getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const799 auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
800 -> ConstVsyncSchedulePtr {
801 std::scoped_lock lock(mDisplayLock);
802 return getVsyncScheduleLocked(idOpt);
803 }
804
getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const805 auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
806 -> ConstVsyncSchedulePtr {
807 ftl::FakeGuard guard(kMainThreadContext);
808
809 if (!idOpt) {
810 LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
811 idOpt = mPacesetterDisplayId;
812 }
813
814 const auto displayOpt = mDisplays.get(*idOpt);
815 if (!displayOpt) {
816 return nullptr;
817 }
818 return displayOpt->get().schedulePtr;
819 }
820
kernelIdleTimerCallback(TimerState state)821 void Scheduler::kernelIdleTimerCallback(TimerState state) {
822 SFTRACE_INT("ExpiredKernelIdleTimer", static_cast<int>(state));
823
824 // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
825 // magic number
826 const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getPeakFps();
827
828 constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz;
829 using namespace fps_approx_ops;
830
831 if (state == TimerState::Reset && refreshRate > FPS_THRESHOLD_FOR_KERNEL_TIMER) {
832 // If we're not in performance mode then the kernel timer shouldn't do
833 // anything, as the refresh rate during DPU power collapse will be the
834 // same.
835 resyncAllToHardwareVsync(true /* allowToEnable */);
836 } else if (state == TimerState::Expired && refreshRate <= FPS_THRESHOLD_FOR_KERNEL_TIMER) {
837 // Disable HW VSYNC if the timer expired, as we don't need it enabled if
838 // we're not pushing frames, and if we're in PERFORMANCE mode then we'll
839 // need to update the VsyncController model anyway.
840 std::scoped_lock lock(mDisplayLock);
841 ftl::FakeGuard guard(kMainThreadContext);
842 for (const auto& [_, display] : mDisplays) {
843 constexpr bool kDisallow = false;
844 display.schedulePtr->disableHardwareVsync(kDisallow);
845 }
846 }
847
848 mSchedulerCallback.kernelTimerChanged(state == TimerState::Expired);
849 }
850
idleTimerCallback(TimerState state)851 void Scheduler::idleTimerCallback(TimerState state) {
852 applyPolicy(&Policy::idleTimer, state);
853 SFTRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
854 }
855
touchTimerCallback(TimerState state)856 void Scheduler::touchTimerCallback(TimerState state) {
857 const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive;
858 // Touch event will boost the refresh rate to performance.
859 // Clear layer history to get fresh FPS detection.
860 // NOTE: Instead of checking all the layers, we should be checking the layer
861 // that is currently on top. b/142507166 will give us this capability.
862 if (applyPolicy(&Policy::touch, touch).touch) {
863 mLayerHistory.clear();
864 }
865 SFTRACE_INT("TouchState", static_cast<int>(touch));
866 }
867
displayPowerTimerCallback(TimerState state)868 void Scheduler::displayPowerTimerCallback(TimerState state) {
869 applyPolicy(&Policy::displayPowerTimer, state);
870 SFTRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
871 }
872
dump(utils::Dumper & dumper) const873 void Scheduler::dump(utils::Dumper& dumper) const {
874 using namespace std::string_view_literals;
875
876 {
877 utils::Dumper::Section section(dumper, "Features"sv);
878
879 for (Feature feature : ftl::enum_range<Feature>()) {
880 if (const auto flagOpt = ftl::flag_name(feature)) {
881 dumper.dump(flagOpt->substr(1), mFeatures.test(feature));
882 }
883 }
884 }
885 {
886 utils::Dumper::Section section(dumper, "Policy"sv);
887 {
888 std::scoped_lock lock(mDisplayLock);
889 ftl::FakeGuard guard(kMainThreadContext);
890 dumper.dump("pacesetterDisplayId"sv, mPacesetterDisplayId);
891 }
892 dumper.dump("layerHistory"sv, mLayerHistory.dump());
893 dumper.dump("touchTimer"sv, mTouchTimer.transform(&OneShotTimer::interval));
894 dumper.dump("displayPowerTimer"sv, mDisplayPowerTimer.transform(&OneShotTimer::interval));
895 }
896
897 mFrameRateOverrideMappings.dump(dumper);
898 dumper.eol();
899
900 mVsyncConfiguration->dump(dumper.out());
901 dumper.eol();
902
903 mRefreshRateStats->dump(dumper.out());
904 dumper.eol();
905
906 std::scoped_lock lock(mDisplayLock);
907 ftl::FakeGuard guard(kMainThreadContext);
908
909 for (const auto& [id, display] : mDisplays) {
910 utils::Dumper::Section
911 section(dumper,
912 id == mPacesetterDisplayId
913 ? ftl::Concat("Pacesetter Display ", id.value).c_str()
914 : ftl::Concat("Follower Display ", id.value).c_str());
915
916 display.selectorPtr->dump(dumper);
917 display.targeterPtr->dump(dumper);
918 dumper.eol();
919 }
920 }
921
dumpVsync(std::string & out) const922 void Scheduler::dumpVsync(std::string& out) const {
923 std::scoped_lock lock(mDisplayLock);
924 ftl::FakeGuard guard(kMainThreadContext);
925 if (mPacesetterDisplayId) {
926 base::StringAppendF(&out, "VsyncSchedule for pacesetter %s:\n",
927 to_string(*mPacesetterDisplayId).c_str());
928 getVsyncScheduleLocked()->dump(out);
929 }
930 for (auto& [id, display] : mDisplays) {
931 if (id == mPacesetterDisplayId) {
932 continue;
933 }
934 base::StringAppendF(&out, "VsyncSchedule for follower %s:\n", to_string(id).c_str());
935 display.schedulePtr->dump(out);
936 }
937 }
938
939 #pragma clang diagnostic push
940 #pragma clang diagnostic ignored "-Wunused-value" // b/369277774
updateFrameRateOverrides(GlobalSignals consideredSignals,Fps displayRefreshRate)941 void Scheduler::updateFrameRateOverrides(GlobalSignals consideredSignals, Fps displayRefreshRate) {
942 const bool changed = (std::scoped_lock(mPolicyLock),
943 updateFrameRateOverridesLocked(consideredSignals, displayRefreshRate));
944
945 if (changed) {
946 onFrameRateOverridesChanged();
947 }
948 }
949 #pragma clang diagnostic pop
950
updateFrameRateOverridesLocked(GlobalSignals consideredSignals,Fps displayRefreshRate)951 bool Scheduler::updateFrameRateOverridesLocked(GlobalSignals consideredSignals,
952 Fps displayRefreshRate) {
953 if (consideredSignals.idle) return false;
954
955 const auto frameRateOverrides =
956 pacesetterSelectorPtr()->getFrameRateOverrides(mPolicy.contentRequirements,
957 displayRefreshRate, consideredSignals);
958
959 // Note that RefreshRateSelector::supportsFrameRateOverrideByContent is checked when querying
960 // the FrameRateOverrideMappings rather than here.
961 return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
962 }
963
addBufferStuffedUids(BufferStuffingMap bufferStuffedUids)964 void Scheduler::addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) {
965 if (!mRenderEventThread) return;
966 mRenderEventThread->addBufferStuffedUids(std::move(bufferStuffedUids));
967 }
968
promotePacesetterDisplay(PhysicalDisplayId pacesetterId,PromotionParams params)969 void Scheduler::promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams params) {
970 std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
971 {
972 std::scoped_lock lock(mDisplayLock);
973 pacesetterVsyncSchedule = promotePacesetterDisplayLocked(pacesetterId, params);
974 }
975
976 applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
977 }
978
promotePacesetterDisplayLocked(PhysicalDisplayId pacesetterId,PromotionParams params)979 std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
980 PhysicalDisplayId pacesetterId, PromotionParams params) {
981 // TODO: b/241286431 - Choose the pacesetter among mDisplays.
982 mPacesetterDisplayId = pacesetterId;
983 ALOGI("Display %s is the pacesetter", to_string(pacesetterId).c_str());
984
985 std::shared_ptr<VsyncSchedule> newVsyncSchedulePtr;
986 if (const auto pacesetterOpt = pacesetterDisplayLocked()) {
987 const Display& pacesetter = *pacesetterOpt;
988
989 if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) {
990 pacesetter.selectorPtr->setIdleTimerCallbacks(
991 {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
992 .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
993 .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
994 .onExpired =
995 [this] { kernelIdleTimerCallback(TimerState::Expired); }},
996 .vrr = {.onReset = [this] { mSchedulerCallback.vrrDisplayIdle(false); },
997 .onExpired = [this] { mSchedulerCallback.vrrDisplayIdle(true); }}});
998
999 pacesetter.selectorPtr->startIdleTimer();
1000 }
1001
1002 newVsyncSchedulePtr = pacesetter.schedulePtr;
1003
1004 constexpr bool kForce = true;
1005 newVsyncSchedulePtr->onDisplayModeChanged(pacesetter.selectorPtr->getActiveMode().modePtr,
1006 kForce);
1007 }
1008 return newVsyncSchedulePtr;
1009 }
1010
applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule)1011 void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
1012 onNewVsyncSchedule(vsyncSchedule->getDispatch());
1013
1014 if (hasEventThreads()) {
1015 eventThreadFor(Cycle::Render).onNewVsyncSchedule(vsyncSchedule);
1016 eventThreadFor(Cycle::LastComposite).onNewVsyncSchedule(vsyncSchedule);
1017 }
1018 }
1019
demotePacesetterDisplay(PromotionParams params)1020 void Scheduler::demotePacesetterDisplay(PromotionParams params) {
1021 if (!FlagManager::getInstance().connected_display() || params.toggleIdleTimer) {
1022 // No need to lock for reads on kMainThreadContext.
1023 if (const auto pacesetterPtr =
1024 FTL_FAKE_GUARD(mDisplayLock, pacesetterSelectorPtrLocked())) {
1025 pacesetterPtr->stopIdleTimer();
1026 pacesetterPtr->clearIdleTimerCallbacks();
1027 }
1028 }
1029
1030 // Clear state that depends on the pacesetter's RefreshRateSelector.
1031 std::scoped_lock lock(mPolicyLock);
1032 mPolicy = {};
1033 }
1034
updateAttachedChoreographersFrameRate(const surfaceflinger::frontend::RequestedLayerState & layer,Fps fps)1035 void Scheduler::updateAttachedChoreographersFrameRate(
1036 const surfaceflinger::frontend::RequestedLayerState& layer, Fps fps) {
1037 std::scoped_lock lock(mChoreographerLock);
1038
1039 const auto layerId = static_cast<int32_t>(layer.id);
1040 const auto choreographers = mAttachedChoreographers.find(layerId);
1041 if (choreographers == mAttachedChoreographers.end()) {
1042 return;
1043 }
1044
1045 auto& layerChoreographers = choreographers->second;
1046
1047 layerChoreographers.frameRate = fps;
1048 SFTRACE_FORMAT_INSTANT("%s: %s for %s", __func__, to_string(fps).c_str(), layer.name.c_str());
1049 ALOGV("%s: %s for %s", __func__, to_string(fps).c_str(), layer.name.c_str());
1050
1051 auto it = layerChoreographers.connections.begin();
1052 while (it != layerChoreographers.connections.end()) {
1053 sp<EventThreadConnection> choreographerConnection = it->promote();
1054 if (choreographerConnection) {
1055 choreographerConnection->frameRate = fps;
1056 it++;
1057 } else {
1058 it = choreographers->second.connections.erase(it);
1059 }
1060 }
1061
1062 if (layerChoreographers.connections.empty()) {
1063 mAttachedChoreographers.erase(choreographers);
1064 }
1065 }
1066
updateAttachedChoreographersInternal(const surfaceflinger::frontend::LayerHierarchy & layerHierarchy,Fps displayRefreshRate,int parentDivisor)1067 int Scheduler::updateAttachedChoreographersInternal(
1068 const surfaceflinger::frontend::LayerHierarchy& layerHierarchy, Fps displayRefreshRate,
1069 int parentDivisor) {
1070 const char* name = layerHierarchy.getLayer() ? layerHierarchy.getLayer()->name.c_str() : "Root";
1071
1072 int divisor = 0;
1073 if (layerHierarchy.getLayer()) {
1074 const auto frameRateCompatibility = layerHierarchy.getLayer()->frameRateCompatibility;
1075 const auto frameRate = Fps::fromValue(layerHierarchy.getLayer()->frameRate);
1076 ALOGV("%s: %s frameRate %s parentDivisor=%d", __func__, name, to_string(frameRate).c_str(),
1077 parentDivisor);
1078
1079 if (frameRate.isValid()) {
1080 if (frameRateCompatibility == ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE ||
1081 frameRateCompatibility == ANATIVEWINDOW_FRAME_RATE_EXACT) {
1082 // Since this layer wants an exact match, we would only set a frame rate if the
1083 // desired rate is a divisor of the display refresh rate.
1084 divisor = RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate);
1085 } else if (frameRateCompatibility == ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT) {
1086 // find the closest frame rate divisor for the desired frame rate.
1087 divisor = static_cast<int>(
1088 std::round(displayRefreshRate.getValue() / frameRate.getValue()));
1089 }
1090 }
1091 }
1092
1093 // We start by traversing the children, updating their choreographers, and getting back the
1094 // aggregated frame rate.
1095 int childrenDivisor = 0;
1096 for (const auto& [child, _] : layerHierarchy.mChildren) {
1097 LOG_ALWAYS_FATAL_IF(child == nullptr || child->getLayer() == nullptr);
1098
1099 ALOGV("%s: %s traversing child %s", __func__, name, child->getLayer()->name.c_str());
1100
1101 const int childDivisor =
1102 updateAttachedChoreographersInternal(*child, displayRefreshRate, divisor);
1103 childrenDivisor = childrenDivisor > 0 ? childrenDivisor : childDivisor;
1104 if (childDivisor > 0) {
1105 childrenDivisor = std::gcd(childrenDivisor, childDivisor);
1106 }
1107 ALOGV("%s: %s childrenDivisor=%d", __func__, name, childrenDivisor);
1108 }
1109
1110 ALOGV("%s: %s divisor=%d", __func__, name, divisor);
1111
1112 // If there is no explicit vote for this layer. Use the children's vote if exists
1113 divisor = (divisor == 0) ? childrenDivisor : divisor;
1114 ALOGV("%s: %s divisor=%d with children", __func__, name, divisor);
1115
1116 // If there is no explicit vote for this layer or its children, Use the parent vote if exists
1117 divisor = (divisor == 0) ? parentDivisor : divisor;
1118 ALOGV("%s: %s divisor=%d with parent", __func__, name, divisor);
1119
1120 if (layerHierarchy.getLayer()) {
1121 Fps fps = divisor > 1 ? displayRefreshRate / (unsigned int)divisor : Fps();
1122 updateAttachedChoreographersFrameRate(*layerHierarchy.getLayer(), fps);
1123 }
1124
1125 return divisor;
1126 }
1127
updateAttachedChoreographers(const surfaceflinger::frontend::LayerHierarchy & layerHierarchy,Fps displayRefreshRate)1128 void Scheduler::updateAttachedChoreographers(
1129 const surfaceflinger::frontend::LayerHierarchy& layerHierarchy, Fps displayRefreshRate) {
1130 SFTRACE_CALL();
1131 updateAttachedChoreographersInternal(layerHierarchy, displayRefreshRate, 0);
1132 }
1133
1134 template <typename S, typename T>
applyPolicy(S Policy::* statePtr,T && newState)1135 auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals {
1136 SFTRACE_CALL();
1137 std::vector<display::DisplayModeRequest> modeRequests;
1138 GlobalSignals consideredSignals;
1139
1140 bool refreshRateChanged = false;
1141 bool frameRateOverridesChanged;
1142
1143 {
1144 std::scoped_lock lock(mPolicyLock);
1145
1146 auto& currentState = mPolicy.*statePtr;
1147 if (currentState == newState) return {};
1148 currentState = std::forward<T>(newState);
1149
1150 DisplayModeChoiceMap modeChoices;
1151 ftl::Optional<FrameRateMode> modeOpt;
1152 {
1153 std::scoped_lock lock(mDisplayLock);
1154 ftl::FakeGuard guard(kMainThreadContext);
1155
1156 modeChoices = chooseDisplayModes();
1157
1158 // TODO(b/240743786): The pacesetter display's mode must change for any
1159 // DisplayModeRequest to go through. Fix this by tracking per-display Scheduler::Policy
1160 // and timers.
1161 std::tie(modeOpt, consideredSignals) =
1162 modeChoices.get(*mPacesetterDisplayId)
1163 .transform([](const DisplayModeChoice& choice) {
1164 return std::make_pair(choice.mode, choice.consideredSignals);
1165 })
1166 .value();
1167 }
1168
1169 modeRequests.reserve(modeChoices.size());
1170 for (auto& [id, choice] : modeChoices) {
1171 modeRequests.emplace_back(
1172 display::DisplayModeRequest{.mode = std::move(choice.mode),
1173 .emitEvent = choice.consideredSignals
1174 .shouldEmitEvent()});
1175 }
1176
1177 if (!FlagManager::getInstance().vrr_bugfix_dropped_frame()) {
1178 frameRateOverridesChanged =
1179 updateFrameRateOverridesLocked(consideredSignals, modeOpt->fps);
1180 }
1181 if (mPolicy.modeOpt != modeOpt) {
1182 mPolicy.modeOpt = modeOpt;
1183 refreshRateChanged = true;
1184 } else if (consideredSignals.shouldEmitEvent()) {
1185 // The mode did not change, but we may need to emit if DisplayModeRequest::emitEvent was
1186 // previously false.
1187 emitModeChangeIfNeeded();
1188 }
1189 }
1190 if (refreshRateChanged) {
1191 mSchedulerCallback.requestDisplayModes(std::move(modeRequests));
1192 }
1193
1194 if (FlagManager::getInstance().vrr_bugfix_dropped_frame()) {
1195 std::scoped_lock lock(mPolicyLock);
1196 frameRateOverridesChanged =
1197 updateFrameRateOverridesLocked(consideredSignals, mPolicy.modeOpt->fps);
1198 }
1199 if (frameRateOverridesChanged) {
1200 onFrameRateOverridesChanged();
1201 }
1202 return consideredSignals;
1203 }
1204
chooseDisplayModes() const1205 auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {
1206 SFTRACE_CALL();
1207
1208 DisplayModeChoiceMap modeChoices;
1209 const auto globalSignals = makeGlobalSignals();
1210
1211 const Fps pacesetterFps = [&]() REQUIRES(mPolicyLock, mDisplayLock, kMainThreadContext) {
1212 auto rankedFrameRates =
1213 pacesetterSelectorPtrLocked()->getRankedFrameRates(mPolicy.contentRequirements,
1214 globalSignals);
1215
1216 const Fps pacesetterFps = rankedFrameRates.ranking.front().frameRateMode.fps;
1217
1218 modeChoices.try_emplace(*mPacesetterDisplayId,
1219 DisplayModeChoice::from(std::move(rankedFrameRates)));
1220 return pacesetterFps;
1221 }();
1222
1223 // Choose a mode for powered-on follower displays.
1224 for (const auto& [id, display] : mDisplays) {
1225 if (id == *mPacesetterDisplayId) continue;
1226 if (display.powerMode != hal::PowerMode::ON) continue;
1227
1228 auto rankedFrameRates =
1229 display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals,
1230 pacesetterFps);
1231
1232 modeChoices.try_emplace(id, DisplayModeChoice::from(std::move(rankedFrameRates)));
1233 }
1234
1235 return modeChoices;
1236 }
1237
makeGlobalSignals() const1238 GlobalSignals Scheduler::makeGlobalSignals() const {
1239 const bool powerOnImminent = mDisplayPowerTimer &&
1240 (mPolicy.displayPowerMode != hal::PowerMode::ON ||
1241 mPolicy.displayPowerTimer == TimerState::Reset);
1242
1243 return {.touch = mTouchTimer && mPolicy.touch == TouchState::Active,
1244 .idle = mPolicy.idleTimer == TimerState::Expired,
1245 .powerOnImminent = powerOnImminent};
1246 }
1247
getPreferredDisplayMode()1248 FrameRateMode Scheduler::getPreferredDisplayMode() {
1249 std::lock_guard<std::mutex> lock(mPolicyLock);
1250 const auto frameRateMode =
1251 pacesetterSelectorPtr()
1252 ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals())
1253 .ranking.front()
1254 .frameRateMode;
1255
1256 // Make sure the stored mode is up to date.
1257 mPolicy.modeOpt = frameRateMode;
1258
1259 return frameRateMode;
1260 }
1261
onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline & timeline)1262 void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
1263 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
1264 mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);
1265
1266 const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
1267 if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
1268 mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
1269 }
1270 }
1271
onCompositionPresented(nsecs_t presentTime)1272 bool Scheduler::onCompositionPresented(nsecs_t presentTime) {
1273 std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
1274 if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
1275 if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
1276 // We need to composite again as refreshTimeNanos is still in the future.
1277 return true;
1278 }
1279
1280 mLastVsyncPeriodChangeTimeline->refreshRequired = false;
1281 }
1282 return false;
1283 }
1284
onActiveDisplayAreaChanged(uint32_t displayArea)1285 void Scheduler::onActiveDisplayAreaChanged(uint32_t displayArea) {
1286 mLayerHistory.setDisplayArea(displayArea);
1287 }
1288
setGameModeFrameRateForUid(FrameRateOverride frameRateOverride)1289 void Scheduler::setGameModeFrameRateForUid(FrameRateOverride frameRateOverride) {
1290 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
1291 return;
1292 }
1293
1294 if (FlagManager::getInstance().game_default_frame_rate()) {
1295 // update the frame rate override mapping in LayerHistory
1296 mLayerHistory.updateGameModeFrameRateOverride(frameRateOverride);
1297 } else {
1298 mFrameRateOverrideMappings.setGameModeRefreshRateForUid(frameRateOverride);
1299 }
1300
1301 onFrameRateOverridesChanged();
1302 }
1303
setGameDefaultFrameRateForUid(FrameRateOverride frameRateOverride)1304 void Scheduler::setGameDefaultFrameRateForUid(FrameRateOverride frameRateOverride) {
1305 if (!FlagManager::getInstance().game_default_frame_rate() ||
1306 (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f)) {
1307 return;
1308 }
1309
1310 // update the frame rate override mapping in LayerHistory
1311 mLayerHistory.updateGameDefaultFrameRateOverride(frameRateOverride);
1312 }
1313
setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride)1314 void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) {
1315 if (frameRateOverride.frameRateHz > 0.f && frameRateOverride.frameRateHz < 1.f) {
1316 return;
1317 }
1318
1319 mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
1320 onFrameRateOverridesChanged();
1321 }
1322
updateSmallAreaDetection(std::vector<std::pair<int32_t,float>> & uidThresholdMappings)1323 void Scheduler::updateSmallAreaDetection(
1324 std::vector<std::pair<int32_t, float>>& uidThresholdMappings) {
1325 mSmallAreaDetectionAllowMappings.update(uidThresholdMappings);
1326 }
1327
setSmallAreaDetectionThreshold(int32_t appId,float threshold)1328 void Scheduler::setSmallAreaDetectionThreshold(int32_t appId, float threshold) {
1329 mSmallAreaDetectionAllowMappings.setThresholdForAppId(appId, threshold);
1330 }
1331
isSmallDirtyArea(int32_t appId,uint32_t dirtyArea)1332 bool Scheduler::isSmallDirtyArea(int32_t appId, uint32_t dirtyArea) {
1333 std::optional<float> oThreshold = mSmallAreaDetectionAllowMappings.getThresholdForAppId(appId);
1334 if (oThreshold) {
1335 return mLayerHistory.isSmallDirtyArea(dirtyArea, oThreshold.value());
1336 }
1337 return false;
1338 }
1339
1340 } // namespace android::scheduler
1341