xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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