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