• 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 #pragma once
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <functional>
22 #include <future>
23 #include <memory>
24 #include <mutex>
25 #include <unordered_map>
26 #include <utility>
27 
28 // TODO(b/129481165): remove the #pragma below and fix conversion issues
29 #pragma clang diagnostic push
30 #pragma clang diagnostic ignored "-Wconversion"
31 #pragma clang diagnostic ignored "-Wextra"
32 #include <ui/GraphicTypes.h>
33 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
34 
35 #include <ftl/fake_guard.h>
36 #include <ftl/non_null.h>
37 #include <ftl/optional.h>
38 #include <scheduler/Features.h>
39 #include <scheduler/FrameRateMode.h>
40 #include <scheduler/FrameTargeter.h>
41 #include <scheduler/Time.h>
42 #include <scheduler/VsyncConfig.h>
43 #include <ui/DisplayId.h>
44 #include <ui/DisplayMap.h>
45 
46 #include "DisplayHardware/DisplayMode.h"
47 #include "EventThread.h"
48 #include "FrameRateOverrideMappings.h"
49 #include "ISchedulerCallback.h"
50 #include "LayerHistory.h"
51 #include "MessageQueue.h"
52 #include "OneShotTimer.h"
53 #include "RefreshRateSelector.h"
54 #include "SmallAreaDetectionAllowMappings.h"
55 #include "Utils/Dumper.h"
56 #include "VsyncConfiguration.h"
57 #include "VsyncModulator.h"
58 
59 #include <FrontEnd/LayerHierarchy.h>
60 
61 namespace android {
62 
63 class FenceTime;
64 class TimeStats;
65 
66 namespace frametimeline {
67 class TokenManager;
68 } // namespace frametimeline
69 
70 namespace surfaceflinger {
71 class Factory;
72 } // namespace surfaceflinger
73 
74 namespace scheduler {
75 
76 using GlobalSignals = RefreshRateSelector::GlobalSignals;
77 
78 class RefreshRateStats;
79 class VsyncConfiguration;
80 class VsyncSchedule;
81 
82 enum class Cycle {
83     Render,       // Surface rendering.
84     LastComposite // Ahead of display compositing by one refresh period.
85 };
86 
87 class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
88     using Impl = android::impl::MessageQueue;
89 
90 public:
91     Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, surfaceflinger::Factory&,
92               Fps activeRefreshRate, TimeStats&);
93     virtual ~Scheduler();
94 
95     void startTimers();
96 
97     // TODO: b/241285191 - Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
98     void setPacesetterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext)
99             EXCLUDES(mDisplayLock, mVsyncConfigLock);
100 
101     using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
102 
103     using ConstVsyncSchedulePtr = std::shared_ptr<const VsyncSchedule>;
104     using VsyncSchedulePtr = std::shared_ptr<VsyncSchedule>;
105 
106     // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the
107     // active display is never unregistered, since hotplug disconnect never happens for activatable
108     // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary
109     // display.
110     // TODO: b/255635821 - Remove active display parameters.
111     void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr,
112                          PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext)
113             EXCLUDES(mDisplayLock);
114     void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId)
115             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
116 
117     void run();
118 
119     void initVsync(frametimeline::TokenManager&, std::chrono::nanoseconds workDuration);
120 
121     using Impl::setDuration;
122 
123     using Impl::getScheduledFrameResult;
124     using Impl::scheduleConfigure;
125     using Impl::scheduleFrame;
126 
127     // Schedule an asynchronous or synchronous task on the main thread.
128     template <typename F, typename T = std::invoke_result_t<F>>
schedule(F && f)129     [[nodiscard]] std::future<T> schedule(F&& f) {
130         auto [task, future] = makeTask(std::move(f));
131         postMessage(std::move(task));
132         return std::move(future);
133     }
134 
135     template <typename F, typename T = std::invoke_result_t<F>>
scheduleDelayed(F && f,nsecs_t uptimeDelay)136     [[nodiscard]] std::future<T> scheduleDelayed(F&& f, nsecs_t uptimeDelay) {
137         auto [task, future] = makeTask(std::move(f));
138         postMessageDelayed(std::move(task), uptimeDelay);
139         return std::move(future);
140     }
141 
142     void createEventThread(Cycle, frametimeline::TokenManager*,
143                            std::chrono::nanoseconds workDuration,
144                            std::chrono::nanoseconds readyDuration);
145 
146     sp<IDisplayEventConnection> createDisplayEventConnection(
147             Cycle, EventRegistrationFlags eventRegistration = {},
148             const sp<IBinder>& layerHandle = nullptr) EXCLUDES(mChoreographerLock);
149 
150     enum class Hotplug { Connected, Disconnected };
151     void dispatchHotplug(PhysicalDisplayId, Hotplug);
152 
153     void dispatchHotplugError(int32_t errorCode);
154 
155     // Returns true if the PhysicalDisplayId is the pacesetter.
156     bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&,
157                               bool clearContentRequirements) EXCLUDES(mPolicyLock);
158 
159     void onDisplayModeRejected(PhysicalDisplayId, DisplayModeId);
160 
161     void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
162     void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext);
163 
164     void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);
165 
166     // Modifies work duration in the event thread.
167     void setDuration(Cycle, std::chrono::nanoseconds workDuration,
168                      std::chrono::nanoseconds readyDuration);
169 
vsyncModulator()170     VsyncModulator& vsyncModulator() { return *mVsyncModulator; }
171 
172     // In some cases, we should only modulate for the pacesetter display. In those
173     // cases, the caller should pass in the relevant display, and the method
174     // will no-op if it's not the pacesetter. Other cases are not specific to a
175     // display.
176     template <typename... Args,
177               typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
modulateVsync(std::optional<PhysicalDisplayId> id,Handler handler,Args...args)178     void modulateVsync(std::optional<PhysicalDisplayId> id, Handler handler, Args... args) {
179         if (id) {
180             std::scoped_lock lock(mDisplayLock);
181             ftl::FakeGuard guard(kMainThreadContext);
182             if (id != mPacesetterDisplayId) {
183                 return;
184             }
185         }
186 
187         if (const auto config = (*mVsyncModulator.*handler)(args...)) {
188             setVsyncConfig(*config, getPacesetterVsyncPeriod());
189         }
190     }
191 
192     void updatePhaseConfiguration(PhysicalDisplayId, Fps) EXCLUDES(mVsyncConfigLock);
193     void reloadPhaseConfiguration(Fps, Duration minSfDuration, Duration maxSfDuration,
194                                   Duration appDuration) EXCLUDES(mVsyncConfigLock);
195 
getCurrentVsyncConfigs()196     VsyncConfigSet getCurrentVsyncConfigs() const EXCLUDES(mVsyncConfigLock) {
197         std::scoped_lock lock{mVsyncConfigLock};
198         return mVsyncConfiguration->getCurrentConfigs();
199     }
200 
getVsyncConfigsForRefreshRate(Fps refreshRate)201     VsyncConfigSet getVsyncConfigsForRefreshRate(Fps refreshRate) const EXCLUDES(mVsyncConfigLock) {
202         std::scoped_lock lock{mVsyncConfigLock};
203         return mVsyncConfiguration->getConfigsForRefreshRate(refreshRate);
204     }
205 
206     // Sets the render rate for the scheduler to run at.
207     void setRenderRate(PhysicalDisplayId, Fps, bool applyImmediately);
208 
209     void enableHardwareVsync(PhysicalDisplayId) REQUIRES(kMainThreadContext);
210     void disableHardwareVsync(PhysicalDisplayId, bool disallow) REQUIRES(kMainThreadContext);
211 
212     // Resyncs the scheduler to hardware vsync.
213     // If allowToEnable is true, then hardware vsync will be turned on.
214     // Otherwise, if hardware vsync is not already enabled then this method will
215     // no-op.
216     // If modePtr is nullopt, use the active display mode.
217     void resyncToHardwareVsync(PhysicalDisplayId id, bool allowToEnable,
EXCLUDES(mDisplayLock)218                                DisplayModePtr modePtr = nullptr) EXCLUDES(mDisplayLock) {
219         std::scoped_lock lock(mDisplayLock);
220         ftl::FakeGuard guard(kMainThreadContext);
221         resyncToHardwareVsyncLocked(id, allowToEnable, modePtr);
222     }
forceNextResync()223     void forceNextResync() { mLastResyncTime = 0; }
224 
225     // Passes a vsync sample to VsyncController. Returns true if
226     // VsyncController detected that the vsync period changed and false
227     // otherwise.
228     bool addResyncSample(PhysicalDisplayId, nsecs_t timestamp,
229                          std::optional<nsecs_t> hwcVsyncPeriod);
230     void addPresentFence(PhysicalDisplayId, std::shared_ptr<FenceTime>)
231             REQUIRES(kMainThreadContext);
232 
233     // Layers are registered on creation, and unregistered when the weak reference expires.
234     void registerLayer(Layer*, FrameRateCompatibility);
235     void recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime,
236                             nsecs_t now, LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock);
237     void setModeChangePending(bool pending);
238     void setDefaultFrameRateCompatibility(int32_t id, scheduler::FrameRateCompatibility);
239     void setLayerProperties(int32_t id, const LayerProps&);
240     void deregisterLayer(Layer*);
241     void onLayerDestroyed(Layer*) EXCLUDES(mChoreographerLock);
242 
243     // Detects content using layer history, and selects a matching refresh rate.
244     void chooseRefreshRateForContent(const surfaceflinger::frontend::LayerHierarchy*,
245                                      bool updateAttachedChoreographer) EXCLUDES(mDisplayLock);
246 
247     void resetIdleTimer();
248 
249     // Indicates that touch interaction is taking place.
250     void onTouchHint();
251 
252     void setDisplayPowerMode(PhysicalDisplayId, hal::PowerMode) REQUIRES(kMainThreadContext);
253 
254     // TODO(b/255635821): Track this per display.
255     void setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode) REQUIRES(kMainThreadContext);
256 
257     ConstVsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> = std::nullopt) const
258             EXCLUDES(mDisplayLock);
259 
260     VsyncSchedulePtr getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
EXCLUDES(mDisplayLock)261             EXCLUDES(mDisplayLock) {
262         return std::const_pointer_cast<VsyncSchedule>(std::as_const(*this).getVsyncSchedule(idOpt));
263     }
264 
expectedPresentTimeForPacesetter()265     TimePoint expectedPresentTimeForPacesetter() const EXCLUDES(mDisplayLock) {
266         std::scoped_lock lock(mDisplayLock);
267         return pacesetterDisplayLocked()
268                 .transform([](const Display& display) {
269                     return display.targeterPtr->target().expectedPresentTime();
270                 })
271                 .value_or(TimePoint());
272     }
273 
274     // Returns true if a given vsync timestamp is considered valid vsync
275     // for a given uid
276     bool isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const;
277 
278     bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const;
279 
280     void dump(utils::Dumper&) const EXCLUDES(mVsyncConfigLock);
281     void dump(Cycle, std::string&) const;
282     void dumpVsync(std::string&) const EXCLUDES(mDisplayLock);
283 
284     // Returns the preferred refresh rate and frame rate for the pacesetter display.
285     FrameRateMode getPreferredDisplayMode();
286 
287     // Notifies the scheduler about a refresh rate timeline change.
288     void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline);
289 
290     // Notifies the scheduler once the composition is presented. Returns if recomposite is needed.
291     bool onCompositionPresented(nsecs_t presentTime);
292 
293     // Notifies the scheduler when the display size has changed. Called from SF's main thread
294     void onActiveDisplayAreaChanged(uint32_t displayArea);
295 
296     // Stores the preferred refresh rate that an app should run at.
297     // FrameRateOverride.refreshRateHz == 0 means no preference.
298     void setPreferredRefreshRateForUid(FrameRateOverride);
299 
300     // Stores the frame rate override that a game should run at set by game interventions.
301     // FrameRateOverride.refreshRateHz == 0 means no preference.
302     void setGameModeFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
303 
304     // Stores the frame rate override that a game should run rat set by default game frame rate.
305     // FrameRateOverride.refreshRateHz == 0 means no preference, game default game frame rate is not
306     // enabled.
307     //
308     // "ro.surface_flinger.game_default_frame_rate_override" sets the frame rate value,
309     // "persist.graphics.game_default_frame_rate.enabled" controls whether this feature is enabled.
310     void setGameDefaultFrameRateForUid(FrameRateOverride) EXCLUDES(mDisplayLock);
311 
312     void updateSmallAreaDetection(std::vector<std::pair<int32_t, float>>& uidThresholdMappings);
313 
314     void setSmallAreaDetectionThreshold(int32_t appId, float threshold);
315 
316     // Returns true if the dirty area is less than threshold.
317     bool isSmallDirtyArea(int32_t appId, uint32_t dirtyArea);
318 
319     // Retrieves the overridden refresh rate for a given uid.
320     std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock);
321 
getPacesetterVsyncPeriod()322     Period getPacesetterVsyncPeriod() const EXCLUDES(mDisplayLock) {
323         return pacesetterSelectorPtr()->getActiveMode().fps.getPeriod();
324     }
325 
getPacesetterRefreshRate()326     Fps getPacesetterRefreshRate() const EXCLUDES(mDisplayLock) {
327         return pacesetterSelectorPtr()->getActiveMode().fps;
328     }
329 
330     Fps getNextFrameInterval(PhysicalDisplayId, TimePoint currentExpectedPresentTime) const
331             EXCLUDES(mDisplayLock);
332 
333     // Returns the framerate of the layer with the given sequence ID
getLayerFramerate(nsecs_t now,int32_t id)334     float getLayerFramerate(nsecs_t now, int32_t id) const {
335         return mLayerHistory.getLayerFramerate(now, id);
336     }
337 
338     void updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) EXCLUDES(mPolicyLock);
339 
340     // Returns true if the small dirty detection is enabled for the appId.
supportSmallDirtyDetection(int32_t appId)341     bool supportSmallDirtyDetection(int32_t appId) {
342         return mFeatures.test(Feature::kSmallDirtyContentDetection) &&
343                 mSmallAreaDetectionAllowMappings.getThresholdForAppId(appId).has_value();
344     }
345 
346     // Injects a delay that is a fraction of the predicted frame duration for the next frame.
injectPacesetterDelay(float frameDurationFraction)347     void injectPacesetterDelay(float frameDurationFraction) REQUIRES(kMainThreadContext) {
348         mPacesetterFrameDurationFractionToSkip = frameDurationFraction;
349     }
350 
setDebugPresentDelay(TimePoint delay)351     void setDebugPresentDelay(TimePoint delay) { mDebugPresentDelay = delay; }
352 
353 private:
354     friend class TestableScheduler;
355 
356     enum class ContentDetectionState { Off, On };
357     enum class TimerState { Reset, Expired };
358     enum class TouchState { Inactive, Active };
359 
360     // impl::MessageQueue overrides:
361     void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override
362             REQUIRES(kMainThreadContext, mDisplayLock) EXCLUDES(mVsyncConfigLock);
363 
364     // Used to skip event dispatch before EventThread creation during boot.
365     // TODO: b/241285191 - Reorder Scheduler initialization to avoid this.
hasEventThreads()366     bool hasEventThreads() const {
367         return CC_LIKELY(
368                 mRenderEventThread &&
369                 (FlagManager::getInstance().deprecate_vsync_sf() || mLastCompositeEventThread));
370     }
371 
eventThreadFor(Cycle cycle)372     EventThread& eventThreadFor(Cycle cycle) const {
373         return *(cycle == Cycle::Render ? mRenderEventThread : mLastCompositeEventThread);
374     }
375 
376     // Update feature state machine to given state when corresponding timer resets or expires.
377     void kernelIdleTimerCallback(TimerState) EXCLUDES(mDisplayLock);
378     void idleTimerCallback(TimerState);
379     void touchTimerCallback(TimerState);
380     void displayPowerTimerCallback(TimerState);
381 
382     // VsyncSchedule delegate.
383     void onHardwareVsyncRequest(PhysicalDisplayId, bool enable);
384 
385     void resyncToHardwareVsyncLocked(PhysicalDisplayId, bool allowToEnable,
386                                      DisplayModePtr modePtr = nullptr)
387             REQUIRES(kMainThreadContext, mDisplayLock);
388     void resyncAllToHardwareVsync(bool allowToEnable) EXCLUDES(mDisplayLock);
389     void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
390 
391     // TODO: b/241286431 - Remove this option, which assumes that the pacesetter does not change
392     // when a (secondary) display is registered or unregistered. In the short term, this avoids
393     // a deadlock where the main thread joins with the timer thread as the timer thread waits to
394     // lock a mutex held by the main thread.
395     struct PromotionParams {
396         // Whether to stop and start the idle timer.
397         bool toggleIdleTimer;
398     };
399 
400     void promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams)
401             REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
402 
403     // Changes to the displays (e.g. registering and unregistering) must be made
404     // while mDisplayLock is locked, and the new pacesetter then must be promoted while
405     // mDisplayLock is still locked. However, a new pacesetter means that
406     // MessageQueue and EventThread need to use the new pacesetter's
407     // VsyncSchedule, and this must happen while mDisplayLock is *not* locked,
408     // or else we may deadlock with EventThread.
409     std::shared_ptr<VsyncSchedule> promotePacesetterDisplayLocked(PhysicalDisplayId pacesetterId,
410                                                                   PromotionParams)
411             REQUIRES(kMainThreadContext, mDisplayLock);
412     void applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule>) EXCLUDES(mDisplayLock);
413 
414     // If toggleIdleTimer is true, the calling thread blocks until the pacesetter's idle timer
415     // thread exits, in which case mDisplayLock must not be locked by the caller to avoid deadlock,
416     // since the timer thread locks it before exit.
417     void demotePacesetterDisplay(PromotionParams) REQUIRES(kMainThreadContext)
418             EXCLUDES(mDisplayLock, mPolicyLock);
419 
420     void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr,
421                                  PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext)
422             EXCLUDES(mDisplayLock);
423 
424     struct Policy;
425 
426     // Sets the S state of the policy to the T value under mPolicyLock, and chooses a display mode
427     // that fulfills the new policy if the state changed. Returns the signals that were considered.
428     template <typename S, typename T>
429     GlobalSignals applyPolicy(S Policy::*, T&&) EXCLUDES(mPolicyLock);
430 
431     struct DisplayModeChoice {
DisplayModeChoiceDisplayModeChoice432         DisplayModeChoice(FrameRateMode mode, GlobalSignals consideredSignals)
433               : mode(std::move(mode)), consideredSignals(consideredSignals) {}
434 
fromDisplayModeChoice435         static DisplayModeChoice from(RefreshRateSelector::RankedFrameRates rankedFrameRates) {
436             return {rankedFrameRates.ranking.front().frameRateMode,
437                     rankedFrameRates.consideredSignals};
438         }
439 
440         FrameRateMode mode;
441         GlobalSignals consideredSignals;
442 
443         bool operator==(const DisplayModeChoice& other) const {
444             return mode == other.mode && consideredSignals == other.consideredSignals;
445         }
446 
447         // For tests.
448         friend std::ostream& operator<<(std::ostream& stream, const DisplayModeChoice& choice) {
449             return stream << '{' << to_string(*choice.mode.modePtr) << " considering "
450                           << choice.consideredSignals.toString().c_str() << '}';
451         }
452     };
453 
454     using DisplayModeChoiceMap = ui::PhysicalDisplayMap<PhysicalDisplayId, DisplayModeChoice>;
455 
456     // See mDisplayLock for thread safety.
457     DisplayModeChoiceMap chooseDisplayModes() const
458             REQUIRES(mPolicyLock, mDisplayLock, kMainThreadContext);
459 
460     GlobalSignals makeGlobalSignals() const REQUIRES(mPolicyLock);
461 
462     bool updateFrameRateOverridesLocked(GlobalSignals, Fps displayRefreshRate)
463             REQUIRES(mPolicyLock);
464 
465     void onFrameRateOverridesChanged();
466 
467     void updateAttachedChoreographers(const surfaceflinger::frontend::LayerHierarchy&,
468                                       Fps displayRefreshRate);
469     int updateAttachedChoreographersInternal(const surfaceflinger::frontend::LayerHierarchy&,
470                                              Fps displayRefreshRate, int parentDivisor);
471     void updateAttachedChoreographersFrameRate(const surfaceflinger::frontend::RequestedLayerState&,
472                                                Fps fps) EXCLUDES(mChoreographerLock);
473 
474     void emitModeChangeIfNeeded() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock);
475 
476     // IEventThreadCallback overrides
477     bool throttleVsync(TimePoint, uid_t) override;
478     // Get frame interval
479     Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
480     void resync() override EXCLUDES(mDisplayLock);
481     void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);
482 
483     std::unique_ptr<EventThread> mRenderEventThread;
484     std::unique_ptr<EventThread> mLastCompositeEventThread;
485 
486     std::atomic<nsecs_t> mLastResyncTime = 0;
487 
488     const FeatureFlags mFeatures;
489 
490     mutable std::mutex mVsyncConfigLock;
491     // Stores phase offsets configured per refresh rate.
492     std::unique_ptr<VsyncConfiguration> mVsyncConfiguration GUARDED_BY(mVsyncConfigLock);
493 
494     // Shifts the VSYNC phase during certain transactions and refresh rate changes.
495     const sp<VsyncModulator> mVsyncModulator;
496 
497     const std::unique_ptr<RefreshRateStats> mRefreshRateStats;
498 
499     // Used to choose refresh rate if content detection is enabled.
500     LayerHistory mLayerHistory;
501 
502     // Timer used to monitor touch events.
503     ftl::Optional<OneShotTimer> mTouchTimer;
504     // Timer used to monitor display power mode.
505     ftl::Optional<OneShotTimer> mDisplayPowerTimer;
506 
507     // Injected delay prior to compositing, for simulating jank.
508     float mPacesetterFrameDurationFractionToSkip GUARDED_BY(kMainThreadContext) = 0.f;
509 
510     ISchedulerCallback& mSchedulerCallback;
511 
512     // mDisplayLock may be locked while under mPolicyLock.
513     mutable std::mutex mPolicyLock;
514 
515     // Only required for reads outside kMainThreadContext. kMainThreadContext is the only writer, so
516     // must lock for writes but not reads. See also mPolicyLock for locking order.
517     mutable std::mutex mDisplayLock;
518 
519     using FrameTargeterPtr = std::unique_ptr<FrameTargeter>;
520 
521     struct Display {
DisplayDisplay522         Display(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
523                 VsyncSchedulePtr schedulePtr, FeatureFlags features)
524               : displayId(displayId),
525                 selectorPtr(std::move(selectorPtr)),
526                 schedulePtr(std::move(schedulePtr)),
527                 targeterPtr(std::make_unique<FrameTargeter>(displayId, features)) {}
528 
529         const PhysicalDisplayId displayId;
530 
531         // Effectively const except in move constructor.
532         RefreshRateSelectorPtr selectorPtr;
533         VsyncSchedulePtr schedulePtr;
534         FrameTargeterPtr targeterPtr;
535 
536         hal::PowerMode powerMode = hal::PowerMode::OFF;
537     };
538 
539     using DisplayRef = std::reference_wrapper<Display>;
540     using ConstDisplayRef = std::reference_wrapper<const Display>;
541 
542     ui::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays GUARDED_BY(mDisplayLock)
543             GUARDED_BY(kMainThreadContext);
544 
545     ftl::Optional<PhysicalDisplayId> mPacesetterDisplayId GUARDED_BY(mDisplayLock)
546             GUARDED_BY(kMainThreadContext);
547 
pacesetterDisplayLocked()548     ftl::Optional<DisplayRef> pacesetterDisplayLocked() REQUIRES(mDisplayLock) {
549         return static_cast<const Scheduler*>(this)->pacesetterDisplayLocked().transform(
550                 [](const Display& display) { return std::ref(const_cast<Display&>(display)); });
551     }
552 
pacesetterDisplayLocked()553     ftl::Optional<ConstDisplayRef> pacesetterDisplayLocked() const REQUIRES(mDisplayLock) {
554         ftl::FakeGuard guard(kMainThreadContext);
555         return mPacesetterDisplayId.and_then([this](PhysicalDisplayId pacesetterId)
556                                                      REQUIRES(mDisplayLock, kMainThreadContext) {
557                                                          return mDisplays.get(pacesetterId);
558                                                      });
559     }
560 
561     // The pacesetter must exist as a precondition.
pacesetterPtrLocked()562     ftl::NonNull<const Display*> pacesetterPtrLocked() const REQUIRES(mDisplayLock) {
563         return ftl::as_non_null(&pacesetterDisplayLocked()->get());
564     }
565 
pacesetterSelectorPtr()566     RefreshRateSelectorPtr pacesetterSelectorPtr() const EXCLUDES(mDisplayLock) {
567         std::scoped_lock lock(mDisplayLock);
568         return pacesetterSelectorPtrLocked();
569     }
570 
pacesetterSelectorPtrLocked()571     RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) {
572         return pacesetterDisplayLocked()
573                 .transform([](const Display& display) { return display.selectorPtr; })
574                 .or_else([] { return std::optional<RefreshRateSelectorPtr>(nullptr); })
575                 .value();
576     }
577 
578     ConstVsyncSchedulePtr getVsyncScheduleLocked(
579             std::optional<PhysicalDisplayId> = std::nullopt) const REQUIRES(mDisplayLock);
580 
581     VsyncSchedulePtr getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt = std::nullopt)
REQUIRES(mDisplayLock)582             REQUIRES(mDisplayLock) {
583         return std::const_pointer_cast<VsyncSchedule>(
584                 static_cast<const Scheduler*>(this)->getVsyncScheduleLocked(idOpt));
585     }
586 
587     struct Policy {
588         // Policy for choosing the display mode.
589         LayerHistory::Summary contentRequirements;
590         TimerState idleTimer = TimerState::Reset;
591         TouchState touch = TouchState::Inactive;
592         TimerState displayPowerTimer = TimerState::Expired;
593         hal::PowerMode displayPowerMode = hal::PowerMode::ON;
594 
595         // Chosen display mode.
596         ftl::Optional<FrameRateMode> modeOpt;
597 
598         // Display mode of latest emitted event.
599         std::optional<FrameRateMode> emittedModeOpt;
600     } mPolicy GUARDED_BY(mPolicyLock);
601 
602     std::mutex mChoreographerLock;
603 
604     struct AttachedChoreographers {
605         Fps frameRate;
606         std::unordered_set<wp<EventThreadConnection>, WpHash> connections;
607     };
608     // Map keyed by layer ID (sequence) to choreographer connections.
609     std::unordered_map<int32_t, AttachedChoreographers> mAttachedChoreographers
610             GUARDED_BY(mChoreographerLock);
611 
612     std::mutex mVsyncTimelineLock;
613     std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
614             GUARDED_BY(mVsyncTimelineLock);
615     static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
616 
617     FrameRateOverrideMappings mFrameRateOverrideMappings;
618     SmallAreaDetectionAllowMappings mSmallAreaDetectionAllowMappings;
619 
620     std::atomic<std::optional<TimePoint>> mDebugPresentDelay;
621 };
622 
623 } // namespace scheduler
624 } // namespace android
625