xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp (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 // #define LOG_NDEBUG 0
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 
20 // TODO(b/129481165): remove the #pragma below and fix conversion issues
21 #pragma clang diagnostic push
22 #pragma clang diagnostic ignored "-Wextra"
23 
24 #include <chrono>
25 #include <cmath>
26 #include <deque>
27 #include <map>
28 
29 #include <android-base/properties.h>
30 #include <android-base/stringprintf.h>
31 #include <common/trace.h>
32 #include <ftl/enum.h>
33 #include <ftl/fake_guard.h>
34 #include <ftl/match.h>
35 #include <ftl/unit.h>
36 #include <scheduler/FrameRateMode.h>
37 
38 #include "RefreshRateSelector.h"
39 
40 #include <com_android_graphics_surfaceflinger_flags.h>
41 
42 #undef LOG_TAG
43 #define LOG_TAG "RefreshRateSelector"
44 
45 namespace android::scheduler {
46 namespace {
47 
48 using namespace com::android::graphics::surfaceflinger;
49 
50 struct RefreshRateScore {
51     FrameRateMode frameRateMode;
52     float overallScore;
53     struct {
54         float modeBelowThreshold;
55         float modeAboveThreshold;
56     } fixedRateBelowThresholdLayersScore;
57 };
58 
59 constexpr RefreshRateSelector::GlobalSignals kNoSignals;
60 
formatLayerInfo(const RefreshRateSelector::LayerRequirement & layer,float weight)61 std::string formatLayerInfo(const RefreshRateSelector::LayerRequirement& layer, float weight) {
62     return base::StringPrintf("%s (type=%s, weight=%.2f, seamlessness=%s) %s", layer.name.c_str(),
63                               ftl::enum_string(layer.vote).c_str(), weight,
64                               ftl::enum_string(layer.seamlessness).c_str(),
65                               to_string(layer.desiredRefreshRate).c_str());
66 }
67 
constructKnownFrameRates(const DisplayModes & modes)68 std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) {
69     std::vector<Fps> knownFrameRates = {24_Hz, 30_Hz, 45_Hz, 60_Hz, 72_Hz};
70     knownFrameRates.reserve(knownFrameRates.size() + modes.size());
71 
72     // Add all supported refresh rates.
73     for (const auto& [id, mode] : modes) {
74         knownFrameRates.push_back(mode->getPeakFps());
75     }
76 
77     // Sort and remove duplicates.
78     std::sort(knownFrameRates.begin(), knownFrameRates.end(), isStrictlyLess);
79     knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
80                                       isApproxEqual),
81                           knownFrameRates.end());
82     return knownFrameRates;
83 }
84 
sortByRefreshRate(const DisplayModes & modes)85 std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes) {
86     std::vector<DisplayModeIterator> sortedModes;
87     sortedModes.reserve(modes.size());
88     for (auto it = modes.begin(); it != modes.end(); ++it) {
89         sortedModes.push_back(it);
90     }
91 
92     std::sort(sortedModes.begin(), sortedModes.end(), [](auto it1, auto it2) {
93         const auto& mode1 = it1->second;
94         const auto& mode2 = it2->second;
95 
96         if (mode1->getVsyncRate().getPeriodNsecs() == mode2->getVsyncRate().getPeriodNsecs()) {
97             return mode1->getGroup() > mode2->getGroup();
98         }
99 
100         return mode1->getVsyncRate().getPeriodNsecs() > mode2->getVsyncRate().getPeriodNsecs();
101     });
102 
103     return sortedModes;
104 }
105 
divisorRange(Fps vsyncRate,Fps peakFps,FpsRange range,RefreshRateSelector::Config::FrameRateOverride config)106 std::pair<unsigned, unsigned> divisorRange(Fps vsyncRate, Fps peakFps, FpsRange range,
107                                            RefreshRateSelector::Config::FrameRateOverride config) {
108     if (config != RefreshRateSelector::Config::FrameRateOverride::Enabled) {
109         return {1, 1};
110     }
111 
112     using fps_approx_ops::operator/;
113     // use signed type as `fps / range.max` might be 0
114     auto start = std::max(1, static_cast<int>(peakFps / range.max) - 1);
115     if (FlagManager::getInstance().vrr_config()) {
116         start = std::max(1,
117                          static_cast<int>(vsyncRate /
118                                           std::min(range.max, peakFps, fps_approx_ops::operator<)) -
119                                  1);
120     }
121     const auto end = vsyncRate /
122             std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate,
123                      fps_approx_ops::operator<);
124 
125     return {start, end};
126 }
127 
shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator> & sortedModes)128 bool shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator>& sortedModes) {
129     for (const auto it1 : sortedModes) {
130         const auto& mode1 = it1->second;
131         for (const auto it2 : sortedModes) {
132             const auto& mode2 = it2->second;
133 
134             if (RefreshRateSelector::getFrameRateDivisor(mode1->getPeakFps(),
135                                                          mode2->getPeakFps()) >= 2) {
136                 return true;
137             }
138         }
139     }
140     return false;
141 }
142 
toString(const RefreshRateSelector::PolicyVariant & policy)143 std::string toString(const RefreshRateSelector::PolicyVariant& policy) {
144     using namespace std::string_literals;
145 
146     return ftl::match(
147             policy,
148             [](const RefreshRateSelector::DisplayManagerPolicy& policy) {
149                 return "DisplayManagerPolicy"s + policy.toString();
150             },
151             [](const RefreshRateSelector::OverridePolicy& policy) {
152                 return "OverridePolicy"s + policy.toString();
153             },
154             [](RefreshRateSelector::NoOverridePolicy) { return "NoOverridePolicy"s; });
155 }
156 
157 } // namespace
158 
createFrameRateModes(const Policy & policy,std::function<bool (const DisplayMode &)> && filterModes,const FpsRange & renderRange) const159 auto RefreshRateSelector::createFrameRateModes(
160         const Policy& policy, std::function<bool(const DisplayMode&)>&& filterModes,
161         const FpsRange& renderRange) const -> std::vector<FrameRateMode> {
162     struct Key {
163         Fps fps;
164         int32_t group;
165     };
166 
167     struct KeyLess {
168         bool operator()(const Key& a, const Key& b) const {
169             using namespace fps_approx_ops;
170             if (a.fps != b.fps) {
171                 return a.fps < b.fps;
172             }
173 
174             // For the same fps the order doesn't really matter, but we still
175             // want the behaviour of a strictly less operator.
176             // We use the group id as the secondary ordering for that.
177             return a.group < b.group;
178         }
179     };
180 
181     std::map<Key, DisplayModeIterator, KeyLess> ratesMap;
182     for (auto it = mDisplayModes.begin(); it != mDisplayModes.end(); ++it) {
183         const auto& [id, mode] = *it;
184 
185         if (!filterModes(*mode)) {
186             continue;
187         }
188         const auto vsyncRate = mode->getVsyncRate();
189         const auto peakFps = mode->getPeakFps();
190         const auto [start, end] =
191                 divisorRange(vsyncRate, peakFps, renderRange, mConfig.enableFrameRateOverride);
192         for (auto divisor = start; divisor <= end; divisor++) {
193             const auto fps = vsyncRate / divisor;
194             using fps_approx_ops::operator<;
195             if (divisor > 1 && fps < kMinSupportedFrameRate) {
196                 break;
197             }
198 
199             if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Enabled &&
200                 !renderRange.includes(fps)) {
201                 continue;
202             }
203 
204             if (mConfig.enableFrameRateOverride ==
205                         Config::FrameRateOverride::AppOverrideNativeRefreshRates &&
206                 !isNativeRefreshRate(fps)) {
207                 continue;
208             }
209 
210             const auto [existingIter, emplaceHappened] =
211                     ratesMap.try_emplace(Key{fps, mode->getGroup()}, it);
212             if (emplaceHappened) {
213                 ALOGV("%s: including %s (%s(%s))", __func__, to_string(fps).c_str(),
214                       to_string(peakFps).c_str(), to_string(vsyncRate).c_str());
215             } else {
216                 // If the primary physical range is a single rate, prefer to stay in that rate
217                 // even if there is a lower physical refresh rate available. This would cause more
218                 // cases to stay within the primary physical range
219                 const Fps existingModeFps = existingIter->second->second->getPeakFps();
220                 const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
221                         policy.primaryRanges.physical.includes(existingModeFps);
222                 const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
223                         policy.primaryRanges.physical.includes(mode->getPeakFps());
224                 if (newModeIsPrimaryRange == existingModeIsPrimaryRange) {
225                     // We might need to update the map as we found a lower refresh rate
226                     if (isStrictlyLess(mode->getPeakFps(), existingModeFps)) {
227                         existingIter->second = it;
228                         ALOGV("%s: changing %s (%s(%s)) as we found a lower physical rate",
229                               __func__, to_string(fps).c_str(), to_string(peakFps).c_str(),
230                               to_string(vsyncRate).c_str());
231                     }
232                 } else if (newModeIsPrimaryRange) {
233                     existingIter->second = it;
234                     ALOGV("%s: changing %s (%s(%s)) to stay in the primary range", __func__,
235                           to_string(fps).c_str(), to_string(peakFps).c_str(),
236                           to_string(vsyncRate).c_str());
237                 }
238             }
239         }
240     }
241 
242     std::vector<FrameRateMode> frameRateModes;
243     frameRateModes.reserve(ratesMap.size());
244     for (const auto& [key, mode] : ratesMap) {
245         frameRateModes.emplace_back(FrameRateMode{key.fps, ftl::as_non_null(mode->second)});
246     }
247 
248     // We always want that the lowest frame rate will be corresponding to the
249     // lowest mode for power saving.
250     const auto lowestRefreshRateIt =
251             std::min_element(frameRateModes.begin(), frameRateModes.end(),
252                              [](const FrameRateMode& lhs, const FrameRateMode& rhs) {
253                                  return isStrictlyLess(lhs.modePtr->getVsyncRate(),
254                                                        rhs.modePtr->getVsyncRate());
255                              });
256     frameRateModes.erase(frameRateModes.begin(), lowestRefreshRateIt);
257 
258     return frameRateModes;
259 }
260 
261 struct RefreshRateSelector::RefreshRateScoreComparator {
operator ()android::scheduler::RefreshRateSelector::RefreshRateScoreComparator262     bool operator()(const RefreshRateScore& lhs, const RefreshRateScore& rhs) const {
263         const auto& [frameRateMode, overallScore, _] = lhs;
264 
265         std::string name = to_string(frameRateMode);
266 
267         ALOGV("%s sorting scores %.2f", name.c_str(), overallScore);
268 
269         if (!ScoredFrameRate::scoresEqual(overallScore, rhs.overallScore)) {
270             return overallScore > rhs.overallScore;
271         }
272 
273         if (refreshRateOrder == RefreshRateOrder::Descending) {
274             using fps_approx_ops::operator>;
275             return frameRateMode.fps > rhs.frameRateMode.fps;
276         } else {
277             using fps_approx_ops::operator<;
278             return frameRateMode.fps < rhs.frameRateMode.fps;
279         }
280     }
281 
282     const RefreshRateOrder refreshRateOrder;
283 };
284 
toString() const285 std::string RefreshRateSelector::Policy::toString() const {
286     return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
287                               ", primaryRanges=%s, appRequestRanges=%s idleScreenConfig=%s}",
288                               ftl::to_underlying(defaultMode),
289                               allowGroupSwitching ? "true" : "false",
290                               to_string(primaryRanges).c_str(), to_string(appRequestRanges).c_str(),
291                               idleScreenConfigOpt ? idleScreenConfigOpt->toString().c_str()
292                                                   : "nullptr");
293 }
294 
getDisplayFrames(nsecs_t layerPeriod,nsecs_t displayPeriod) const295 std::pair<nsecs_t, nsecs_t> RefreshRateSelector::getDisplayFrames(nsecs_t layerPeriod,
296                                                                   nsecs_t displayPeriod) const {
297     auto [quotient, remainder] = std::div(layerPeriod, displayPeriod);
298     if (remainder <= MARGIN_FOR_PERIOD_CALCULATION ||
299         std::abs(remainder - displayPeriod) <= MARGIN_FOR_PERIOD_CALCULATION) {
300         quotient++;
301         remainder = 0;
302     }
303 
304     return {quotient, remainder};
305 }
306 
calculateNonExactMatchingDefaultLayerScoreLocked(nsecs_t displayPeriod,nsecs_t layerPeriod) const307 float RefreshRateSelector::calculateNonExactMatchingDefaultLayerScoreLocked(
308         nsecs_t displayPeriod, nsecs_t layerPeriod) const {
309     // Find the actual rate the layer will render, assuming
310     // that layerPeriod is the minimal period to render a frame.
311     // For example if layerPeriod is 20ms and displayPeriod is 16ms,
312     // then the actualLayerPeriod will be 32ms, because it is the
313     // smallest multiple of the display period which is >= layerPeriod.
314     auto actualLayerPeriod = displayPeriod;
315     int multiplier = 1;
316     while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
317         multiplier++;
318         actualLayerPeriod = displayPeriod * multiplier;
319     }
320 
321     // Because of the threshold we used above it's possible that score is slightly
322     // above 1.
323     return std::min(1.0f, static_cast<float>(layerPeriod) / static_cast<float>(actualLayerPeriod));
324 }
325 
calculateNonExactMatchingLayerScoreLocked(const LayerRequirement & layer,Fps refreshRate) const326 float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const LayerRequirement& layer,
327                                                                      Fps refreshRate) const {
328     constexpr float kScoreForFractionalPairs = .8f;
329 
330     const auto displayPeriod = refreshRate.getPeriodNsecs();
331     const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
332     if (layer.vote == LayerVoteType::ExplicitDefault) {
333         return calculateNonExactMatchingDefaultLayerScoreLocked(displayPeriod, layerPeriod);
334     }
335 
336     if (layer.vote == LayerVoteType::ExplicitGte) {
337         using fps_approx_ops::operator>=;
338         if (refreshRate >= layer.desiredRefreshRate) {
339             return 1.0f;
340         } else {
341             return calculateDistanceScoreLocked(layer.desiredRefreshRate, refreshRate);
342         }
343     }
344 
345     if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
346         layer.vote == LayerVoteType::Heuristic) {
347         using fps_approx_ops::operator<;
348         if (refreshRate < 60_Hz) {
349             const bool favorsAtLeast60 =
350                     std::find_if(mFrameRatesThatFavorsAtLeast60.begin(),
351                                  mFrameRatesThatFavorsAtLeast60.end(), [&](Fps fps) {
352                                      using fps_approx_ops::operator==;
353                                      return fps == layer.desiredRefreshRate;
354                                  }) != mFrameRatesThatFavorsAtLeast60.end();
355             if (favorsAtLeast60) {
356                 return 0;
357             }
358         }
359 
360         const float multiplier = refreshRate.getValue() / layer.desiredRefreshRate.getValue();
361 
362         // We only want to score this layer as a fractional pair if the content is not
363         // significantly faster than the display rate, at it would cause a significant frame drop.
364         // It is more appropriate to choose a higher display rate even if
365         // a pull-down will be required.
366         constexpr float kMinMultiplier = 0.75f;
367         if (multiplier >= kMinMultiplier &&
368             isFractionalPairOrMultiple(refreshRate, layer.desiredRefreshRate)) {
369             return kScoreForFractionalPairs;
370         }
371 
372         // Calculate how many display vsyncs we need to present a single frame for this
373         // layer
374         const auto [displayFramesQuotient, displayFramesRemainder] =
375                 getDisplayFrames(layerPeriod, displayPeriod);
376         static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
377         if (displayFramesRemainder == 0) {
378             // Layer desired refresh rate matches the display rate.
379             return 1.0f;
380         }
381 
382         if (displayFramesQuotient == 0) {
383             // Layer desired refresh rate is higher than the display rate.
384             return (static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod)) *
385                     (1.0f / (MAX_FRAMES_TO_FIT + 1));
386         }
387 
388         // Layer desired refresh rate is lower than the display rate. Check how well it fits
389         // the cadence.
390         auto diff = std::abs(displayFramesRemainder - (displayPeriod - displayFramesRemainder));
391         int iter = 2;
392         while (diff > MARGIN_FOR_PERIOD_CALCULATION && iter < MAX_FRAMES_TO_FIT) {
393             diff = diff - (displayPeriod - diff);
394             iter++;
395         }
396 
397         return (1.0f / iter);
398     }
399 
400     return 0;
401 }
402 
calculateDistanceScoreLocked(Fps referenceRate,Fps refreshRate) const403 float RefreshRateSelector::calculateDistanceScoreLocked(Fps referenceRate, Fps refreshRate) const {
404     using fps_approx_ops::operator>=;
405     const float ratio = referenceRate >= refreshRate
406             ? refreshRate.getValue() / referenceRate.getValue()
407             : referenceRate.getValue() / refreshRate.getValue();
408     // Use ratio^2 to get a lower score the more we get further from the reference rate.
409     return ratio * ratio;
410 }
411 
calculateDistanceScoreFromMaxLocked(Fps refreshRate) const412 float RefreshRateSelector::calculateDistanceScoreFromMaxLocked(Fps refreshRate) const {
413     const auto& maxFps = mAppRequestFrameRates.back().fps;
414     return calculateDistanceScoreLocked(maxFps, refreshRate);
415 }
416 
calculateLayerScoreLocked(const LayerRequirement & layer,Fps refreshRate,bool isSeamlessSwitch) const417 float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
418                                                      bool isSeamlessSwitch) const {
419     // Slightly prefer seamless switches.
420     constexpr float kSeamedSwitchPenalty = 0.95f;
421     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
422 
423     if (layer.vote == LayerVoteType::ExplicitCategory) {
424         // HighHint is considered later for touch boost.
425         if (layer.frameRateCategory == FrameRateCategory::HighHint) {
426             return 0.f;
427         }
428 
429         if (getFrameRateCategoryRange(layer.frameRateCategory).includes(refreshRate)) {
430             return 1.f;
431         }
432 
433         FpsRange categoryRange = getFrameRateCategoryRange(layer.frameRateCategory);
434         using fps_approx_ops::operator<;
435         if (refreshRate < categoryRange.min) {
436             return calculateNonExactMatchingDefaultLayerScoreLocked(refreshRate.getPeriodNsecs(),
437                                                                     categoryRange.min
438                                                                             .getPeriodNsecs());
439         }
440         return calculateNonExactMatchingDefaultLayerScoreLocked(refreshRate.getPeriodNsecs(),
441                                                                 categoryRange.max.getPeriodNsecs());
442     }
443 
444     // If the layer wants Max, give higher score to the higher refresh rate
445     if (layer.vote == LayerVoteType::Max) {
446         return calculateDistanceScoreFromMaxLocked(refreshRate);
447     }
448 
449     if (layer.vote == LayerVoteType::ExplicitExact) {
450         const int divisor = getFrameRateDivisor(refreshRate, layer.desiredRefreshRate);
451         if (supportsAppFrameRateOverrideByContent()) {
452             // Since we support frame rate override, allow refresh rates which are
453             // multiples of the layer's request, as those apps would be throttled
454             // down to run at the desired refresh rate.
455             return divisor > 0;
456         }
457 
458         return divisor == 1;
459     }
460 
461     // If the layer frame rate is a divisor of the refresh rate it should score
462     // the highest score.
463     if (layer.desiredRefreshRate.isValid() &&
464         getFrameRateDivisor(refreshRate, layer.desiredRefreshRate) > 0) {
465         return 1.0f * seamlessness;
466     }
467 
468     // The layer frame rate is not a divisor of the refresh rate,
469     // there is a small penalty attached to the score to favor the frame rates
470     // the exactly matches the display refresh rate or a multiple.
471     constexpr float kNonExactMatchingPenalty = 0.95f;
472     return calculateNonExactMatchingLayerScoreLocked(layer, refreshRate) * seamlessness *
473             kNonExactMatchingPenalty;
474 }
475 
getRankedFrameRates(const std::vector<LayerRequirement> & layers,GlobalSignals signals,Fps pacesetterFps) const476 auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement>& layers,
477                                               GlobalSignals signals, Fps pacesetterFps) const
478         -> RankedFrameRates {
479     GetRankedFrameRatesCache cache{layers, signals, pacesetterFps};
480 
481     std::lock_guard lock(mLock);
482 
483     if (mGetRankedFrameRatesCache && mGetRankedFrameRatesCache->matches(cache)) {
484         return mGetRankedFrameRatesCache->result;
485     }
486 
487     cache.result = getRankedFrameRatesLocked(layers, signals, pacesetterFps);
488     mGetRankedFrameRatesCache = std::move(cache);
489     return mGetRankedFrameRatesCache->result;
490 }
491 
492 using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
493 using PerUidLayerRequirements = std::unordered_map<uid_t, LayerRequirementPtrs>;
494 
groupLayersByUid(const std::vector<RefreshRateSelector::LayerRequirement> & layers)495 PerUidLayerRequirements groupLayersByUid(
496         const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
497     PerUidLayerRequirements layersByUid;
498     for (const auto& layer : layers) {
499         const auto it = layersByUid.emplace(layer.ownerUid, LayerRequirementPtrs()).first;
500         auto& layersWithSameUid = it->second;
501         layersWithSameUid.push_back(&layer);
502     }
503     return layersByUid;
504 }
505 
getRankedFrameRatesLocked(const std::vector<LayerRequirement> & layers,GlobalSignals signals,Fps pacesetterFps) const506 auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers,
507                                                     GlobalSignals signals, Fps pacesetterFps) const
508         -> RankedFrameRates {
509     using namespace fps_approx_ops;
510     SFTRACE_CALL();
511     ALOGV("%s: %zu layers", __func__, layers.size());
512 
513     const auto& activeMode = *getActiveModeLocked().modePtr;
514 
515     if (pacesetterFps.isValid()) {
516         ALOGV("Follower display");
517 
518         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending,
519                                             std::nullopt, [&](FrameRateMode mode) {
520                                                 return mode.modePtr->getPeakFps() == pacesetterFps;
521                                             });
522 
523         if (!ranking.empty()) {
524             SFTRACE_FORMAT_INSTANT("%s (Follower display)",
525                                    to_string(ranking.front().frameRateMode.fps).c_str());
526 
527             return {ranking, kNoSignals, pacesetterFps};
528         }
529 
530         ALOGW("Follower display cannot follow the pacesetter");
531     }
532 
533     // Keep the display at max frame rate for the duration of powering on the display.
534     if (signals.powerOnImminent) {
535         ALOGV("Power On Imminent");
536         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending);
537         SFTRACE_FORMAT_INSTANT("%s (Power On Imminent)",
538                                to_string(ranking.front().frameRateMode.fps).c_str());
539         return {ranking, GlobalSignals{.powerOnImminent = true}};
540     }
541 
542     // A method for UI Toolkit to send the touch signal via "HighHint" category vote,
543     // which will touch boost when there are no ExplicitDefault layer votes on the app.
544     // At most one app can have the "HighHint" touch boost vote at a time.
545     // This accounts for cases such as games that use `setFrameRate`
546     // with Default compatibility to limit the frame rate and disabling touch boost.
547     bool isAppTouchBoost = false;
548     const auto layersByUid = groupLayersByUid(layers);
549     for (const auto& [uid, layersWithSameUid] : layersByUid) {
550         bool hasHighHint = false;
551         bool hasExplicitDefault = false;
552         for (const auto& layer : layersWithSameUid) {
553             switch (layer->vote) {
554                 case LayerVoteType::ExplicitDefault:
555                     hasExplicitDefault = true;
556                     break;
557                 case LayerVoteType::ExplicitCategory:
558                     if (layer->frameRateCategory == FrameRateCategory::HighHint) {
559                         hasHighHint = true;
560                     }
561                     break;
562                 default:
563                     // No action
564                     break;
565             }
566             if (hasHighHint && hasExplicitDefault) {
567                 break;
568             }
569         }
570 
571         if (hasHighHint && !hasExplicitDefault) {
572             // Focused app has touch signal (HighHint) and no frame rate ExplicitDefault votes
573             // (which prevents touch boost due to games use case).
574             isAppTouchBoost = true;
575             break;
576         }
577     }
578 
579     int noVoteLayers = 0;
580     // Layers that prefer the same mode ("no-op").
581     int noPreferenceLayers = 0;
582     int minVoteLayers = 0;
583     int maxVoteLayers = 0;
584     int explicitDefaultVoteLayers = 0;
585     int explicitExactOrMultipleVoteLayers = 0;
586     int explicitExact = 0;
587     int explicitGteLayers = 0;
588     int explicitCategoryVoteLayers = 0;
589     int seamedFocusedLayers = 0;
590     int categorySmoothSwitchOnlyLayers = 0;
591 
592     for (const auto& layer : layers) {
593         switch (layer.vote) {
594             case LayerVoteType::NoVote:
595                 noVoteLayers++;
596                 break;
597             case LayerVoteType::Min:
598                 minVoteLayers++;
599                 break;
600             case LayerVoteType::Max:
601                 maxVoteLayers++;
602                 break;
603             case LayerVoteType::ExplicitDefault:
604                 explicitDefaultVoteLayers++;
605                 break;
606             case LayerVoteType::ExplicitExactOrMultiple:
607                 explicitExactOrMultipleVoteLayers++;
608                 break;
609             case LayerVoteType::ExplicitExact:
610                 explicitExact++;
611                 break;
612             case LayerVoteType::ExplicitGte:
613                 explicitGteLayers++;
614                 break;
615             case LayerVoteType::ExplicitCategory:
616                 // HighHint does not count as an explicit signal from an app. It is a touch signal
617                 // sent from UI Toolkit.
618                 if (layer.frameRateCategory != FrameRateCategory::HighHint) {
619                     explicitCategoryVoteLayers++;
620                 }
621                 if (layer.frameRateCategory == FrameRateCategory::NoPreference) {
622                     noPreferenceLayers++;
623                 }
624                 break;
625             case LayerVoteType::Heuristic:
626                 break;
627         }
628 
629         if (layer.seamlessness == Seamlessness::SeamedAndSeamless && layer.focused) {
630             seamedFocusedLayers++;
631         }
632         if (layer.frameRateCategorySmoothSwitchOnly) {
633             categorySmoothSwitchOnlyLayers++;
634         }
635     }
636 
637     const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
638             explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0 || explicitGteLayers > 0 ||
639             explicitCategoryVoteLayers > 0;
640 
641     const Policy* policy = getCurrentPolicyLocked();
642     const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
643 
644     // If the default mode group is different from the group of current mode,
645     // this means a layer requesting a seamed mode switch just disappeared and
646     // we should switch back to the default group.
647     // However if a seamed layer is still present we anchor around the group
648     // of the current mode, in order to prevent unnecessary seamed mode switches
649     // (e.g. when pausing a video playback).
650     const auto anchorGroup =
651             seamedFocusedLayers > 0 ? activeMode.getGroup() : defaultMode->getGroup();
652 
653     // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
654     // selected a refresh rate to see if we should apply touch boost.
655     if (signals.touch && !hasExplicitVoteLayers) {
656         ALOGV("Touch Boost");
657         const auto ranking = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
658         SFTRACE_FORMAT_INSTANT("%s (Touch Boost)",
659                                to_string(ranking.front().frameRateMode.fps).c_str());
660         return {ranking, GlobalSignals{.touch = true}};
661     }
662 
663     // If the primary range consists of a single refresh rate then we can only
664     // move out the of range if layers explicitly request a different refresh
665     // rate.
666     if (!signals.touch && signals.idle &&
667         !(policy->primaryRangeIsSingleRate() && hasExplicitVoteLayers)) {
668         ALOGV("Idle");
669         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
670         SFTRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str());
671         return {ranking, GlobalSignals{.idle = true}};
672     }
673 
674     if (layers.empty() || noVoteLayers == layers.size()) {
675         ALOGV("No layers with votes");
676         const auto ranking = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
677         SFTRACE_FORMAT_INSTANT("%s (No layers with votes)",
678                                to_string(ranking.front().frameRateMode.fps).c_str());
679         return {ranking, kNoSignals};
680     }
681 
682     // If all layers are category NoPreference, use the current config.
683     if (noPreferenceLayers + noVoteLayers == layers.size()) {
684         ALOGV("All layers NoPreference");
685         constexpr float kScore = std::numeric_limits<float>::max();
686         FrameRateRanking currentMode;
687         currentMode.emplace_back(ScoredFrameRate{getActiveModeLocked(), kScore});
688         SFTRACE_FORMAT_INSTANT("%s (All layers NoPreference)",
689                               to_string(currentMode.front().frameRateMode.fps).c_str());
690         return {currentMode, kNoSignals};
691     }
692 
693     const bool smoothSwitchOnly = categorySmoothSwitchOnlyLayers > 0;
694     const DisplayModeId activeModeId = activeMode.getId();
695 
696     // Only if all layers want Min we should return Min
697     if (noVoteLayers + minVoteLayers == layers.size()) {
698         ALOGV("All layers Min");
699         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending,
700                                             std::nullopt, [&](FrameRateMode mode) {
701                                                 return !smoothSwitchOnly ||
702                                                         mode.modePtr->getId() == activeModeId;
703                                             });
704         SFTRACE_FORMAT_INSTANT("%s (All layers Min)",
705                                to_string(ranking.front().frameRateMode.fps).c_str());
706         return {ranking, kNoSignals};
707     }
708 
709     // Find the best refresh rate based on score
710     std::vector<RefreshRateScore> scores;
711     scores.reserve(mAppRequestFrameRates.size());
712 
713     for (const FrameRateMode& it : mAppRequestFrameRates) {
714         scores.emplace_back(RefreshRateScore{it, 0.0f});
715     }
716 
717     for (const auto& layer : layers) {
718         ALOGV("Calculating score for %s (%s, weight %.2f, desired %.2f, category %s) ",
719               layer.name.c_str(), ftl::enum_string(layer.vote).c_str(), layer.weight,
720               layer.desiredRefreshRate.getValue(),
721               ftl::enum_string(layer.frameRateCategory).c_str());
722         if (layer.isNoVote() || layer.frameRateCategory == FrameRateCategory::NoPreference ||
723             layer.vote == LayerVoteType::Min) {
724             ALOGV("%s scoring skipped due to vote", formatLayerInfo(layer, layer.weight).c_str());
725             continue;
726         }
727 
728         const auto weight = layer.weight;
729 
730         for (auto& [mode, overallScore, fixedRateBelowThresholdLayersScore] : scores) {
731             const auto& [fps, modePtr] = mode;
732             const bool isSeamlessSwitch = modePtr->getGroup() == activeMode.getGroup();
733 
734             if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
735                 ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
736                       formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
737                       to_string(activeMode).c_str());
738                 continue;
739             }
740 
741             if (layer.seamlessness == Seamlessness::SeamedAndSeamless && !isSeamlessSwitch &&
742                 !layer.focused) {
743                 ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
744                       " Current mode = %s",
745                       formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
746                       to_string(activeMode).c_str());
747                 continue;
748             }
749 
750             if (smoothSwitchOnly && modePtr->getId() != activeModeId) {
751                 ALOGV("%s ignores %s because it's non-VRR and smooth switch only."
752                       " Current mode = %s",
753                       formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
754                       to_string(activeMode).c_str());
755                 continue;
756             }
757 
758             // Layers with default seamlessness vote for the current mode group if
759             // there are layers with seamlessness=SeamedAndSeamless and for the default
760             // mode group otherwise. In second case, if the current mode group is different
761             // from the default, this means a layer with seamlessness=SeamedAndSeamless has just
762             // disappeared.
763             const bool isInPolicyForDefault = modePtr->getGroup() == anchorGroup;
764             if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
765                 ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
766                       to_string(*modePtr).c_str(), to_string(activeMode).c_str());
767                 continue;
768             }
769 
770             const bool inPrimaryPhysicalRange =
771                     policy->primaryRanges.physical.includes(modePtr->getPeakFps());
772             const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps);
773             if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) ||
774                  !inPrimaryRenderRange) &&
775                 !(layer.focused &&
776                   (layer.vote == LayerVoteType::ExplicitDefault ||
777                    layer.vote == LayerVoteType::ExplicitExact))) {
778                 // Only focused layers with ExplicitDefault frame rate settings are allowed to score
779                 // refresh rates outside the primary range.
780                 continue;
781             }
782 
783             const float layerScore = calculateLayerScoreLocked(layer, fps, isSeamlessSwitch);
784             const float weightedLayerScore = weight * layerScore;
785 
786             // Layer with fixed source has a special consideration which depends on the
787             // mConfig.frameRateMultipleThreshold. We don't want these layers to score
788             // refresh rates above the threshold, but we also don't want to favor the lower
789             // ones by having a greater number of layers scoring them. Instead, we calculate
790             // the score independently for these layers and later decide which
791             // refresh rates to add it. For example, desired 24 fps with 120 Hz threshold should not
792             // score 120 Hz, but desired 60 fps should contribute to the score.
793             const bool fixedSourceLayer = [](LayerVoteType vote) {
794                 switch (vote) {
795                     case LayerVoteType::ExplicitExactOrMultiple:
796                     case LayerVoteType::Heuristic:
797                         return true;
798                     case LayerVoteType::NoVote:
799                     case LayerVoteType::Min:
800                     case LayerVoteType::Max:
801                     case LayerVoteType::ExplicitDefault:
802                     case LayerVoteType::ExplicitExact:
803                     case LayerVoteType::ExplicitGte:
804                     case LayerVoteType::ExplicitCategory:
805                         return false;
806                 }
807             }(layer.vote);
808             const bool layerBelowThreshold = mConfig.frameRateMultipleThreshold != 0 &&
809                     layer.desiredRefreshRate <
810                             Fps::fromValue(mConfig.frameRateMultipleThreshold / 2);
811             if (fixedSourceLayer && layerBelowThreshold) {
812                 const bool modeAboveThreshold =
813                         modePtr->getPeakFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold);
814                 if (modeAboveThreshold) {
815                     ALOGV("%s gives %s (%s(%s)) fixed source (above threshold) score of %.4f",
816                           formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
817                           to_string(modePtr->getPeakFps()).c_str(),
818                           to_string(modePtr->getVsyncRate()).c_str(), layerScore);
819                     fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore;
820                 } else {
821                     ALOGV("%s gives %s (%s(%s)) fixed source (below threshold) score of %.4f",
822                           formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
823                           to_string(modePtr->getPeakFps()).c_str(),
824                           to_string(modePtr->getVsyncRate()).c_str(), layerScore);
825                     fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore;
826                 }
827             } else {
828                 ALOGV("%s gives %s (%s(%s)) score of %.4f", formatLayerInfo(layer, weight).c_str(),
829                       to_string(fps).c_str(), to_string(modePtr->getPeakFps()).c_str(),
830                       to_string(modePtr->getVsyncRate()).c_str(), layerScore);
831                 overallScore += weightedLayerScore;
832             }
833         }
834     }
835 
836     // We want to find the best refresh rate without the fixed source layers,
837     // so we could know whether we should add the modeAboveThreshold scores or not.
838     // If the best refresh rate is already above the threshold, it means that
839     // some non-fixed source layers already scored it, so we can just add the score
840     // for all fixed source layers, even the ones that are above the threshold.
841     const bool maxScoreAboveThreshold = [&] {
842         if (mConfig.frameRateMultipleThreshold == 0 || scores.empty()) {
843             return false;
844         }
845 
846         const auto maxScoreIt =
847                 std::max_element(scores.begin(), scores.end(),
848                                  [](RefreshRateScore max, RefreshRateScore current) {
849                                      return current.overallScore > max.overallScore;
850                                  });
851         ALOGV("%s (%s(%s)) is the best refresh rate without fixed source layers. It is %s the "
852               "threshold for "
853               "refresh rate multiples",
854               to_string(maxScoreIt->frameRateMode.fps).c_str(),
855               to_string(maxScoreIt->frameRateMode.modePtr->getPeakFps()).c_str(),
856               to_string(maxScoreIt->frameRateMode.modePtr->getVsyncRate()).c_str(),
857               maxScoreAboveThreshold ? "above" : "below");
858         return maxScoreIt->frameRateMode.modePtr->getPeakFps() >=
859                 Fps::fromValue(mConfig.frameRateMultipleThreshold);
860     }();
861 
862     // Now we can add the fixed rate layers score
863     for (auto& [frameRateMode, overallScore, fixedRateBelowThresholdLayersScore] : scores) {
864         overallScore += fixedRateBelowThresholdLayersScore.modeBelowThreshold;
865         if (maxScoreAboveThreshold) {
866             overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold;
867         }
868         ALOGV("%s (%s(%s)) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(),
869               to_string(frameRateMode.modePtr->getPeakFps()).c_str(),
870               to_string(frameRateMode.modePtr->getVsyncRate()).c_str(), overallScore);
871     }
872 
873     // Now that we scored all the refresh rates we need to pick the one that got the highest
874     // overallScore. Sort the scores based on their overallScore in descending order of priority.
875     const RefreshRateOrder refreshRateOrder =
876             maxVoteLayers > 0 ? RefreshRateOrder::Descending : RefreshRateOrder::Ascending;
877     std::sort(scores.begin(), scores.end(),
878               RefreshRateScoreComparator{.refreshRateOrder = refreshRateOrder});
879 
880     FrameRateRanking ranking;
881     ranking.reserve(scores.size());
882 
883     std::transform(scores.begin(), scores.end(), back_inserter(ranking),
884                    [](const RefreshRateScore& score) {
885                        return ScoredFrameRate{score.frameRateMode, score.overallScore};
886                    });
887 
888     const bool noLayerScore = std::all_of(scores.begin(), scores.end(), [](RefreshRateScore score) {
889         return score.overallScore == 0;
890     });
891 
892     // TODO(b/364651864): Evaluate correctness of primaryRangeIsSingleRate.
893     if (!mIsVrrDevice.load() && policy->primaryRangeIsSingleRate()) {
894         // If we never scored any layers, then choose the rate from the primary
895         // range instead of picking a random score from the app range.
896         if (noLayerScore) {
897             ALOGV("Layers not scored");
898             const auto descending = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
899             SFTRACE_FORMAT_INSTANT("%s (Layers not scored)",
900                                    to_string(descending.front().frameRateMode.fps).c_str());
901             return {descending, kNoSignals};
902         } else {
903             ALOGV("primaryRangeIsSingleRate");
904             SFTRACE_FORMAT_INSTANT("%s (primaryRangeIsSingleRate)",
905                                    to_string(ranking.front().frameRateMode.fps).c_str());
906             return {ranking, kNoSignals};
907         }
908     }
909 
910     // Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly
911     // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
912     // vote we should not change it if we get a touch event. Only apply touch boost if it will
913     // actually increase the refresh rate over the normal selection.
914     const auto isTouchBoostForExplicitExact = [&]() -> bool {
915         if (supportsAppFrameRateOverrideByContent()) {
916             // Enable touch boost if there are other layers besides exact
917             return explicitExact + noVoteLayers + explicitGteLayers != layers.size();
918         } else {
919             // Enable touch boost if there are no exact layers
920             return explicitExact == 0;
921         }
922     };
923 
924     const auto isTouchBoostForCategory = [&]() -> bool {
925         return explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size();
926     };
927 
928     // This accounts for cases such as games that use `setFrameRate` with Default
929     // compatibility to limit the frame rate, which should not have touch boost.
930     const bool isLateGlobalTouchBoost = signals.touch && explicitDefaultVoteLayers == 0;
931     const bool isLateTouchBoost = isLateGlobalTouchBoost || isAppTouchBoost;
932     if (isLateTouchBoost && isTouchBoostForExplicitExact() && isTouchBoostForCategory()) {
933         const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
934         using fps_approx_ops::operator<;
935 
936         if (scores.front().frameRateMode.fps <= touchRefreshRates.front().frameRateMode.fps) {
937             ALOGV("Touch Boost [late]");
938             SFTRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
939                                    to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
940             return {touchRefreshRates, GlobalSignals{.touch = true}};
941         }
942     }
943 
944     // If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
945     // current config
946     if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) {
947         ALOGV("preferredDisplayMode");
948         const auto ascendingWithPreferred =
949                 rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, activeMode.getId());
950         SFTRACE_FORMAT_INSTANT("%s (preferredDisplayMode)",
951                                to_string(ascendingWithPreferred.front().frameRateMode.fps).c_str());
952         return {ascendingWithPreferred, kNoSignals};
953     }
954 
955     ALOGV("%s (scored)", to_string(ranking.front().frameRateMode.fps).c_str());
956     SFTRACE_FORMAT_INSTANT("%s (scored)", to_string(ranking.front().frameRateMode.fps).c_str());
957     return {ranking, kNoSignals};
958 }
959 
getFrameRateOverrides(const std::vector<LayerRequirement> & layers,Fps displayRefreshRate,GlobalSignals globalSignals) const960 auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequirement>& layers,
961                                                 Fps displayRefreshRate,
962                                                 GlobalSignals globalSignals) const
963         -> UidToFrameRateOverride {
964     SFTRACE_CALL();
965     if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Disabled) {
966         return {};
967     }
968 
969     ALOGV("%s: %zu layers", __func__, layers.size());
970     std::lock_guard lock(mLock);
971 
972     const auto* policyPtr = getCurrentPolicyLocked();
973     // We don't want to run lower than 30fps
974     // TODO(b/297600226): revise this for dVRR
975     const Fps minFrameRate = std::max(policyPtr->appRequestRanges.render.min, 30_Hz, isApproxLess);
976 
977     using fps_approx_ops::operator/;
978     const unsigned numMultiples = displayRefreshRate / minFrameRate;
979 
980     std::vector<std::pair<Fps, float>> scoredFrameRates;
981     scoredFrameRates.reserve(numMultiples);
982 
983     for (unsigned n = numMultiples; n > 0; n--) {
984         const Fps divisor = displayRefreshRate / n;
985         if (mConfig.enableFrameRateOverride ==
986                     Config::FrameRateOverride::AppOverrideNativeRefreshRates &&
987             !isNativeRefreshRate(divisor)) {
988             continue;
989         }
990 
991         if (policyPtr->appRequestRanges.render.includes(divisor)) {
992             ALOGV("%s: adding %s as a potential frame rate", __func__, to_string(divisor).c_str());
993             scoredFrameRates.emplace_back(divisor, 0);
994         }
995     }
996 
997     const auto layersByUid = groupLayersByUid(layers);
998     UidToFrameRateOverride frameRateOverrides;
999     for (const auto& [uid, layersWithSameUid] : layersByUid) {
1000         // Look for cases that should not have frame rate overrides.
1001         bool hasExplicitExactOrMultiple = false;
1002         bool hasExplicitDefault = false;
1003         bool hasHighHint = false;
1004         bool hasSkipOverrideLayer = false;
1005         for (const auto& layer : layersWithSameUid) {
1006             switch (layer->vote) {
1007                 case LayerVoteType::ExplicitExactOrMultiple:
1008                     hasExplicitExactOrMultiple = true;
1009                     break;
1010                 case LayerVoteType::ExplicitDefault:
1011                     hasExplicitDefault = true;
1012                     break;
1013                 case LayerVoteType::ExplicitCategory:
1014                     if (layer->frameRateCategory == FrameRateCategory::HighHint) {
1015                         hasHighHint = true;
1016                     }
1017                     break;
1018                 case LayerVoteType::Max:
1019                 case LayerVoteType::Heuristic:
1020                     hasSkipOverrideLayer = true;
1021                     break;
1022                 default:
1023                     // No action
1024                     break;
1025             }
1026             if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint &&
1027                 hasSkipOverrideLayer) {
1028                 break;
1029             }
1030         }
1031 
1032         if (hasSkipOverrideLayer) {
1033             ALOGV("%s: Skipping due to vote(s): uid=%d", __func__, uid);
1034             continue;
1035         }
1036 
1037         // Layers with ExplicitExactOrMultiple expect touch boost
1038         if (globalSignals.touch && hasExplicitExactOrMultiple) {
1039             continue;
1040         }
1041 
1042         // Mirrors getRankedFrameRates. If there is no ExplicitDefault, expect touch boost and
1043         // skip frame rate override.
1044         if (hasHighHint && !hasExplicitDefault) {
1045             continue;
1046         }
1047 
1048         for (auto& [_, score] : scoredFrameRates) {
1049             score = 0;
1050         }
1051 
1052         for (const auto& layer : layersWithSameUid) {
1053             if (layer->isNoVote() || layer->frameRateCategory == FrameRateCategory::NoPreference ||
1054                 layer->vote == LayerVoteType::Min) {
1055                 continue;
1056             }
1057 
1058             LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
1059                                         layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
1060                                         layer->vote != LayerVoteType::ExplicitExact &&
1061                                         layer->vote != LayerVoteType::ExplicitGte &&
1062                                         layer->vote != LayerVoteType::ExplicitCategory,
1063                                 "Invalid layer vote type for frame rate overrides");
1064             for (auto& [fps, score] : scoredFrameRates) {
1065                 constexpr bool isSeamlessSwitch = true;
1066                 const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch);
1067                 score += layer->weight * layerScore;
1068             }
1069         }
1070 
1071         // If we never scored any layers, we don't have a preferred frame rate
1072         if (std::all_of(scoredFrameRates.begin(), scoredFrameRates.end(),
1073                         [](const auto& scoredFrameRate) {
1074                             const auto [_, score] = scoredFrameRate;
1075                             return score == 0;
1076                         })) {
1077             continue;
1078         }
1079 
1080         // Now that we scored all the refresh rates we need to pick the lowest refresh rate
1081         // that got the highest score.
1082         const auto [overrideFps, _] =
1083                 *std::max_element(scoredFrameRates.begin(), scoredFrameRates.end(),
1084                                   [](const auto& lhsPair, const auto& rhsPair) {
1085                                       const float lhs = lhsPair.second;
1086                                       const float rhs = rhsPair.second;
1087                                       return lhs < rhs && !ScoredFrameRate::scoresEqual(lhs, rhs);
1088                                   });
1089         ALOGV("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid);
1090         SFTRACE_FORMAT_INSTANT("%s: overriding to %s for uid=%d", __func__,
1091                                to_string(overrideFps).c_str(), uid);
1092         if (SFTRACE_ENABLED() && FlagManager::getInstance().trace_frame_rate_override()) {
1093             std::stringstream ss;
1094             ss << "FrameRateOverride " << uid;
1095             SFTRACE_INT(ss.str().c_str(), overrideFps.getIntValue());
1096         }
1097         frameRateOverrides.emplace(uid, overrideFps);
1098     }
1099 
1100     return frameRateOverrides;
1101 }
1102 
onKernelTimerChanged(ftl::Optional<DisplayModeId> desiredModeIdOpt,bool timerExpired) const1103 ftl::Optional<FrameRateMode> RefreshRateSelector::onKernelTimerChanged(
1104         ftl::Optional<DisplayModeId> desiredModeIdOpt, bool timerExpired) const {
1105     std::lock_guard lock(mLock);
1106 
1107     const auto current =
1108             desiredModeIdOpt
1109                     .and_then([this](DisplayModeId modeId)
1110                                       REQUIRES(mLock) { return mDisplayModes.get(modeId); })
1111                     .transform([](const DisplayModePtr& modePtr) {
1112                         return FrameRateMode{modePtr->getPeakFps(), ftl::as_non_null(modePtr)};
1113                     })
1114                     .or_else([this] {
1115                         ftl::FakeGuard guard(mLock);
1116                         return std::make_optional(getActiveModeLocked());
1117                     })
1118                     .value();
1119 
1120     const DisplayModePtr& min = mMinRefreshRateModeIt->second;
1121     if (current.modePtr->getId() == min->getId()) {
1122         return {};
1123     }
1124 
1125     return timerExpired ? FrameRateMode{min->getPeakFps(), ftl::as_non_null(min)} : current;
1126 }
1127 
getMinRefreshRateByPolicyLocked() const1128 const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const {
1129     const auto& activeMode = *getActiveModeLocked().modePtr;
1130 
1131     for (const FrameRateMode& mode : mPrimaryFrameRates) {
1132         if (activeMode.getGroup() == mode.modePtr->getGroup()) {
1133             return mode.modePtr.get();
1134         }
1135     }
1136 
1137     ALOGE("Can't find min refresh rate by policy with the same mode group as the current mode %s",
1138           to_string(activeMode).c_str());
1139 
1140     // Default to the lowest refresh rate.
1141     return mPrimaryFrameRates.front().modePtr.get();
1142 }
1143 
getMaxRefreshRateByPolicyLocked(int anchorGroup) const1144 const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
1145     const ftl::NonNull<DisplayModePtr>* maxByAnchor = &mPrimaryFrameRates.back().modePtr;
1146     const ftl::NonNull<DisplayModePtr>* max = &mPrimaryFrameRates.back().modePtr;
1147 
1148     bool maxByAnchorFound = false;
1149     for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) {
1150         using namespace fps_approx_ops;
1151         if (it->modePtr->getPeakFps() > (*max)->getPeakFps()) {
1152             max = &it->modePtr;
1153         }
1154 
1155         if (anchorGroup == it->modePtr->getGroup() &&
1156             it->modePtr->getPeakFps() >= (*maxByAnchor)->getPeakFps()) {
1157             maxByAnchorFound = true;
1158             maxByAnchor = &it->modePtr;
1159         }
1160     }
1161 
1162     if (maxByAnchorFound) {
1163         return maxByAnchor->get();
1164     }
1165 
1166     ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup);
1167 
1168     // Default to the highest refresh rate.
1169     return max->get();
1170 }
1171 
rankFrameRates(std::optional<int> anchorGroupOpt,RefreshRateOrder refreshRateOrder,std::optional<DisplayModeId> preferredDisplayModeOpt,const RankFrameRatesPredicate & predicate) const1172 auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt,
1173                                          RefreshRateOrder refreshRateOrder,
1174                                          std::optional<DisplayModeId> preferredDisplayModeOpt,
1175                                          const RankFrameRatesPredicate& predicate) const
1176         -> FrameRateRanking {
1177     using fps_approx_ops::operator<;
1178     const char* const whence = __func__;
1179 
1180     // find the highest frame rate for each display mode
1181     ftl::SmallMap<DisplayModeId, Fps, 8> maxRenderRateForMode;
1182     const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
1183     if (ascending) {
1184         // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
1185         //  use a lower frame rate when we want Ascending frame rates.
1186         for (const auto& frameRateMode : mPrimaryFrameRates) {
1187             if (anchorGroupOpt && frameRateMode.modePtr->getGroup() != anchorGroupOpt) {
1188                 continue;
1189             }
1190 
1191             const auto [iter, _] = maxRenderRateForMode.try_emplace(frameRateMode.modePtr->getId(),
1192                                                                     frameRateMode.fps);
1193             if (iter->second < frameRateMode.fps) {
1194                 iter->second = frameRateMode.fps;
1195             }
1196         }
1197     }
1198 
1199     std::deque<ScoredFrameRate> ranking;
1200     const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) {
1201         const auto& modePtr = frameRateMode.modePtr;
1202         if ((anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) ||
1203             !predicate(frameRateMode)) {
1204             return;
1205         }
1206 
1207         const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
1208         const auto id = modePtr->getId();
1209         if (ascending && frameRateMode.fps < *maxRenderRateForMode.get(id)) {
1210             // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
1211             //  use a lower frame rate when we want Ascending frame rates.
1212             return;
1213         }
1214 
1215         float score = calculateDistanceScoreFromMaxLocked(frameRateMode.fps);
1216 
1217         if (ascending) {
1218             score = 1.0f / score;
1219         }
1220 
1221         constexpr float kScore = std::numeric_limits<float>::max();
1222         if (preferredDisplayModeOpt) {
1223             if (*preferredDisplayModeOpt == modePtr->getId()) {
1224                 ranking.emplace_front(ScoredFrameRate{frameRateMode, kScore});
1225                 return;
1226             }
1227             constexpr float kNonPreferredModePenalty = 0.95f;
1228             score *= kNonPreferredModePenalty;
1229         } else if (ascending && id == getMinRefreshRateByPolicyLocked()->getId()) {
1230             // TODO(b/266481656): Once this bug is fixed, we can remove this workaround
1231             //  and actually use a lower frame rate when we want Ascending frame rates.
1232             ranking.emplace_front(ScoredFrameRate{frameRateMode, kScore});
1233             return;
1234         }
1235 
1236         ALOGV("%s(%s) %s (%s(%s)) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(),
1237               to_string(frameRateMode.fps).c_str(), to_string(modePtr->getPeakFps()).c_str(),
1238               to_string(modePtr->getVsyncRate()).c_str(), score);
1239         ranking.emplace_back(ScoredFrameRate{frameRateMode, score});
1240     };
1241 
1242     if (refreshRateOrder == RefreshRateOrder::Ascending) {
1243         std::for_each(mPrimaryFrameRates.begin(), mPrimaryFrameRates.end(), rankFrameRate);
1244     } else {
1245         std::for_each(mPrimaryFrameRates.rbegin(), mPrimaryFrameRates.rend(), rankFrameRate);
1246     }
1247 
1248     if (!ranking.empty() || !anchorGroupOpt) {
1249         return {ranking.begin(), ranking.end()};
1250     }
1251 
1252     ALOGW("Can't find %s refresh rate by policy with the same mode group"
1253           " as the mode group %d",
1254           refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());
1255 
1256     constexpr std::optional<int> kNoAnchorGroup = std::nullopt;
1257     return rankFrameRates(kNoAnchorGroup, refreshRateOrder, preferredDisplayModeOpt);
1258 }
1259 
getActiveMode() const1260 FrameRateMode RefreshRateSelector::getActiveMode() const {
1261     std::lock_guard lock(mLock);
1262     return getActiveModeLocked();
1263 }
1264 
getActiveModeLocked() const1265 const FrameRateMode& RefreshRateSelector::getActiveModeLocked() const {
1266     return *mActiveModeOpt;
1267 }
1268 
setActiveMode(DisplayModeId modeId,Fps renderFrameRate)1269 void RefreshRateSelector::setActiveMode(DisplayModeId modeId, Fps renderFrameRate) {
1270     std::lock_guard lock(mLock);
1271 
1272     // Invalidate the cached invocation to getRankedFrameRates. This forces
1273     // the refresh rate to be recomputed on the next call to getRankedFrameRates.
1274     mGetRankedFrameRatesCache.reset();
1275 
1276     const auto activeModeOpt = mDisplayModes.get(modeId);
1277     LOG_ALWAYS_FATAL_IF(!activeModeOpt);
1278 
1279     mActiveModeOpt.emplace(FrameRateMode{renderFrameRate, ftl::as_non_null(activeModeOpt->get())});
1280     mIsVrrDevice = FlagManager::getInstance().vrr_config() &&
1281             activeModeOpt->get()->getVrrConfig().has_value();
1282 }
1283 
RefreshRateSelector(DisplayModes modes,DisplayModeId activeModeId,Config config)1284 RefreshRateSelector::RefreshRateSelector(DisplayModes modes, DisplayModeId activeModeId,
1285                                          Config config)
1286       : mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
1287     initializeIdleTimer(mConfig.legacyIdleTimerTimeout);
1288     FTL_FAKE_GUARD(kMainThreadContext, updateDisplayModes(std::move(modes), activeModeId));
1289 }
1290 
initializeIdleTimer(std::chrono::milliseconds timeout)1291 void RefreshRateSelector::initializeIdleTimer(std::chrono::milliseconds timeout) {
1292     if (timeout > 0ms) {
1293         mIdleTimer.emplace(
1294                 "IdleTimer", timeout,
1295                 [this] {
1296                     std::scoped_lock lock(mIdleTimerCallbacksMutex);
1297                     if (const auto callbacks = getIdleTimerCallbacks()) {
1298                         callbacks->onReset();
1299                     }
1300                 },
1301                 [this] {
1302                     std::scoped_lock lock(mIdleTimerCallbacksMutex);
1303                     if (const auto callbacks = getIdleTimerCallbacks()) {
1304                         callbacks->onExpired();
1305                     }
1306                 });
1307     }
1308 }
1309 
updateDisplayModes(DisplayModes modes,DisplayModeId activeModeId)1310 void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) {
1311     std::lock_guard lock(mLock);
1312 
1313     // Invalidate the cached invocation to getRankedFrameRates. This forces
1314     // the refresh rate to be recomputed on the next call to getRankedFrameRates.
1315     mGetRankedFrameRatesCache.reset();
1316 
1317     mDisplayModes = std::move(modes);
1318     const auto activeModeOpt = mDisplayModes.get(activeModeId);
1319     LOG_ALWAYS_FATAL_IF(!activeModeOpt);
1320     mActiveModeOpt = FrameRateMode{activeModeOpt->get()->getPeakFps(),
1321                                    ftl::as_non_null(activeModeOpt->get())};
1322 
1323     const auto sortedModes = sortByRefreshRate(mDisplayModes);
1324     mMinRefreshRateModeIt = sortedModes.front();
1325     mMaxRefreshRateModeIt = sortedModes.back();
1326 
1327     // Reset the policy because the old one may no longer be valid.
1328     mDisplayManagerPolicy = {};
1329     mDisplayManagerPolicy.defaultMode = activeModeId;
1330 
1331     mFrameRateOverrideConfig = [&] {
1332         switch (mConfig.enableFrameRateOverride) {
1333             case Config::FrameRateOverride::Disabled:
1334             case Config::FrameRateOverride::AppOverride:
1335             case Config::FrameRateOverride::Enabled:
1336                 return mConfig.enableFrameRateOverride;
1337             case Config::FrameRateOverride::AppOverrideNativeRefreshRates:
1338                 return shouldEnableFrameRateOverride(sortedModes)
1339                         ? Config::FrameRateOverride::AppOverrideNativeRefreshRates
1340                         : Config::FrameRateOverride::Disabled;
1341         }
1342     }();
1343 
1344     if (mConfig.enableFrameRateOverride ==
1345         Config::FrameRateOverride::AppOverrideNativeRefreshRates) {
1346         for (const auto& [_, mode] : mDisplayModes) {
1347             mAppOverrideNativeRefreshRates.try_emplace(mode->getPeakFps(), ftl::unit);
1348         }
1349     }
1350 
1351     constructAvailableRefreshRates();
1352 }
1353 
isPolicyValidLocked(const Policy & policy) const1354 bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const {
1355     // defaultMode must be a valid mode, and within the given refresh rate range.
1356     if (const auto mode = mDisplayModes.get(policy.defaultMode)) {
1357         if (!policy.primaryRanges.physical.includes(mode->get()->getPeakFps())) {
1358             ALOGE("Default mode is not in the primary range.");
1359             return false;
1360         }
1361     } else {
1362         ALOGE("Default mode is not found.");
1363         return false;
1364     }
1365 
1366     const auto& primaryRanges = policy.primaryRanges;
1367     const auto& appRequestRanges = policy.appRequestRanges;
1368     ALOGE_IF(!appRequestRanges.physical.includes(primaryRanges.physical),
1369              "Physical range is invalid: primary: %s appRequest: %s",
1370              to_string(primaryRanges.physical).c_str(),
1371              to_string(appRequestRanges.physical).c_str());
1372     ALOGE_IF(!appRequestRanges.render.includes(primaryRanges.render),
1373              "Render range is invalid: primary: %s appRequest: %s",
1374              to_string(primaryRanges.render).c_str(), to_string(appRequestRanges.render).c_str());
1375 
1376     return primaryRanges.valid() && appRequestRanges.valid();
1377 }
1378 
setPolicy(const PolicyVariant & policy)1379 auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyResult {
1380     Policy oldPolicy;
1381     PhysicalDisplayId displayId;
1382     {
1383         std::lock_guard lock(mLock);
1384         oldPolicy = *getCurrentPolicyLocked();
1385 
1386         const bool valid = ftl::match(
1387                 policy,
1388                 [this](const auto& policy) {
1389                     ftl::FakeGuard guard(mLock);
1390                     if (!isPolicyValidLocked(policy)) {
1391                         ALOGE("Invalid policy: %s", policy.toString().c_str());
1392                         return false;
1393                     }
1394 
1395                     using T = std::decay_t<decltype(policy)>;
1396 
1397                     if constexpr (std::is_same_v<T, DisplayManagerPolicy>) {
1398                         mDisplayManagerPolicy = policy;
1399                     } else {
1400                         static_assert(std::is_same_v<T, OverridePolicy>);
1401                         mOverridePolicy = policy;
1402                     }
1403                     return true;
1404                 },
1405                 [this](NoOverridePolicy) {
1406                     ftl::FakeGuard guard(mLock);
1407                     mOverridePolicy.reset();
1408                     return true;
1409                 });
1410 
1411         if (!valid) {
1412             return SetPolicyResult::Invalid;
1413         }
1414 
1415         mGetRankedFrameRatesCache.reset();
1416 
1417         const auto& idleScreenConfigOpt = getCurrentPolicyLocked()->idleScreenConfigOpt;
1418         if (idleScreenConfigOpt != oldPolicy.idleScreenConfigOpt) {
1419             if (!idleScreenConfigOpt.has_value()) {
1420                 if (mIdleTimer) {
1421                     // fallback to legacy timer if existed, otherwise pause the old timer
1422                     if (mConfig.legacyIdleTimerTimeout > 0ms) {
1423                         mIdleTimer->setInterval(mConfig.legacyIdleTimerTimeout);
1424                         mIdleTimer->resume();
1425                     } else {
1426                         mIdleTimer->pause();
1427                     }
1428                 }
1429             } else if (idleScreenConfigOpt->timeoutMillis > 0) {
1430                 // create a new timer or reconfigure
1431                 const auto timeout = std::chrono::milliseconds{idleScreenConfigOpt->timeoutMillis};
1432                 if (!mIdleTimer) {
1433                     initializeIdleTimer(timeout);
1434                     if (mIdleTimerStarted) {
1435                         mIdleTimer->start();
1436                     }
1437                 } else {
1438                     mIdleTimer->setInterval(timeout);
1439                     mIdleTimer->resume();
1440                 }
1441             } else {
1442                 if (mIdleTimer) {
1443                     mIdleTimer->pause();
1444                 }
1445             }
1446         }
1447 
1448         if (getCurrentPolicyLocked()->similarExceptIdleConfig(oldPolicy)) {
1449             return SetPolicyResult::Unchanged;
1450         }
1451 
1452         constructAvailableRefreshRates();
1453 
1454         displayId = getActiveModeLocked().modePtr->getPhysicalDisplayId();
1455     }
1456 
1457     const unsigned numModeChanges = std::exchange(mNumModeSwitchesInPolicy, 0u);
1458 
1459     ALOGI("Display %s policy changed\n"
1460           "Previous: %s\n"
1461           "Current:  %s\n"
1462           "%u mode changes were performed under the previous policy",
1463           to_string(displayId).c_str(), oldPolicy.toString().c_str(), toString(policy).c_str(),
1464           numModeChanges);
1465 
1466     return SetPolicyResult::Changed;
1467 }
1468 
getCurrentPolicyLocked() const1469 auto RefreshRateSelector::getCurrentPolicyLocked() const -> const Policy* {
1470     return mOverridePolicy ? &mOverridePolicy.value() : &mDisplayManagerPolicy;
1471 }
1472 
getCurrentPolicy() const1473 auto RefreshRateSelector::getCurrentPolicy() const -> Policy {
1474     std::lock_guard lock(mLock);
1475     return *getCurrentPolicyLocked();
1476 }
1477 
getDisplayManagerPolicy() const1478 auto RefreshRateSelector::getDisplayManagerPolicy() const -> Policy {
1479     std::lock_guard lock(mLock);
1480     return mDisplayManagerPolicy;
1481 }
1482 
isModeAllowed(const FrameRateMode & mode) const1483 bool RefreshRateSelector::isModeAllowed(const FrameRateMode& mode) const {
1484     std::lock_guard lock(mLock);
1485     return std::find(mAppRequestFrameRates.begin(), mAppRequestFrameRates.end(), mode) !=
1486             mAppRequestFrameRates.end();
1487 }
1488 
constructAvailableRefreshRates()1489 void RefreshRateSelector::constructAvailableRefreshRates() {
1490     // Filter modes based on current policy and sort on refresh rate.
1491     const Policy* policy = getCurrentPolicyLocked();
1492     ALOGV("%s: %s ", __func__, policy->toString().c_str());
1493 
1494     const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
1495 
1496     const auto filterRefreshRates = [&](const FpsRanges& ranges,
1497                                         const char* rangeName) REQUIRES(mLock) {
1498         const auto filterModes = [&](const DisplayMode& mode) {
1499             return mode.getResolution() == defaultMode->getResolution() &&
1500                     mode.getDpi() == defaultMode->getDpi() &&
1501                     (policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) &&
1502                     ranges.physical.includes(mode.getPeakFps()) &&
1503                     (supportsFrameRateOverride() || ranges.render.includes(mode.getPeakFps()));
1504         };
1505 
1506         auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render);
1507         if (frameRateModes.empty()) {
1508             ALOGW("No matching frame rate modes for %s range. policy: %s", rangeName,
1509                   policy->toString().c_str());
1510             // TODO(b/292105422): Ideally DisplayManager should not send render ranges smaller than
1511             // the min supported. See b/292047939.
1512             //  For not we just ignore the render ranges.
1513             frameRateModes = createFrameRateModes(*policy, filterModes, {});
1514         }
1515         LOG_ALWAYS_FATAL_IF(frameRateModes.empty(),
1516                             "No matching frame rate modes for %s range even after ignoring the "
1517                             "render range. policy: %s",
1518                             rangeName, policy->toString().c_str());
1519 
1520         const auto stringifyModes = [&] {
1521             std::string str;
1522             for (const auto& frameRateMode : frameRateModes) {
1523                 str += to_string(frameRateMode) + " ";
1524             }
1525             return str;
1526         };
1527         ALOGV("%s render rates: %s, isVrrDevice? %d", rangeName, stringifyModes().c_str(),
1528               mIsVrrDevice.load());
1529 
1530         return frameRateModes;
1531     };
1532 
1533     mPrimaryFrameRates = filterRefreshRates(policy->primaryRanges, "primary");
1534     mAppRequestFrameRates = filterRefreshRates(policy->appRequestRanges, "app request");
1535     mAllFrameRates = filterRefreshRates(FpsRanges(getSupportedFrameRateRangeLocked(),
1536                                                   getSupportedFrameRateRangeLocked()),
1537                                         "full frame rates");
1538 }
1539 
isVrrDevice() const1540 bool RefreshRateSelector::isVrrDevice() const {
1541     return mIsVrrDevice;
1542 }
1543 
findClosestKnownFrameRate(Fps frameRate) const1544 Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const {
1545     using namespace fps_approx_ops;
1546 
1547     if (frameRate <= mKnownFrameRates.front()) {
1548         return mKnownFrameRates.front();
1549     }
1550 
1551     if (frameRate >= mKnownFrameRates.back()) {
1552         return mKnownFrameRates.back();
1553     }
1554 
1555     auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate,
1556                                        isStrictlyLess);
1557 
1558     const auto distance1 = std::abs(frameRate.getValue() - lowerBound->getValue());
1559     const auto distance2 = std::abs(frameRate.getValue() - std::prev(lowerBound)->getValue());
1560     return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
1561 }
1562 
getSupportedFrameRates() const1563 std::vector<float> RefreshRateSelector::getSupportedFrameRates() const {
1564     std::scoped_lock lock(mLock);
1565     // TODO(b/356986687) Remove the limit once we have the anchor list implementation.
1566     const size_t frameRatesSize = std::min<size_t>(11, mAllFrameRates.size());
1567     std::vector<float> supportedFrameRates;
1568     supportedFrameRates.reserve(frameRatesSize);
1569     std::transform(mAllFrameRates.rbegin(),
1570                    mAllFrameRates.rbegin() + static_cast<int>(frameRatesSize),
1571                    std::back_inserter(supportedFrameRates),
1572                    [](FrameRateMode mode) { return mode.fps.getValue(); });
1573     return supportedFrameRates;
1574 }
1575 
getSupportedFrameRateRangeLocked() const1576 FpsRange RefreshRateSelector::getSupportedFrameRateRangeLocked() const {
1577     using fps_approx_ops::operator<;
1578     if (mMaxRefreshRateModeIt->second->getPeakFps() < kMinSupportedFrameRate) {
1579         return {mMaxRefreshRateModeIt->second->getPeakFps(), kMinSupportedFrameRate};
1580     }
1581     return {kMinSupportedFrameRate, mMaxRefreshRateModeIt->second->getPeakFps()};
1582 }
1583 
getIdleTimerAction() const1584 auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction {
1585     std::lock_guard lock(mLock);
1586 
1587     const Fps deviceMinFps = mMinRefreshRateModeIt->second->getPeakFps();
1588     const DisplayModePtr& minByPolicy = getMinRefreshRateByPolicyLocked();
1589 
1590     // Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
1591     // the min allowed refresh rate is higher than the device min, we do not want to enable the
1592     // timer.
1593     if (isStrictlyLess(deviceMinFps, minByPolicy->getPeakFps())) {
1594         return KernelIdleTimerAction::TurnOff;
1595     }
1596 
1597     const DisplayModePtr& maxByPolicy =
1598             getMaxRefreshRateByPolicyLocked(getActiveModeLocked().modePtr->getGroup());
1599     if (minByPolicy == maxByPolicy) {
1600         // Turn on the timer when the min of the primary range is below the device min.
1601         if (const Policy* currentPolicy = getCurrentPolicyLocked();
1602             isApproxLess(currentPolicy->primaryRanges.physical.min, deviceMinFps)) {
1603             return KernelIdleTimerAction::TurnOn;
1604         }
1605         return KernelIdleTimerAction::TurnOff;
1606     }
1607 
1608     // Turn on the timer in all other cases.
1609     return KernelIdleTimerAction::TurnOn;
1610 }
1611 
getFrameRateDivisor(Fps displayRefreshRate,Fps layerFrameRate)1612 int RefreshRateSelector::getFrameRateDivisor(Fps displayRefreshRate, Fps layerFrameRate) {
1613     // This calculation needs to be in sync with the java code
1614     // in DisplayManagerService.getDisplayInfoForFrameRateOverride
1615 
1616     // The threshold must be smaller than 0.001 in order to differentiate
1617     // between the fractional pairs (e.g. 59.94 and 60).
1618     constexpr float kThreshold = 0.0009f;
1619     const auto numPeriods = displayRefreshRate.getValue() / layerFrameRate.getValue();
1620     const auto numPeriodsRounded = std::round(numPeriods);
1621     if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
1622         return 0;
1623     }
1624 
1625     return static_cast<int>(numPeriodsRounded);
1626 }
1627 
isFractionalPairOrMultiple(Fps smaller,Fps bigger)1628 bool RefreshRateSelector::isFractionalPairOrMultiple(Fps smaller, Fps bigger) {
1629     if (isStrictlyLess(bigger, smaller)) {
1630         return isFractionalPairOrMultiple(bigger, smaller);
1631     }
1632 
1633     const auto multiplier = std::round(bigger.getValue() / smaller.getValue());
1634     constexpr float kCoef = 1000.f / 1001.f;
1635     return isApproxEqual(bigger, Fps::fromValue(smaller.getValue() * multiplier / kCoef)) ||
1636             isApproxEqual(bigger, Fps::fromValue(smaller.getValue() * multiplier * kCoef));
1637 }
1638 
dump(utils::Dumper & dumper) const1639 void RefreshRateSelector::dump(utils::Dumper& dumper) const {
1640     using namespace std::string_view_literals;
1641 
1642     std::lock_guard lock(mLock);
1643 
1644     const auto activeMode = getActiveModeLocked();
1645     dumper.dump("renderRate"sv, to_string(activeMode.fps));
1646     dumper.dump("activeMode"sv, to_string(*activeMode.modePtr));
1647 
1648     dumper.dump("displayModes"sv);
1649     {
1650         utils::Dumper::Indent indent(dumper);
1651         for (const auto& [id, mode] : mDisplayModes) {
1652             dumper.dump({}, to_string(*mode));
1653         }
1654     }
1655 
1656     dumper.dump("displayManagerPolicy"sv, mDisplayManagerPolicy.toString());
1657 
1658     if (const Policy& currentPolicy = *getCurrentPolicyLocked();
1659         mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
1660         dumper.dump("overridePolicy"sv, currentPolicy.toString());
1661     }
1662 
1663     dumper.dump("frameRateOverrideConfig"sv, *ftl::enum_name(mFrameRateOverrideConfig));
1664 
1665     dumper.dump("idleTimer"sv);
1666     {
1667         utils::Dumper::Indent indent(dumper);
1668         dumper.dump("interval"sv, mIdleTimer.transform(&OneShotTimer::interval));
1669         dumper.dump("controller"sv,
1670                     mConfig.kernelIdleTimerController
1671                             .and_then(&ftl::enum_name<KernelIdleTimerController>)
1672                             .value_or("Platform"sv));
1673     }
1674 }
1675 
getIdleTimerTimeout()1676 std::chrono::milliseconds RefreshRateSelector::getIdleTimerTimeout() {
1677     if (FlagManager::getInstance().idle_screen_refresh_rate_timeout() && mIdleTimer) {
1678         return std::chrono::duration_cast<std::chrono::milliseconds>(mIdleTimer->interval());
1679     }
1680     return mConfig.legacyIdleTimerTimeout;
1681 }
1682 
1683 // TODO(b/293651105): Extract category FpsRange mapping to OEM-configurable config.
getFrameRateCategoryRange(FrameRateCategory category)1684 FpsRange RefreshRateSelector::getFrameRateCategoryRange(FrameRateCategory category) {
1685     switch (category) {
1686         case FrameRateCategory::High:
1687             return FpsRange{kFrameRateCategoryRateHigh, 120_Hz};
1688         case FrameRateCategory::Normal:
1689             return FpsRange{kFrameRateCategoryRateNormal, 120_Hz};
1690         case FrameRateCategory::Low:
1691             return FpsRange{48_Hz, 120_Hz};
1692         case FrameRateCategory::HighHint:
1693         case FrameRateCategory::NoPreference:
1694         case FrameRateCategory::Default:
1695             LOG_ALWAYS_FATAL("Should not get fps range for frame rate category: %s",
1696                              ftl::enum_string(category).c_str());
1697         default:
1698             LOG_ALWAYS_FATAL("Invalid frame rate category for range: %s",
1699                              ftl::enum_string(category).c_str());
1700     }
1701 }
1702 
1703 } // namespace android::scheduler
1704 
1705 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1706 #pragma clang diagnostic pop // ignored "-Wextra"
1707