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