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