xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/RefreshRateSelector.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2019 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 <type_traits>
20 #include <utility>
21 #include <variant>
22 
23 #include <ftl/concat.h>
24 #include <ftl/optional.h>
25 #include <ftl/unit.h>
26 #include <gui/DisplayEventReceiver.h>
27 
28 #include <scheduler/Fps.h>
29 #include <scheduler/FrameRateMode.h>
30 #include <scheduler/Seamlessness.h>
31 
32 #include "DisplayHardware/DisplayMode.h"
33 #include "Scheduler/OneShotTimer.h"
34 #include "ThreadContext.h"
35 #include "Utils/Dumper.h"
36 
37 namespace android::scheduler {
38 
39 using namespace std::chrono_literals;
40 
41 using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
42 
43 // Selects the refresh rate of a display by ranking its `DisplayModes` in accordance with
44 // the DisplayManager (or override) `Policy`, the `LayerRequirement` of each active layer,
45 // and `GlobalSignals`.
46 class RefreshRateSelector {
47 public:
48     // Margin used when matching refresh rates to the content desired ones.
49     static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
50             std::chrono::nanoseconds(800us).count();
51 
52     // The lowest Render Frame Rate that will ever be selected
53     static constexpr Fps kMinSupportedFrameRate = 20_Hz;
54 
55     // Start range for FrameRateCategory Normal and High.
56     static constexpr Fps kFrameRateCategoryRateHigh = 90_Hz;
57     static constexpr Fps kFrameRateCategoryRateNormal = 60_Hz;
58     static constexpr std::pair<Fps, Fps> kFrameRateCategoryRates = {kFrameRateCategoryRateNormal,
59                                                                     kFrameRateCategoryRateHigh};
60 
61     class Policy {
62         static constexpr int kAllowGroupSwitchingDefault = false;
63 
64     public:
65         // The default mode, used to ensure we only initiate display mode switches within the
66         // same mode group as defaultMode's group.
67         DisplayModeId defaultMode;
68         // Whether or not we switch mode groups to get the best frame rate.
69         bool allowGroupSwitching = kAllowGroupSwitchingDefault;
70         // The primary refresh rate ranges. @see DisplayModeSpecs.aidl for details.
71         // TODO(b/257072060): use the render range when selecting SF render rate
72         //  or the app override frame rate
73         FpsRanges primaryRanges;
74         // The app request refresh rate ranges. @see DisplayModeSpecs.aidl for details.
75         FpsRanges appRequestRanges;
76         // The idle timer configuration, if provided.
77         std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig> idleScreenConfigOpt;
78 
79         Policy() = default;
80 
81         Policy(DisplayModeId defaultMode, FpsRange range,
82                bool allowGroupSwitching = kAllowGroupSwitchingDefault,
83                const std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig>&
84                        idleScreenConfigOpt = std::nullopt)
Policy(defaultMode,FpsRanges{range, range},FpsRanges{range, range},allowGroupSwitching,idleScreenConfigOpt)85               : Policy(defaultMode, FpsRanges{range, range}, FpsRanges{range, range},
86                        allowGroupSwitching, idleScreenConfigOpt) {}
87 
88         Policy(DisplayModeId defaultMode, FpsRanges primaryRanges, FpsRanges appRequestRanges,
89                bool allowGroupSwitching = kAllowGroupSwitchingDefault,
90                const std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig>&
91                        idleScreenConfigOpt = std::nullopt)
defaultMode(defaultMode)92               : defaultMode(defaultMode),
93                 allowGroupSwitching(allowGroupSwitching),
94                 primaryRanges(primaryRanges),
95                 appRequestRanges(appRequestRanges),
96                 idleScreenConfigOpt(idleScreenConfigOpt) {}
97 
98         bool operator==(const Policy& other) const {
99             using namespace fps_approx_ops;
100             return similarExceptIdleConfig(other) &&
101                     idleScreenConfigOpt == other.idleScreenConfigOpt;
102         }
103 
104         bool operator!=(const Policy& other) const { return !(*this == other); }
105 
primaryRangeIsSingleRate()106         bool primaryRangeIsSingleRate() const {
107             return isApproxEqual(primaryRanges.physical.min, primaryRanges.physical.max);
108         }
109 
similarExceptIdleConfig(const Policy & updated)110         bool similarExceptIdleConfig(const Policy& updated) const {
111             using namespace fps_approx_ops;
112             return defaultMode == updated.defaultMode && primaryRanges == updated.primaryRanges &&
113                     appRequestRanges == updated.appRequestRanges &&
114                     allowGroupSwitching == updated.allowGroupSwitching;
115         }
116 
117         std::string toString() const;
118     };
119 
120     enum class SetPolicyResult { Invalid, Unchanged, Changed };
121 
122     // We maintain the display manager policy and the override policy separately. The override
123     // policy is used by CTS tests to get a consistent device state for testing. While the override
124     // policy is set, it takes precedence over the display manager policy. Once the override policy
125     // is cleared, we revert to using the display manager policy.
126     struct DisplayManagerPolicy : Policy {
127         using Policy::Policy;
128     };
129 
130     struct OverridePolicy : Policy {
131         using Policy::Policy;
132     };
133 
134     struct NoOverridePolicy {};
135 
136     using PolicyVariant = std::variant<DisplayManagerPolicy, OverridePolicy, NoOverridePolicy>;
137 
138     SetPolicyResult setPolicy(const PolicyVariant&) EXCLUDES(mLock) REQUIRES(kMainThreadContext);
139 
onModeChangeInitiated()140     void onModeChangeInitiated() REQUIRES(kMainThreadContext) { mNumModeSwitchesInPolicy++; }
141 
142     // Gets the current policy, which will be the override policy if active, and the display manager
143     // policy otherwise.
144     Policy getCurrentPolicy() const EXCLUDES(mLock);
145     // Gets the display manager policy, regardless of whether an override policy is active.
146     Policy getDisplayManagerPolicy() const EXCLUDES(mLock);
147 
148     // Returns true if mode is allowed by the current policy.
149     bool isModeAllowed(const FrameRateMode&) const EXCLUDES(mLock);
150 
151     // Describes the different options the layer voted for refresh rate
152     enum class LayerVoteType {
153         NoVote,          // Doesn't care about the refresh rate
154         Min,             // Minimal refresh rate available
155         Max,             // Maximal refresh rate available
156         Heuristic,       // Specific refresh rate that was calculated by platform using a heuristic
157         ExplicitDefault, // Specific refresh rate that was provided by the app with Default
158                          // compatibility
159         ExplicitExactOrMultiple, // Specific refresh rate that was provided by the app with
160                                  // ExactOrMultiple compatibility
161         ExplicitExact,           // Specific refresh rate that was provided by the app with
162                                  // Exact compatibility
163         ExplicitGte,             // Greater than or equal to frame rate provided by the app
164         ExplicitCategory,        // Specific frame rate category was provided by the app
165 
166         ftl_last = ExplicitCategory
167     };
168 
169     // Captures the layer requirements for a refresh rate. This will be used to determine the
170     // display refresh rate.
171     struct LayerRequirement {
172         // Layer's name. Used for debugging purposes.
173         std::string name;
174         // Layer's owner uid
175         uid_t ownerUid = static_cast<uid_t>(-1);
176         // Layer vote type.
177         LayerVoteType vote = LayerVoteType::NoVote;
178         // Layer's desired refresh rate, if applicable.
179         Fps desiredRefreshRate;
180         // If a seamless mode switch is required.
181         Seamlessness seamlessness = Seamlessness::Default;
182         // Layer frame rate category.
183         FrameRateCategory frameRateCategory = FrameRateCategory::Default;
184         // Goes together with frame rate category vote. Allow refresh rate changes only
185         // if there would be no jank.
186         bool frameRateCategorySmoothSwitchOnly = false;
187         // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer
188         // would have on choosing the refresh rate.
189         float weight = 0.0f;
190         // Whether layer is in focus or not based on WindowManager's state
191         bool focused = false;
192 
193         bool operator==(const LayerRequirement& other) const {
194             return name == other.name && vote == other.vote &&
195                     isApproxEqual(desiredRefreshRate, other.desiredRefreshRate) &&
196                     seamlessness == other.seamlessness && weight == other.weight &&
197                     focused == other.focused && frameRateCategory == other.frameRateCategory;
198         }
199 
200         bool operator!=(const LayerRequirement& other) const { return !(*this == other); }
201 
isNoVoteLayerRequirement202         bool isNoVote() const { return RefreshRateSelector::isNoVote(vote); }
203     };
204 
205     // Returns true if the layer explicitly instructs to not contribute to refresh rate selection.
206     // In other words, true if the layer should be ignored.
isNoVote(LayerVoteType vote)207     static bool isNoVote(LayerVoteType vote) { return vote == LayerVoteType::NoVote; }
208 
209     // Global state describing signals that affect refresh rate choice.
210     struct GlobalSignals {
211         // Whether the user touched the screen recently. Used to apply touch boost.
212         bool touch = false;
213         // True if the system hasn't seen any buffers posted to layers recently.
214         bool idle = false;
215         // Whether the display is about to be powered on, or has been in PowerMode::ON
216         // within the timeout of DisplayPowerTimer.
217         bool powerOnImminent = false;
218 
shouldEmitEventGlobalSignals219         bool shouldEmitEvent() const { return !idle; }
220 
221         bool operator==(GlobalSignals other) const {
222             return touch == other.touch && idle == other.idle &&
223                     powerOnImminent == other.powerOnImminent;
224         }
225 
toStringGlobalSignals226         auto toString() const {
227             return ftl::Concat("{touch=", touch, ", idle=", idle,
228                                ", powerOnImminent=", powerOnImminent, '}');
229         }
230     };
231 
232     struct ScoredFrameRate {
233         FrameRateMode frameRateMode;
234         float score = 0.0f;
235 
236         bool operator==(const ScoredFrameRate& other) const {
237             return frameRateMode == other.frameRateMode && score == other.score;
238         }
239 
scoresEqualScoredFrameRate240         static bool scoresEqual(float lhs, float rhs) {
241             constexpr float kEpsilon = 0.0001f;
242             return std::abs(lhs - rhs) <= kEpsilon;
243         }
244 
245         struct DescendingScore {
operatorScoredFrameRate::DescendingScore246             bool operator()(const ScoredFrameRate& lhs, const ScoredFrameRate& rhs) const {
247                 return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score);
248             }
249         };
250     };
251 
252     using FrameRateRanking = std::vector<ScoredFrameRate>;
253 
254     struct RankedFrameRates {
255         FrameRateRanking ranking; // Ordered by descending score.
256         GlobalSignals consideredSignals;
257         Fps pacesetterFps;
258 
259         bool operator==(const RankedFrameRates& other) const {
260             return ranking == other.ranking && consideredSignals == other.consideredSignals &&
261                     isApproxEqual(pacesetterFps, other.pacesetterFps);
262         }
263     };
264 
265     // If valid, `pacesetterFps` (used by follower displays) filters the ranking to modes matching
266     // that refresh rate.
267     RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals,
268                                          Fps pacesetterFps = {}) const EXCLUDES(mLock);
269 
getSupportedRefreshRateRange()270     FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
271         std::lock_guard lock(mLock);
272         return {mMinRefreshRateModeIt->second->getPeakFps(),
273                 mMaxRefreshRateModeIt->second->getPeakFps()};
274     }
275 
276     ftl::Optional<FrameRateMode> onKernelTimerChanged(ftl::Optional<DisplayModeId> desiredModeIdOpt,
277                                                       bool timerExpired) const EXCLUDES(mLock);
278 
279     void setActiveMode(DisplayModeId, Fps renderFrameRate) EXCLUDES(mLock);
280 
281     // See mActiveModeOpt for thread safety.
282     FrameRateMode getActiveMode() const EXCLUDES(mLock);
283 
284     // Returns a known frame rate that is the closest to frameRate
285     Fps findClosestKnownFrameRate(Fps frameRate) const;
286 
287     enum class KernelIdleTimerController { Sysprop, HwcApi, ftl_last = HwcApi };
288 
289     // Configuration flags.
290     struct Config {
291         enum class FrameRateOverride {
292             // Do not override the frame rate for an app
293             Disabled,
294 
295             // Override the frame rate for an app to a value which is also
296             // a display refresh rate
297             AppOverrideNativeRefreshRates,
298 
299             // Override the frame rate for an app to any value
300             AppOverride,
301 
302             // Override the frame rate for all apps and all values.
303             Enabled,
304 
305             ftl_last = Enabled
306         };
307         FrameRateOverride enableFrameRateOverride = FrameRateOverride::Disabled;
308 
309         // Specifies the upper refresh rate threshold (inclusive) for layer vote types of multiple
310         // or heuristic, such that refresh rates higher than this value will not be voted for. 0 if
311         // no threshold is set.
312         int frameRateMultipleThreshold = 0;
313 
314         // The Idle Timer timeout. 0 timeout means no idle timer.
315         std::chrono::milliseconds legacyIdleTimerTimeout = 0ms;
316 
317         // The controller representing how the kernel idle timer will be configured
318         // either on the HWC api or sysprop.
319         ftl::Optional<KernelIdleTimerController> kernelIdleTimerController;
320     };
321 
322     RefreshRateSelector(
323             DisplayModes, DisplayModeId activeModeId,
324             Config config = {.enableFrameRateOverride = Config::FrameRateOverride::Disabled,
325                              .frameRateMultipleThreshold = 0,
326                              .legacyIdleTimerTimeout = 0ms,
327                              .kernelIdleTimerController = {}});
328 
329     RefreshRateSelector(const RefreshRateSelector&) = delete;
330     RefreshRateSelector& operator=(const RefreshRateSelector&) = delete;
331 
displayModes()332     DisplayModes displayModes() const {
333         std::lock_guard lock(mLock);
334         return mDisplayModes;
335     }
336 
337     // Returns whether switching modes (refresh rate or resolution) is possible.
338     // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
339     //  differ in resolution. Once Config::FrameRateOverride::Enabled becomes the default,
340     //  we can probably remove canSwitch altogether since all devices will be able
341     //  to switch to a frame rate divisor.
canSwitch()342     bool canSwitch() const EXCLUDES(mLock) {
343         std::lock_guard lock(mLock);
344         return mDisplayModes.size() > 1 ||
345                 mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled;
346     }
347 
348     // Class to enumerate options around toggling the kernel timer on and off.
349     enum class KernelIdleTimerAction {
350         TurnOff, // Turn off the idle timer.
351         TurnOn   // Turn on the idle timer.
352     };
353 
354     // Checks whether kernel idle timer should be active depending the policy decisions around
355     // refresh rates.
356     KernelIdleTimerAction getIdleTimerAction() const;
357 
supportsAppFrameRateOverrideByContent()358     bool supportsAppFrameRateOverrideByContent() const {
359         return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled;
360     }
361 
supportsFrameRateOverride()362     bool supportsFrameRateOverride() const {
363         return mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled;
364     }
365 
366     // Return the display refresh rate divisor to match the layer
367     // frame rate, or 0 if the display refresh rate is not a multiple of the
368     // layer refresh rate.
369     static int getFrameRateDivisor(Fps displayRefreshRate, Fps layerFrameRate);
370 
371     // Returns if the provided frame rates have a ratio t*1000/1001 or t*1001/1000
372     // for an integer t.
373     static bool isFractionalPairOrMultiple(Fps, Fps);
374 
375     using UidToFrameRateOverride = std::map<uid_t, Fps>;
376 
377     // Returns the frame rate override for each uid.
378     UidToFrameRateOverride getFrameRateOverrides(const std::vector<LayerRequirement>&,
379                                                  Fps displayFrameRate, GlobalSignals) const
380             EXCLUDES(mLock);
381 
382     // Gets the FpsRange that the FrameRateCategory represents.
383     static FpsRange getFrameRateCategoryRange(FrameRateCategory category);
384 
kernelIdleTimerController()385     std::optional<KernelIdleTimerController> kernelIdleTimerController() {
386         return mConfig.kernelIdleTimerController;
387     }
388 
389     struct IdleTimerCallbacks {
390         struct Callbacks {
391             std::function<void()> onReset;
392             std::function<void()> onExpired;
393         };
394 
395         Callbacks platform;
396         Callbacks kernel;
397         Callbacks vrr;
398     };
399 
setIdleTimerCallbacks(IdleTimerCallbacks callbacks)400     void setIdleTimerCallbacks(IdleTimerCallbacks callbacks) EXCLUDES(mIdleTimerCallbacksMutex) {
401         std::scoped_lock lock(mIdleTimerCallbacksMutex);
402         mIdleTimerCallbacks = std::move(callbacks);
403     }
404 
clearIdleTimerCallbacks()405     void clearIdleTimerCallbacks() EXCLUDES(mIdleTimerCallbacksMutex) {
406         std::scoped_lock lock(mIdleTimerCallbacksMutex);
407         mIdleTimerCallbacks.reset();
408     }
409 
startIdleTimer()410     void startIdleTimer() {
411         mIdleTimerStarted = true;
412         if (mIdleTimer) {
413             mIdleTimer->start();
414         }
415     }
416 
stopIdleTimer()417     void stopIdleTimer() {
418         mIdleTimerStarted = false;
419         if (mIdleTimer) {
420             mIdleTimer->stop();
421         }
422     }
423 
resetKernelIdleTimer()424     void resetKernelIdleTimer() {
425         if (mIdleTimer && mConfig.kernelIdleTimerController) {
426             mIdleTimer->reset();
427         }
428     }
429 
resetIdleTimer()430     void resetIdleTimer() {
431         if (mIdleTimer) {
432             mIdleTimer->reset();
433         }
434     }
435 
436     void dump(utils::Dumper&) const EXCLUDES(mLock);
437 
438     std::chrono::milliseconds getIdleTimerTimeout();
439 
440     bool isVrrDevice() const;
441 
getFrameRateCategoryRates()442     std::pair<Fps, Fps> getFrameRateCategoryRates() const { return kFrameRateCategoryRates; }
443 
444     std::vector<float> getSupportedFrameRates() const EXCLUDES(mLock);
445 
446 private:
447     friend struct TestableRefreshRateSelector;
448 
449     void constructAvailableRefreshRates() REQUIRES(mLock);
450 
451     // See mActiveModeOpt for thread safety.
452     const FrameRateMode& getActiveModeLocked() const REQUIRES(mLock);
453 
454     RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers,
455                                                GlobalSignals signals, Fps pacesetterFps) const
456             REQUIRES(mLock);
457 
458     // Returns number of display frames and remainder when dividing the layer refresh period by
459     // display refresh period.
460     std::pair<nsecs_t, nsecs_t> getDisplayFrames(nsecs_t layerPeriod, nsecs_t displayPeriod) const;
461 
462     // Returns the lowest refresh rate according to the current policy. May change at runtime. Only
463     // uses the primary range, not the app request range.
464     const DisplayModePtr& getMinRefreshRateByPolicyLocked() const REQUIRES(mLock);
465 
466     // Returns the highest refresh rate according to the current policy. May change at runtime. Only
467     // uses the primary range, not the app request range.
468     const DisplayModePtr& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);
469 
470     struct RefreshRateScoreComparator;
471 
472     enum class RefreshRateOrder {
473         Ascending,
474         Descending,
475 
476         ftl_last = Descending
477     };
478 
479     typedef std::function<bool(const FrameRateMode)> RankFrameRatesPredicate;
480 
481     // Rank the frame rates.
482     // Only modes in the primary range for which `predicate` is `true` will be scored.
483     // Does not use the app requested range.
484     FrameRateRanking rankFrameRates(
485             std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder,
486             std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt,
487             const RankFrameRatesPredicate& predicate = [](FrameRateMode) { return true; }) const
488             REQUIRES(mLock);
489 
490     const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
491     bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
492 
493     // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1.
494     float calculateDistanceScoreFromMaxLocked(Fps refreshRate) const REQUIRES(mLock);
495 
496     // Returns the refresh rate score based on its distance from the reference rate.
497     float calculateDistanceScoreLocked(Fps referenceRate, Fps refreshRate) const REQUIRES(mLock);
498 
499     // calculates a score for a layer. Used to determine the display refresh rate
500     // and the frame rate override for certains applications.
501     float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
502                                     bool isSeamlessSwitch) const REQUIRES(mLock);
503 
504     float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&, Fps refreshRate) const
505             REQUIRES(mLock);
506 
507     // Calculates the score for non-exact matching layer that has LayerVoteType::ExplicitDefault.
508     float calculateNonExactMatchingDefaultLayerScoreLocked(nsecs_t displayPeriod,
509                                                            nsecs_t layerPeriod) const
510             REQUIRES(mLock);
511 
512     void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock)
513             REQUIRES(kMainThreadContext);
514 
515     void initializeIdleTimer(std::chrono::milliseconds timeout);
516 
getIdleTimerCallbacks()517     std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const
518             REQUIRES(mIdleTimerCallbacksMutex) {
519         if (!mIdleTimerCallbacks) return {};
520 
521         if (mIsVrrDevice) return mIdleTimerCallbacks->vrr;
522 
523         return mConfig.kernelIdleTimerController.has_value() ? mIdleTimerCallbacks->kernel
524                                                              : mIdleTimerCallbacks->platform;
525     }
526 
isNativeRefreshRate(Fps fps)527     bool isNativeRefreshRate(Fps fps) const REQUIRES(mLock) {
528         LOG_ALWAYS_FATAL_IF(mConfig.enableFrameRateOverride !=
529                                     Config::FrameRateOverride::AppOverrideNativeRefreshRates,
530                             "should only be called when "
531                             "Config::FrameRateOverride::AppOverrideNativeRefreshRates is used");
532         return mAppOverrideNativeRefreshRates.contains(fps);
533     }
534 
535     std::vector<FrameRateMode> createFrameRateModes(
536             const Policy&, std::function<bool(const DisplayMode&)>&& filterModes,
537             const FpsRange&) const REQUIRES(mLock);
538 
539     // The display modes of the active display. The DisplayModeIterators below are pointers into
540     // this container, so must be invalidated whenever the DisplayModes change. The Policy below
541     // is also dependent, so must be reset as well.
542     DisplayModes mDisplayModes GUARDED_BY(mLock);
543 
544     // Set of supported display refresh rates for easy lookup
545     // when FrameRateOverride::AppOverrideNativeRefreshRates is in use.
546     ftl::SmallMap<Fps, ftl::Unit, 8, FpsApproxEqual> mAppOverrideNativeRefreshRates;
547 
548     ftl::Optional<FrameRateMode> mActiveModeOpt GUARDED_BY(mLock);
549 
550     DisplayModeIterator mMinRefreshRateModeIt GUARDED_BY(mLock);
551     DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);
552 
553     // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate.
554     std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock);
555     std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock);
556     std::vector<FrameRateMode> mAllFrameRates GUARDED_BY(mLock);
557 
558     // Caches whether the device is VRR-compatible based on the active display mode.
559     std::atomic_bool mIsVrrDevice = false;
560 
561     Policy mDisplayManagerPolicy GUARDED_BY(mLock);
562     std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
563 
564     unsigned mNumModeSwitchesInPolicy GUARDED_BY(kMainThreadContext) = 0;
565 
566     mutable std::mutex mLock;
567 
568     // A sorted list of known frame rates that a Heuristic layer will choose
569     // from based on the closest value.
570     const std::vector<Fps> mKnownFrameRates;
571 
572     const Config mConfig;
573 
574     // A list of known frame rates that favors at least 60Hz if there is no exact match display
575     // refresh rate
576     const std::vector<Fps> mFrameRatesThatFavorsAtLeast60 = {23.976_Hz, 25_Hz, 29.97_Hz, 50_Hz,
577                                                              59.94_Hz};
578 
579     Config::FrameRateOverride mFrameRateOverrideConfig;
580 
581     struct GetRankedFrameRatesCache {
582         std::vector<LayerRequirement> layers;
583         GlobalSignals signals;
584         Fps pacesetterFps;
585 
586         RankedFrameRates result;
587 
matchesGetRankedFrameRatesCache588         bool matches(const GetRankedFrameRatesCache& other) const {
589             return layers == other.layers && signals == other.signals &&
590                     isApproxEqual(pacesetterFps, other.pacesetterFps);
591         }
592     };
593     mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock);
594 
595     // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
596     std::mutex mIdleTimerCallbacksMutex;
597     std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex);
598     // Used to detect (lack of) frame activity.
599     ftl::Optional<scheduler::OneShotTimer> mIdleTimer;
600     std::atomic<bool> mIdleTimerStarted = false;
601 
602     // Returns the range of supported frame rates.
603     FpsRange getSupportedFrameRateRangeLocked() const REQUIRES(mLock);
604 };
605 
606 } // namespace android::scheduler
607