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