• 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 // #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 <ftl/enum.h>
32 #include <ftl/fake_guard.h>
33 #include <ftl/match.h>
34 #include <ftl/unit.h>
35 #include <gui/TraceUtils.h>
36 #include <scheduler/FrameRateMode.h>
37 #include <utils/Trace.h>
38 
39 #include "../SurfaceFlingerProperties.h"
40 #include "RefreshRateSelector.h"
41 
42 #undef LOG_TAG
43 #define LOG_TAG "RefreshRateSelector"
44 
45 namespace android::scheduler {
46 namespace {
47 
48 struct RefreshRateScore {
49     FrameRateMode frameRateMode;
50     float overallScore;
51     struct {
52         float modeBelowThreshold;
53         float modeAboveThreshold;
54     } fixedRateBelowThresholdLayersScore;
55 };
56 
57 constexpr RefreshRateSelector::GlobalSignals kNoSignals;
58 
formatLayerInfo(const RefreshRateSelector::LayerRequirement & layer,float weight)59 std::string formatLayerInfo(const RefreshRateSelector::LayerRequirement& layer, float weight) {
60     return base::StringPrintf("%s (type=%s, weight=%.2f, seamlessness=%s) %s", layer.name.c_str(),
61                               ftl::enum_string(layer.vote).c_str(), weight,
62                               ftl::enum_string(layer.seamlessness).c_str(),
63                               to_string(layer.desiredRefreshRate).c_str());
64 }
65 
constructKnownFrameRates(const DisplayModes & modes)66 std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) {
67     std::vector<Fps> knownFrameRates = {24_Hz, 30_Hz, 45_Hz, 60_Hz, 72_Hz};
68     knownFrameRates.reserve(knownFrameRates.size() + modes.size());
69 
70     // Add all supported refresh rates.
71     for (const auto& [id, mode] : modes) {
72         knownFrameRates.push_back(mode->getFps());
73     }
74 
75     // Sort and remove duplicates.
76     std::sort(knownFrameRates.begin(), knownFrameRates.end(), isStrictlyLess);
77     knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
78                                       isApproxEqual),
79                           knownFrameRates.end());
80     return knownFrameRates;
81 }
82 
sortByRefreshRate(const DisplayModes & modes)83 std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes) {
84     std::vector<DisplayModeIterator> sortedModes;
85     sortedModes.reserve(modes.size());
86     for (auto it = modes.begin(); it != modes.end(); ++it) {
87         sortedModes.push_back(it);
88     }
89 
90     std::sort(sortedModes.begin(), sortedModes.end(), [](auto it1, auto it2) {
91         const auto& mode1 = it1->second;
92         const auto& mode2 = it2->second;
93 
94         if (mode1->getVsyncPeriod() == mode2->getVsyncPeriod()) {
95             return mode1->getGroup() > mode2->getGroup();
96         }
97 
98         return mode1->getVsyncPeriod() > mode2->getVsyncPeriod();
99     });
100 
101     return sortedModes;
102 }
103 
divisorRange(Fps fps,FpsRange range,RefreshRateSelector::Config::FrameRateOverride config)104 std::pair<unsigned, unsigned> divisorRange(Fps fps, FpsRange range,
105                                            RefreshRateSelector::Config::FrameRateOverride config) {
106     if (config != RefreshRateSelector::Config::FrameRateOverride::Enabled) {
107         return {1, 1};
108     }
109 
110     using fps_approx_ops::operator/;
111     // use signed type as `fps / range.max` might be 0
112     const auto start = std::max(1, static_cast<int>(fps / range.max) - 1);
113     const auto end = fps /
114             std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate,
115                      fps_approx_ops::operator<);
116 
117     return {start, end};
118 }
119 
shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator> & sortedModes)120 bool shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator>& sortedModes) {
121     for (const auto it1 : sortedModes) {
122         const auto& mode1 = it1->second;
123         for (const auto it2 : sortedModes) {
124             const auto& mode2 = it2->second;
125 
126             if (RefreshRateSelector::getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) {
127                 return true;
128             }
129         }
130     }
131     return false;
132 }
133 
toString(const RefreshRateSelector::PolicyVariant & policy)134 std::string toString(const RefreshRateSelector::PolicyVariant& policy) {
135     using namespace std::string_literals;
136 
137     return ftl::match(
138             policy,
139             [](const RefreshRateSelector::DisplayManagerPolicy& policy) {
140                 return "DisplayManagerPolicy"s + policy.toString();
141             },
142             [](const RefreshRateSelector::OverridePolicy& policy) {
143                 return "OverridePolicy"s + policy.toString();
144             },
145             [](RefreshRateSelector::NoOverridePolicy) { return "NoOverridePolicy"s; });
146 }
147 
148 } // namespace
149 
createFrameRateModes(const Policy & policy,std::function<bool (const DisplayMode &)> && filterModes,const FpsRange & renderRange) const150 auto RefreshRateSelector::createFrameRateModes(
151         const Policy& policy, std::function<bool(const DisplayMode&)>&& filterModes,
152         const FpsRange& renderRange) const -> std::vector<FrameRateMode> {
153     struct Key {
154         Fps fps;
155         int32_t group;
156     };
157 
158     struct KeyLess {
159         bool operator()(const Key& a, const Key& b) const {
160             using namespace fps_approx_ops;
161             if (a.fps != b.fps) {
162                 return a.fps < b.fps;
163             }
164 
165             // For the same fps the order doesn't really matter, but we still
166             // want the behaviour of a strictly less operator.
167             // We use the group id as the secondary ordering for that.
168             return a.group < b.group;
169         }
170     };
171 
172     std::map<Key, DisplayModeIterator, KeyLess> ratesMap;
173     for (auto it = mDisplayModes.begin(); it != mDisplayModes.end(); ++it) {
174         const auto& [id, mode] = *it;
175 
176         if (!filterModes(*mode)) {
177             continue;
178         }
179         const auto [start, end] =
180                 divisorRange(mode->getFps(), renderRange, mConfig.enableFrameRateOverride);
181         for (auto divisor = start; divisor <= end; divisor++) {
182             const auto fps = mode->getFps() / divisor;
183             using fps_approx_ops::operator<;
184             if (divisor > 1 && fps < kMinSupportedFrameRate) {
185                 break;
186             }
187 
188             if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Enabled &&
189                 !renderRange.includes(fps)) {
190                 continue;
191             }
192 
193             if (mConfig.enableFrameRateOverride ==
194                         Config::FrameRateOverride::AppOverrideNativeRefreshRates &&
195                 !isNativeRefreshRate(fps)) {
196                 continue;
197             }
198 
199             const auto [existingIter, emplaceHappened] =
200                     ratesMap.try_emplace(Key{fps, mode->getGroup()}, it);
201             if (emplaceHappened) {
202                 ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(),
203                       to_string(mode->getFps()).c_str());
204             } else {
205                 // If the primary physical range is a single rate, prefer to stay in that rate
206                 // even if there is a lower physical refresh rate available. This would cause more
207                 // cases to stay within the primary physical range
208                 const Fps existingModeFps = existingIter->second->second->getFps();
209                 const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
210                         policy.primaryRanges.physical.includes(existingModeFps);
211                 const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
212                         policy.primaryRanges.physical.includes(mode->getFps());
213                 if (newModeIsPrimaryRange == existingModeIsPrimaryRange) {
214                     // We might need to update the map as we found a lower refresh rate
215                     if (isStrictlyLess(mode->getFps(), existingModeFps)) {
216                         existingIter->second = it;
217                         ALOGV("%s: changing %s (%s) as we found a lower physical rate", __func__,
218                               to_string(fps).c_str(), to_string(mode->getFps()).c_str());
219                     }
220                 } else if (newModeIsPrimaryRange) {
221                     existingIter->second = it;
222                     ALOGV("%s: changing %s (%s) to stay in the primary range", __func__,
223                           to_string(fps).c_str(), to_string(mode->getFps()).c_str());
224                 }
225             }
226         }
227     }
228 
229     std::vector<FrameRateMode> frameRateModes;
230     frameRateModes.reserve(ratesMap.size());
231     for (const auto& [key, mode] : ratesMap) {
232         frameRateModes.emplace_back(FrameRateMode{key.fps, ftl::as_non_null(mode->second)});
233     }
234 
235     // We always want that the lowest frame rate will be corresponding to the
236     // lowest mode for power saving.
237     const auto lowestRefreshRateIt =
238             std::min_element(frameRateModes.begin(), frameRateModes.end(),
239                              [](const FrameRateMode& lhs, const FrameRateMode& rhs) {
240                                  return isStrictlyLess(lhs.modePtr->getFps(),
241                                                        rhs.modePtr->getFps());
242                              });
243     frameRateModes.erase(frameRateModes.begin(), lowestRefreshRateIt);
244 
245     return frameRateModes;
246 }
247 
248 struct RefreshRateSelector::RefreshRateScoreComparator {
operator ()android::scheduler::RefreshRateSelector::RefreshRateScoreComparator249     bool operator()(const RefreshRateScore& lhs, const RefreshRateScore& rhs) const {
250         const auto& [frameRateMode, overallScore, _] = lhs;
251 
252         std::string name = to_string(frameRateMode);
253 
254         ALOGV("%s sorting scores %.2f", name.c_str(), overallScore);
255 
256         if (!ScoredFrameRate::scoresEqual(overallScore, rhs.overallScore)) {
257             return overallScore > rhs.overallScore;
258         }
259 
260         if (refreshRateOrder == RefreshRateOrder::Descending) {
261             using fps_approx_ops::operator>;
262             return frameRateMode.fps > rhs.frameRateMode.fps;
263         } else {
264             using fps_approx_ops::operator<;
265             return frameRateMode.fps < rhs.frameRateMode.fps;
266         }
267     }
268 
269     const RefreshRateOrder refreshRateOrder;
270 };
271 
toString() const272 std::string RefreshRateSelector::Policy::toString() const {
273     return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
274                               ", primaryRanges=%s, appRequestRanges=%s}",
275                               defaultMode.value(), allowGroupSwitching ? "true" : "false",
276                               to_string(primaryRanges).c_str(),
277                               to_string(appRequestRanges).c_str());
278 }
279 
getDisplayFrames(nsecs_t layerPeriod,nsecs_t displayPeriod) const280 std::pair<nsecs_t, nsecs_t> RefreshRateSelector::getDisplayFrames(nsecs_t layerPeriod,
281                                                                   nsecs_t displayPeriod) const {
282     auto [quotient, remainder] = std::div(layerPeriod, displayPeriod);
283     if (remainder <= MARGIN_FOR_PERIOD_CALCULATION ||
284         std::abs(remainder - displayPeriod) <= MARGIN_FOR_PERIOD_CALCULATION) {
285         quotient++;
286         remainder = 0;
287     }
288 
289     return {quotient, remainder};
290 }
291 
calculateNonExactMatchingLayerScoreLocked(const LayerRequirement & layer,Fps refreshRate) const292 float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const LayerRequirement& layer,
293                                                                      Fps refreshRate) const {
294     constexpr float kScoreForFractionalPairs = .8f;
295 
296     const auto displayPeriod = refreshRate.getPeriodNsecs();
297     const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
298     if (layer.vote == LayerVoteType::ExplicitDefault) {
299         // Find the actual rate the layer will render, assuming
300         // that layerPeriod is the minimal period to render a frame.
301         // For example if layerPeriod is 20ms and displayPeriod is 16ms,
302         // then the actualLayerPeriod will be 32ms, because it is the
303         // smallest multiple of the display period which is >= layerPeriod.
304         auto actualLayerPeriod = displayPeriod;
305         int multiplier = 1;
306         while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
307             multiplier++;
308             actualLayerPeriod = displayPeriod * multiplier;
309         }
310 
311         // Because of the threshold we used above it's possible that score is slightly
312         // above 1.
313         return std::min(1.0f,
314                         static_cast<float>(layerPeriod) / static_cast<float>(actualLayerPeriod));
315     }
316 
317     if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
318         layer.vote == LayerVoteType::Heuristic) {
319         using fps_approx_ops::operator<;
320         if (refreshRate < 60_Hz) {
321             const bool favorsAtLeast60 =
322                     std::find_if(mFrameRatesThatFavorsAtLeast60.begin(),
323                                  mFrameRatesThatFavorsAtLeast60.end(), [&](Fps fps) {
324                                      using fps_approx_ops::operator==;
325                                      return fps == layer.desiredRefreshRate;
326                                  }) != mFrameRatesThatFavorsAtLeast60.end();
327             if (favorsAtLeast60) {
328                 return 0;
329             }
330         }
331 
332         const float multiplier = refreshRate.getValue() / layer.desiredRefreshRate.getValue();
333 
334         // We only want to score this layer as a fractional pair if the content is not
335         // significantly faster than the display rate, at it would cause a significant frame drop.
336         // It is more appropriate to choose a higher display rate even if
337         // a pull-down will be required.
338         constexpr float kMinMultiplier = 0.75f;
339         if (multiplier >= kMinMultiplier &&
340             isFractionalPairOrMultiple(refreshRate, layer.desiredRefreshRate)) {
341             return kScoreForFractionalPairs;
342         }
343 
344         // Calculate how many display vsyncs we need to present a single frame for this
345         // layer
346         const auto [displayFramesQuotient, displayFramesRemainder] =
347                 getDisplayFrames(layerPeriod, displayPeriod);
348         static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
349         if (displayFramesRemainder == 0) {
350             // Layer desired refresh rate matches the display rate.
351             return 1.0f;
352         }
353 
354         if (displayFramesQuotient == 0) {
355             // Layer desired refresh rate is higher than the display rate.
356             return (static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod)) *
357                     (1.0f / (MAX_FRAMES_TO_FIT + 1));
358         }
359 
360         // Layer desired refresh rate is lower than the display rate. Check how well it fits
361         // the cadence.
362         auto diff = std::abs(displayFramesRemainder - (displayPeriod - displayFramesRemainder));
363         int iter = 2;
364         while (diff > MARGIN_FOR_PERIOD_CALCULATION && iter < MAX_FRAMES_TO_FIT) {
365             diff = diff - (displayPeriod - diff);
366             iter++;
367         }
368 
369         return (1.0f / iter);
370     }
371 
372     return 0;
373 }
374 
calculateDistanceScoreFromMax(Fps refreshRate) const375 float RefreshRateSelector::calculateDistanceScoreFromMax(Fps refreshRate) const {
376     const auto& maxFps = mAppRequestFrameRates.back().fps;
377     const float ratio = refreshRate.getValue() / maxFps.getValue();
378     // Use ratio^2 to get a lower score the more we get further from peak
379     return ratio * ratio;
380 }
381 
calculateLayerScoreLocked(const LayerRequirement & layer,Fps refreshRate,bool isSeamlessSwitch) const382 float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
383                                                      bool isSeamlessSwitch) const {
384     ATRACE_CALL();
385     // Slightly prefer seamless switches.
386     constexpr float kSeamedSwitchPenalty = 0.95f;
387     const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
388 
389     // If the layer wants Max, give higher score to the higher refresh rate
390     if (layer.vote == LayerVoteType::Max) {
391         return calculateDistanceScoreFromMax(refreshRate);
392     }
393 
394     if (layer.vote == LayerVoteType::ExplicitExact) {
395         const int divisor = getFrameRateDivisor(refreshRate, layer.desiredRefreshRate);
396         if (supportsAppFrameRateOverrideByContent()) {
397             // Since we support frame rate override, allow refresh rates which are
398             // multiples of the layer's request, as those apps would be throttled
399             // down to run at the desired refresh rate.
400             return divisor > 0;
401         }
402 
403         return divisor == 1;
404     }
405 
406     // If the layer frame rate is a divisor of the refresh rate it should score
407     // the highest score.
408     if (getFrameRateDivisor(refreshRate, layer.desiredRefreshRate) > 0) {
409         return 1.0f * seamlessness;
410     }
411 
412     // The layer frame rate is not a divisor of the refresh rate,
413     // there is a small penalty attached to the score to favor the frame rates
414     // the exactly matches the display refresh rate or a multiple.
415     constexpr float kNonExactMatchingPenalty = 0.95f;
416     return calculateNonExactMatchingLayerScoreLocked(layer, refreshRate) * seamlessness *
417             kNonExactMatchingPenalty;
418 }
419 
getRankedFrameRates(const std::vector<LayerRequirement> & layers,GlobalSignals signals) const420 auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement>& layers,
421                                               GlobalSignals signals) const -> RankedFrameRates {
422     std::lock_guard lock(mLock);
423 
424     if (mGetRankedFrameRatesCache &&
425         mGetRankedFrameRatesCache->arguments == std::make_pair(layers, signals)) {
426         return mGetRankedFrameRatesCache->result;
427     }
428 
429     const auto result = getRankedFrameRatesLocked(layers, signals);
430     mGetRankedFrameRatesCache = GetRankedFrameRatesCache{{layers, signals}, result};
431     return result;
432 }
433 
getRankedFrameRatesLocked(const std::vector<LayerRequirement> & layers,GlobalSignals signals) const434 auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers,
435                                                     GlobalSignals signals) const
436         -> RankedFrameRates {
437     using namespace fps_approx_ops;
438     ATRACE_CALL();
439     ALOGV("%s: %zu layers", __func__, layers.size());
440 
441     const auto& activeMode = *getActiveModeLocked().modePtr;
442 
443     // Keep the display at max frame rate for the duration of powering on the display.
444     if (signals.powerOnImminent) {
445         ALOGV("Power On Imminent");
446         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending);
447         ATRACE_FORMAT_INSTANT("%s (Power On Imminent)",
448                               to_string(ranking.front().frameRateMode.fps).c_str());
449         return {ranking, GlobalSignals{.powerOnImminent = true}};
450     }
451 
452     int noVoteLayers = 0;
453     int minVoteLayers = 0;
454     int maxVoteLayers = 0;
455     int explicitDefaultVoteLayers = 0;
456     int explicitExactOrMultipleVoteLayers = 0;
457     int explicitExact = 0;
458     int seamedFocusedLayers = 0;
459 
460     for (const auto& layer : layers) {
461         switch (layer.vote) {
462             case LayerVoteType::NoVote:
463                 noVoteLayers++;
464                 break;
465             case LayerVoteType::Min:
466                 minVoteLayers++;
467                 break;
468             case LayerVoteType::Max:
469                 maxVoteLayers++;
470                 break;
471             case LayerVoteType::ExplicitDefault:
472                 explicitDefaultVoteLayers++;
473                 break;
474             case LayerVoteType::ExplicitExactOrMultiple:
475                 explicitExactOrMultipleVoteLayers++;
476                 break;
477             case LayerVoteType::ExplicitExact:
478                 explicitExact++;
479                 break;
480             case LayerVoteType::Heuristic:
481                 break;
482         }
483 
484         if (layer.seamlessness == Seamlessness::SeamedAndSeamless && layer.focused) {
485             seamedFocusedLayers++;
486         }
487     }
488 
489     const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
490             explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0;
491 
492     const Policy* policy = getCurrentPolicyLocked();
493     const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
494 
495     // If the default mode group is different from the group of current mode,
496     // this means a layer requesting a seamed mode switch just disappeared and
497     // we should switch back to the default group.
498     // However if a seamed layer is still present we anchor around the group
499     // of the current mode, in order to prevent unnecessary seamed mode switches
500     // (e.g. when pausing a video playback).
501     const auto anchorGroup =
502             seamedFocusedLayers > 0 ? activeMode.getGroup() : defaultMode->getGroup();
503 
504     // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
505     // selected a refresh rate to see if we should apply touch boost.
506     if (signals.touch && !hasExplicitVoteLayers) {
507         ALOGV("Touch Boost");
508         const auto ranking = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
509         ATRACE_FORMAT_INSTANT("%s (Touch Boost)",
510                               to_string(ranking.front().frameRateMode.fps).c_str());
511         return {ranking, GlobalSignals{.touch = true}};
512     }
513 
514     // If the primary range consists of a single refresh rate then we can only
515     // move out the of range if layers explicitly request a different refresh
516     // rate.
517     if (!signals.touch && signals.idle &&
518         !(policy->primaryRangeIsSingleRate() && hasExplicitVoteLayers)) {
519         ALOGV("Idle");
520         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
521         ATRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str());
522         return {ranking, GlobalSignals{.idle = true}};
523     }
524 
525     if (layers.empty() || noVoteLayers == layers.size()) {
526         ALOGV("No layers with votes");
527         const auto ranking = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
528         ATRACE_FORMAT_INSTANT("%s (No layers with votes)",
529                               to_string(ranking.front().frameRateMode.fps).c_str());
530         return {ranking, kNoSignals};
531     }
532 
533     // Only if all layers want Min we should return Min
534     if (noVoteLayers + minVoteLayers == layers.size()) {
535         ALOGV("All layers Min");
536         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
537         ATRACE_FORMAT_INSTANT("%s (All layers Min)",
538                               to_string(ranking.front().frameRateMode.fps).c_str());
539         return {ranking, kNoSignals};
540     }
541 
542     // Find the best refresh rate based on score
543     std::vector<RefreshRateScore> scores;
544     scores.reserve(mAppRequestFrameRates.size());
545 
546     for (const FrameRateMode& it : mAppRequestFrameRates) {
547         scores.emplace_back(RefreshRateScore{it, 0.0f});
548     }
549 
550     for (const auto& layer : layers) {
551         ALOGV("Calculating score for %s (%s, weight %.2f, desired %.2f) ", layer.name.c_str(),
552               ftl::enum_string(layer.vote).c_str(), layer.weight,
553               layer.desiredRefreshRate.getValue());
554         if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min) {
555             continue;
556         }
557 
558         const auto weight = layer.weight;
559 
560         for (auto& [mode, overallScore, fixedRateBelowThresholdLayersScore] : scores) {
561             const auto& [fps, modePtr] = mode;
562             const bool isSeamlessSwitch = modePtr->getGroup() == activeMode.getGroup();
563 
564             if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
565                 ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
566                       formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
567                       to_string(activeMode).c_str());
568                 continue;
569             }
570 
571             if (layer.seamlessness == Seamlessness::SeamedAndSeamless && !isSeamlessSwitch &&
572                 !layer.focused) {
573                 ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
574                       " Current mode = %s",
575                       formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(),
576                       to_string(activeMode).c_str());
577                 continue;
578             }
579 
580             // Layers with default seamlessness vote for the current mode group if
581             // there are layers with seamlessness=SeamedAndSeamless and for the default
582             // mode group otherwise. In second case, if the current mode group is different
583             // from the default, this means a layer with seamlessness=SeamedAndSeamless has just
584             // disappeared.
585             const bool isInPolicyForDefault = modePtr->getGroup() == anchorGroup;
586             if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
587                 ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
588                       to_string(*modePtr).c_str(), to_string(activeMode).c_str());
589                 continue;
590             }
591 
592             const bool inPrimaryPhysicalRange =
593                     policy->primaryRanges.physical.includes(modePtr->getFps());
594             const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps);
595             if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) ||
596                  !inPrimaryRenderRange) &&
597                 !(layer.focused &&
598                   (layer.vote == LayerVoteType::ExplicitDefault ||
599                    layer.vote == LayerVoteType::ExplicitExact))) {
600                 // Only focused layers with ExplicitDefault frame rate settings are allowed to score
601                 // refresh rates outside the primary range.
602                 continue;
603             }
604 
605             const float layerScore = calculateLayerScoreLocked(layer, fps, isSeamlessSwitch);
606             const float weightedLayerScore = weight * layerScore;
607 
608             // Layer with fixed source has a special consideration which depends on the
609             // mConfig.frameRateMultipleThreshold. We don't want these layers to score
610             // refresh rates above the threshold, but we also don't want to favor the lower
611             // ones by having a greater number of layers scoring them. Instead, we calculate
612             // the score independently for these layers and later decide which
613             // refresh rates to add it. For example, desired 24 fps with 120 Hz threshold should not
614             // score 120 Hz, but desired 60 fps should contribute to the score.
615             const bool fixedSourceLayer = [](LayerVoteType vote) {
616                 switch (vote) {
617                     case LayerVoteType::ExplicitExactOrMultiple:
618                     case LayerVoteType::Heuristic:
619                         return true;
620                     case LayerVoteType::NoVote:
621                     case LayerVoteType::Min:
622                     case LayerVoteType::Max:
623                     case LayerVoteType::ExplicitDefault:
624                     case LayerVoteType::ExplicitExact:
625                         return false;
626                 }
627             }(layer.vote);
628             const bool layerBelowThreshold = mConfig.frameRateMultipleThreshold != 0 &&
629                     layer.desiredRefreshRate <
630                             Fps::fromValue(mConfig.frameRateMultipleThreshold / 2);
631             if (fixedSourceLayer && layerBelowThreshold) {
632                 const bool modeAboveThreshold =
633                         modePtr->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold);
634                 if (modeAboveThreshold) {
635                     ALOGV("%s gives %s (%s) fixed source (above threshold) score of %.4f",
636                           formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
637                           to_string(modePtr->getFps()).c_str(), layerScore);
638                     fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore;
639                 } else {
640                     ALOGV("%s gives %s (%s) fixed source (below threshold) score of %.4f",
641                           formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(),
642                           to_string(modePtr->getFps()).c_str(), layerScore);
643                     fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore;
644                 }
645             } else {
646                 ALOGV("%s gives %s (%s) score of %.4f", formatLayerInfo(layer, weight).c_str(),
647                       to_string(fps).c_str(), to_string(modePtr->getFps()).c_str(), layerScore);
648                 overallScore += weightedLayerScore;
649             }
650         }
651     }
652 
653     // We want to find the best refresh rate without the fixed source layers,
654     // so we could know whether we should add the modeAboveThreshold scores or not.
655     // If the best refresh rate is already above the threshold, it means that
656     // some non-fixed source layers already scored it, so we can just add the score
657     // for all fixed source layers, even the ones that are above the threshold.
658     const bool maxScoreAboveThreshold = [&] {
659         if (mConfig.frameRateMultipleThreshold == 0 || scores.empty()) {
660             return false;
661         }
662 
663         const auto maxScoreIt =
664                 std::max_element(scores.begin(), scores.end(),
665                                  [](RefreshRateScore max, RefreshRateScore current) {
666                                      return current.overallScore > max.overallScore;
667                                  });
668         ALOGV("%s (%s) is the best refresh rate without fixed source layers. It is %s the "
669               "threshold for "
670               "refresh rate multiples",
671               to_string(maxScoreIt->frameRateMode.fps).c_str(),
672               to_string(maxScoreIt->frameRateMode.modePtr->getFps()).c_str(),
673               maxScoreAboveThreshold ? "above" : "below");
674         return maxScoreIt->frameRateMode.modePtr->getFps() >=
675                 Fps::fromValue(mConfig.frameRateMultipleThreshold);
676     }();
677 
678     // Now we can add the fixed rate layers score
679     for (auto& [frameRateMode, overallScore, fixedRateBelowThresholdLayersScore] : scores) {
680         overallScore += fixedRateBelowThresholdLayersScore.modeBelowThreshold;
681         if (maxScoreAboveThreshold) {
682             overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold;
683         }
684         ALOGV("%s (%s) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(),
685               to_string(frameRateMode.modePtr->getFps()).c_str(), overallScore);
686     }
687 
688     // Now that we scored all the refresh rates we need to pick the one that got the highest
689     // overallScore. Sort the scores based on their overallScore in descending order of priority.
690     const RefreshRateOrder refreshRateOrder =
691             maxVoteLayers > 0 ? RefreshRateOrder::Descending : RefreshRateOrder::Ascending;
692     std::sort(scores.begin(), scores.end(),
693               RefreshRateScoreComparator{.refreshRateOrder = refreshRateOrder});
694 
695     FrameRateRanking ranking;
696     ranking.reserve(scores.size());
697 
698     std::transform(scores.begin(), scores.end(), back_inserter(ranking),
699                    [](const RefreshRateScore& score) {
700                        return ScoredFrameRate{score.frameRateMode, score.overallScore};
701                    });
702 
703     const bool noLayerScore = std::all_of(scores.begin(), scores.end(), [](RefreshRateScore score) {
704         return score.overallScore == 0;
705     });
706 
707     if (policy->primaryRangeIsSingleRate()) {
708         // If we never scored any layers, then choose the rate from the primary
709         // range instead of picking a random score from the app range.
710         if (noLayerScore) {
711             ALOGV("Layers not scored");
712             const auto descending = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
713             ATRACE_FORMAT_INSTANT("%s (Layers not scored)",
714                                   to_string(descending.front().frameRateMode.fps).c_str());
715             return {descending, kNoSignals};
716         } else {
717             ATRACE_FORMAT_INSTANT("%s (primaryRangeIsSingleRate)",
718                                   to_string(ranking.front().frameRateMode.fps).c_str());
719             return {ranking, kNoSignals};
720         }
721     }
722 
723     // Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly
724     // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
725     // vote we should not change it if we get a touch event. Only apply touch boost if it will
726     // actually increase the refresh rate over the normal selection.
727     const bool touchBoostForExplicitExact = [&] {
728         if (supportsAppFrameRateOverrideByContent()) {
729             // Enable touch boost if there are other layers besides exact
730             return explicitExact + noVoteLayers != layers.size();
731         } else {
732             // Enable touch boost if there are no exact layers
733             return explicitExact == 0;
734         }
735     }();
736 
737     const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
738     using fps_approx_ops::operator<;
739 
740     if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
741         scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) {
742         ALOGV("Touch Boost");
743         ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
744                               to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
745         return {touchRefreshRates, GlobalSignals{.touch = true}};
746     }
747 
748     // If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
749     // current config
750     if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) {
751         const auto ascendingWithPreferred =
752                 rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, activeMode.getId());
753         ATRACE_FORMAT_INSTANT("%s (preferredDisplayMode)",
754                               to_string(ascendingWithPreferred.front().frameRateMode.fps).c_str());
755         return {ascendingWithPreferred, kNoSignals};
756     }
757 
758     ATRACE_FORMAT_INSTANT("%s (scored))", to_string(ranking.front().frameRateMode.fps).c_str());
759     return {ranking, kNoSignals};
760 }
761 
762 using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
763 using PerUidLayerRequirements = std::unordered_map<uid_t, LayerRequirementPtrs>;
764 
groupLayersByUid(const std::vector<RefreshRateSelector::LayerRequirement> & layers)765 PerUidLayerRequirements groupLayersByUid(
766         const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
767     PerUidLayerRequirements layersByUid;
768     for (const auto& layer : layers) {
769         const auto it = layersByUid.emplace(layer.ownerUid, LayerRequirementPtrs()).first;
770         auto& layersWithSameUid = it->second;
771         layersWithSameUid.push_back(&layer);
772     }
773 
774     // Remove uids that can't have a frame rate override
775     for (auto it = layersByUid.begin(); it != layersByUid.end();) {
776         const auto& layersWithSameUid = it->second;
777         bool skipUid = false;
778         for (const auto& layer : layersWithSameUid) {
779             using LayerVoteType = RefreshRateSelector::LayerVoteType;
780 
781             if (layer->vote == LayerVoteType::Max || layer->vote == LayerVoteType::Heuristic) {
782                 skipUid = true;
783                 break;
784             }
785         }
786         if (skipUid) {
787             it = layersByUid.erase(it);
788         } else {
789             ++it;
790         }
791     }
792 
793     return layersByUid;
794 }
795 
getFrameRateOverrides(const std::vector<LayerRequirement> & layers,Fps displayRefreshRate,GlobalSignals globalSignals) const796 auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequirement>& layers,
797                                                 Fps displayRefreshRate,
798                                                 GlobalSignals globalSignals) const
799         -> UidToFrameRateOverride {
800     ATRACE_CALL();
801     if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Disabled) {
802         return {};
803     }
804 
805     ALOGV("%s: %zu layers", __func__, layers.size());
806     std::lock_guard lock(mLock);
807 
808     const auto* policyPtr = getCurrentPolicyLocked();
809     // We don't want to run lower than 30fps
810     const Fps minFrameRate = std::max(policyPtr->appRequestRanges.render.min, 30_Hz, isApproxLess);
811 
812     using fps_approx_ops::operator/;
813     const unsigned numMultiples = displayRefreshRate / minFrameRate;
814 
815     std::vector<std::pair<Fps, float>> scoredFrameRates;
816     scoredFrameRates.reserve(numMultiples);
817 
818     for (unsigned n = numMultiples; n > 0; n--) {
819         const Fps divisor = displayRefreshRate / n;
820         if (mConfig.enableFrameRateOverride ==
821                     Config::FrameRateOverride::AppOverrideNativeRefreshRates &&
822             !isNativeRefreshRate(divisor)) {
823             continue;
824         }
825 
826         if (policyPtr->appRequestRanges.render.includes(divisor)) {
827             ALOGV("%s: adding %s as a potential frame rate", __func__, to_string(divisor).c_str());
828             scoredFrameRates.emplace_back(divisor, 0);
829         }
830     }
831 
832     const auto layersByUid = groupLayersByUid(layers);
833     UidToFrameRateOverride frameRateOverrides;
834     for (const auto& [uid, layersWithSameUid] : layersByUid) {
835         // Layers with ExplicitExactOrMultiple expect touch boost
836         const bool hasExplicitExactOrMultiple =
837                 std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(),
838                             [](const auto& layer) {
839                                 return layer->vote == LayerVoteType::ExplicitExactOrMultiple;
840                             });
841 
842         if (globalSignals.touch && hasExplicitExactOrMultiple) {
843             continue;
844         }
845 
846         for (auto& [_, score] : scoredFrameRates) {
847             score = 0;
848         }
849 
850         for (const auto& layer : layersWithSameUid) {
851             if (layer->vote == LayerVoteType::NoVote || layer->vote == LayerVoteType::Min) {
852                 continue;
853             }
854 
855             LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
856                                 layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
857                                 layer->vote != LayerVoteType::ExplicitExact);
858             for (auto& [fps, score] : scoredFrameRates) {
859                 constexpr bool isSeamlessSwitch = true;
860                 const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch);
861                 score += layer->weight * layerScore;
862             }
863         }
864 
865         // If we never scored any layers, we don't have a preferred frame rate
866         if (std::all_of(scoredFrameRates.begin(), scoredFrameRates.end(),
867                         [](const auto& scoredFrameRate) {
868                             const auto [_, score] = scoredFrameRate;
869                             return score == 0;
870                         })) {
871             continue;
872         }
873 
874         // Now that we scored all the refresh rates we need to pick the lowest refresh rate
875         // that got the highest score.
876         const auto [overrideFps, _] =
877                 *std::max_element(scoredFrameRates.begin(), scoredFrameRates.end(),
878                                   [](const auto& lhsPair, const auto& rhsPair) {
879                                       const float lhs = lhsPair.second;
880                                       const float rhs = rhsPair.second;
881                                       return lhs < rhs && !ScoredFrameRate::scoresEqual(lhs, rhs);
882                                   });
883         ALOGV("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid);
884         frameRateOverrides.emplace(uid, overrideFps);
885     }
886 
887     return frameRateOverrides;
888 }
889 
onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,bool timerExpired) const890 ftl::Optional<FrameRateMode> RefreshRateSelector::onKernelTimerChanged(
891         std::optional<DisplayModeId> desiredActiveModeId, bool timerExpired) const {
892     std::lock_guard lock(mLock);
893 
894     const auto current = [&]() REQUIRES(mLock) -> FrameRateMode {
895         if (desiredActiveModeId) {
896             const auto& modePtr = mDisplayModes.get(*desiredActiveModeId)->get();
897             return FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)};
898         }
899 
900         return getActiveModeLocked();
901     }();
902 
903     const DisplayModePtr& min = mMinRefreshRateModeIt->second;
904     if (current.modePtr->getId() == min->getId()) {
905         return {};
906     }
907 
908     return timerExpired ? FrameRateMode{min->getFps(), ftl::as_non_null(min)} : current;
909 }
910 
getMinRefreshRateByPolicyLocked() const911 const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const {
912     const auto& activeMode = *getActiveModeLocked().modePtr;
913 
914     for (const FrameRateMode& mode : mPrimaryFrameRates) {
915         if (activeMode.getGroup() == mode.modePtr->getGroup()) {
916             return mode.modePtr.get();
917         }
918     }
919 
920     ALOGE("Can't find min refresh rate by policy with the same mode group as the current mode %s",
921           to_string(activeMode).c_str());
922 
923     // Default to the lowest refresh rate.
924     return mPrimaryFrameRates.front().modePtr.get();
925 }
926 
getMaxRefreshRateByPolicyLocked(int anchorGroup) const927 const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
928     const ftl::NonNull<DisplayModePtr>* maxByAnchor = &mPrimaryFrameRates.back().modePtr;
929     const ftl::NonNull<DisplayModePtr>* max = &mPrimaryFrameRates.back().modePtr;
930 
931     bool maxByAnchorFound = false;
932     for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) {
933         using namespace fps_approx_ops;
934         if (it->modePtr->getFps() > (*max)->getFps()) {
935             max = &it->modePtr;
936         }
937 
938         if (anchorGroup == it->modePtr->getGroup() &&
939             it->modePtr->getFps() >= (*maxByAnchor)->getFps()) {
940             maxByAnchorFound = true;
941             maxByAnchor = &it->modePtr;
942         }
943     }
944 
945     if (maxByAnchorFound) {
946         return maxByAnchor->get();
947     }
948 
949     ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup);
950 
951     // Default to the highest refresh rate.
952     return max->get();
953 }
954 
rankFrameRates(std::optional<int> anchorGroupOpt,RefreshRateOrder refreshRateOrder,std::optional<DisplayModeId> preferredDisplayModeOpt) const955 auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt,
956                                          RefreshRateOrder refreshRateOrder,
957                                          std::optional<DisplayModeId> preferredDisplayModeOpt) const
958         -> FrameRateRanking {
959     using fps_approx_ops::operator<;
960     const char* const whence = __func__;
961 
962     // find the highest frame rate for each display mode
963     ftl::SmallMap<DisplayModeId, Fps, 8> maxRenderRateForMode;
964     const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
965     if (ascending) {
966         // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
967         //  use a lower frame rate when we want Ascending frame rates.
968         for (const auto& frameRateMode : mPrimaryFrameRates) {
969             if (anchorGroupOpt && frameRateMode.modePtr->getGroup() != anchorGroupOpt) {
970                 continue;
971             }
972 
973             const auto [iter, _] = maxRenderRateForMode.try_emplace(frameRateMode.modePtr->getId(),
974                                                                     frameRateMode.fps);
975             if (iter->second < frameRateMode.fps) {
976                 iter->second = frameRateMode.fps;
977             }
978         }
979     }
980 
981     std::deque<ScoredFrameRate> ranking;
982     const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) {
983         const auto& modePtr = frameRateMode.modePtr;
984         if (anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) {
985             return;
986         }
987 
988         const bool ascending = (refreshRateOrder == RefreshRateOrder::Ascending);
989         const auto id = modePtr->getId();
990         if (ascending && frameRateMode.fps < *maxRenderRateForMode.get(id)) {
991             // TODO(b/266481656): Once this bug is fixed, we can remove this workaround and actually
992             //  use a lower frame rate when we want Ascending frame rates.
993             return;
994         }
995 
996         float score = calculateDistanceScoreFromMax(frameRateMode.fps);
997 
998         if (ascending) {
999             score = 1.0f / score;
1000         }
1001 
1002         constexpr float kScore = std::numeric_limits<float>::max();
1003         if (preferredDisplayModeOpt) {
1004             if (*preferredDisplayModeOpt == modePtr->getId()) {
1005                 ranking.emplace_front(ScoredFrameRate{frameRateMode, kScore});
1006                 return;
1007             }
1008             constexpr float kNonPreferredModePenalty = 0.95f;
1009             score *= kNonPreferredModePenalty;
1010         } else if (ascending && id == getMinRefreshRateByPolicyLocked()->getId()) {
1011             // TODO(b/266481656): Once this bug is fixed, we can remove this workaround
1012             //  and actually use a lower frame rate when we want Ascending frame rates.
1013             ranking.emplace_front(ScoredFrameRate{frameRateMode, kScore});
1014             return;
1015         }
1016 
1017         ALOGV("%s(%s) %s (%s) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(),
1018               to_string(frameRateMode.fps).c_str(), to_string(modePtr->getFps()).c_str(), score);
1019         ranking.emplace_back(ScoredFrameRate{frameRateMode, score});
1020     };
1021 
1022     if (refreshRateOrder == RefreshRateOrder::Ascending) {
1023         std::for_each(mPrimaryFrameRates.begin(), mPrimaryFrameRates.end(), rankFrameRate);
1024     } else {
1025         std::for_each(mPrimaryFrameRates.rbegin(), mPrimaryFrameRates.rend(), rankFrameRate);
1026     }
1027 
1028     if (!ranking.empty() || !anchorGroupOpt) {
1029         return {ranking.begin(), ranking.end()};
1030     }
1031 
1032     ALOGW("Can't find %s refresh rate by policy with the same mode group"
1033           " as the mode group %d",
1034           refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());
1035 
1036     constexpr std::optional<int> kNoAnchorGroup = std::nullopt;
1037     return rankFrameRates(kNoAnchorGroup, refreshRateOrder, preferredDisplayModeOpt);
1038 }
1039 
getActiveMode() const1040 FrameRateMode RefreshRateSelector::getActiveMode() const {
1041     std::lock_guard lock(mLock);
1042     return getActiveModeLocked();
1043 }
1044 
getActiveModeLocked() const1045 const FrameRateMode& RefreshRateSelector::getActiveModeLocked() const {
1046     return *mActiveModeOpt;
1047 }
1048 
setActiveMode(DisplayModeId modeId,Fps renderFrameRate)1049 void RefreshRateSelector::setActiveMode(DisplayModeId modeId, Fps renderFrameRate) {
1050     std::lock_guard lock(mLock);
1051 
1052     // Invalidate the cached invocation to getRankedFrameRates. This forces
1053     // the refresh rate to be recomputed on the next call to getRankedFrameRates.
1054     mGetRankedFrameRatesCache.reset();
1055 
1056     const auto activeModeOpt = mDisplayModes.get(modeId);
1057     LOG_ALWAYS_FATAL_IF(!activeModeOpt);
1058 
1059     mActiveModeOpt.emplace(FrameRateMode{renderFrameRate, ftl::as_non_null(activeModeOpt->get())});
1060 }
1061 
RefreshRateSelector(DisplayModes modes,DisplayModeId activeModeId,Config config)1062 RefreshRateSelector::RefreshRateSelector(DisplayModes modes, DisplayModeId activeModeId,
1063                                          Config config)
1064       : mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
1065     initializeIdleTimer();
1066     FTL_FAKE_GUARD(kMainThreadContext, updateDisplayModes(std::move(modes), activeModeId));
1067 }
1068 
initializeIdleTimer()1069 void RefreshRateSelector::initializeIdleTimer() {
1070     if (mConfig.idleTimerTimeout > 0ms) {
1071         mIdleTimer.emplace(
1072                 "IdleTimer", mConfig.idleTimerTimeout,
1073                 [this] {
1074                     std::scoped_lock lock(mIdleTimerCallbacksMutex);
1075                     if (const auto callbacks = getIdleTimerCallbacks()) {
1076                         callbacks->onReset();
1077                     }
1078                 },
1079                 [this] {
1080                     std::scoped_lock lock(mIdleTimerCallbacksMutex);
1081                     if (const auto callbacks = getIdleTimerCallbacks()) {
1082                         callbacks->onExpired();
1083                     }
1084                 });
1085     }
1086 }
1087 
updateDisplayModes(DisplayModes modes,DisplayModeId activeModeId)1088 void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) {
1089     std::lock_guard lock(mLock);
1090 
1091     // Invalidate the cached invocation to getRankedFrameRates. This forces
1092     // the refresh rate to be recomputed on the next call to getRankedFrameRates.
1093     mGetRankedFrameRatesCache.reset();
1094 
1095     mDisplayModes = std::move(modes);
1096     const auto activeModeOpt = mDisplayModes.get(activeModeId);
1097     LOG_ALWAYS_FATAL_IF(!activeModeOpt);
1098     mActiveModeOpt =
1099             FrameRateMode{activeModeOpt->get()->getFps(), ftl::as_non_null(activeModeOpt->get())};
1100 
1101     const auto sortedModes = sortByRefreshRate(mDisplayModes);
1102     mMinRefreshRateModeIt = sortedModes.front();
1103     mMaxRefreshRateModeIt = sortedModes.back();
1104 
1105     // Reset the policy because the old one may no longer be valid.
1106     mDisplayManagerPolicy = {};
1107     mDisplayManagerPolicy.defaultMode = activeModeId;
1108 
1109     mFrameRateOverrideConfig = [&] {
1110         switch (mConfig.enableFrameRateOverride) {
1111             case Config::FrameRateOverride::Disabled:
1112             case Config::FrameRateOverride::AppOverride:
1113             case Config::FrameRateOverride::Enabled:
1114                 return mConfig.enableFrameRateOverride;
1115             case Config::FrameRateOverride::AppOverrideNativeRefreshRates:
1116                 return shouldEnableFrameRateOverride(sortedModes)
1117                         ? Config::FrameRateOverride::AppOverrideNativeRefreshRates
1118                         : Config::FrameRateOverride::Disabled;
1119         }
1120     }();
1121 
1122     if (mConfig.enableFrameRateOverride ==
1123         Config::FrameRateOverride::AppOverrideNativeRefreshRates) {
1124         for (const auto& [_, mode] : mDisplayModes) {
1125             mAppOverrideNativeRefreshRates.try_emplace(mode->getFps(), ftl::unit);
1126         }
1127     }
1128 
1129     constructAvailableRefreshRates();
1130 }
1131 
isPolicyValidLocked(const Policy & policy) const1132 bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const {
1133     // defaultMode must be a valid mode, and within the given refresh rate range.
1134     if (const auto mode = mDisplayModes.get(policy.defaultMode)) {
1135         if (!policy.primaryRanges.physical.includes(mode->get()->getFps())) {
1136             ALOGE("Default mode is not in the primary range.");
1137             return false;
1138         }
1139     } else {
1140         ALOGE("Default mode is not found.");
1141         return false;
1142     }
1143 
1144     const auto& primaryRanges = policy.primaryRanges;
1145     const auto& appRequestRanges = policy.appRequestRanges;
1146     ALOGE_IF(!appRequestRanges.physical.includes(primaryRanges.physical),
1147              "Physical range is invalid: primary: %s appRequest: %s",
1148              to_string(primaryRanges.physical).c_str(),
1149              to_string(appRequestRanges.physical).c_str());
1150     ALOGE_IF(!appRequestRanges.render.includes(primaryRanges.render),
1151              "Render range is invalid: primary: %s appRequest: %s",
1152              to_string(primaryRanges.render).c_str(), to_string(appRequestRanges.render).c_str());
1153 
1154     return primaryRanges.valid() && appRequestRanges.valid();
1155 }
1156 
setPolicy(const PolicyVariant & policy)1157 auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyResult {
1158     Policy oldPolicy;
1159     PhysicalDisplayId displayId;
1160     {
1161         std::lock_guard lock(mLock);
1162         oldPolicy = *getCurrentPolicyLocked();
1163 
1164         const bool valid = ftl::match(
1165                 policy,
1166                 [this](const auto& policy) {
1167                     ftl::FakeGuard guard(mLock);
1168                     if (!isPolicyValidLocked(policy)) {
1169                         ALOGE("Invalid policy: %s", policy.toString().c_str());
1170                         return false;
1171                     }
1172 
1173                     using T = std::decay_t<decltype(policy)>;
1174 
1175                     if constexpr (std::is_same_v<T, DisplayManagerPolicy>) {
1176                         mDisplayManagerPolicy = policy;
1177                     } else {
1178                         static_assert(std::is_same_v<T, OverridePolicy>);
1179                         mOverridePolicy = policy;
1180                     }
1181                     return true;
1182                 },
1183                 [this](NoOverridePolicy) {
1184                     ftl::FakeGuard guard(mLock);
1185                     mOverridePolicy.reset();
1186                     return true;
1187                 });
1188 
1189         if (!valid) {
1190             return SetPolicyResult::Invalid;
1191         }
1192 
1193         mGetRankedFrameRatesCache.reset();
1194 
1195         if (*getCurrentPolicyLocked() == oldPolicy) {
1196             return SetPolicyResult::Unchanged;
1197         }
1198         constructAvailableRefreshRates();
1199 
1200         displayId = getActiveModeLocked().modePtr->getPhysicalDisplayId();
1201     }
1202 
1203     const unsigned numModeChanges = std::exchange(mNumModeSwitchesInPolicy, 0u);
1204 
1205     ALOGI("Display %s policy changed\n"
1206           "Previous: %s\n"
1207           "Current:  %s\n"
1208           "%u mode changes were performed under the previous policy",
1209           to_string(displayId).c_str(), oldPolicy.toString().c_str(), toString(policy).c_str(),
1210           numModeChanges);
1211 
1212     return SetPolicyResult::Changed;
1213 }
1214 
getCurrentPolicyLocked() const1215 auto RefreshRateSelector::getCurrentPolicyLocked() const -> const Policy* {
1216     return mOverridePolicy ? &mOverridePolicy.value() : &mDisplayManagerPolicy;
1217 }
1218 
getCurrentPolicy() const1219 auto RefreshRateSelector::getCurrentPolicy() const -> Policy {
1220     std::lock_guard lock(mLock);
1221     return *getCurrentPolicyLocked();
1222 }
1223 
getDisplayManagerPolicy() const1224 auto RefreshRateSelector::getDisplayManagerPolicy() const -> Policy {
1225     std::lock_guard lock(mLock);
1226     return mDisplayManagerPolicy;
1227 }
1228 
isModeAllowed(const FrameRateMode & mode) const1229 bool RefreshRateSelector::isModeAllowed(const FrameRateMode& mode) const {
1230     std::lock_guard lock(mLock);
1231     return std::find(mAppRequestFrameRates.begin(), mAppRequestFrameRates.end(), mode) !=
1232             mAppRequestFrameRates.end();
1233 }
1234 
constructAvailableRefreshRates()1235 void RefreshRateSelector::constructAvailableRefreshRates() {
1236     // Filter modes based on current policy and sort on refresh rate.
1237     const Policy* policy = getCurrentPolicyLocked();
1238     ALOGV("%s: %s ", __func__, policy->toString().c_str());
1239 
1240     const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get();
1241 
1242     const auto filterRefreshRates = [&](const FpsRanges& ranges,
1243                                         const char* rangeName) REQUIRES(mLock) {
1244         const auto filterModes = [&](const DisplayMode& mode) {
1245             return mode.getResolution() == defaultMode->getResolution() &&
1246                     mode.getDpi() == defaultMode->getDpi() &&
1247                     (policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) &&
1248                     ranges.physical.includes(mode.getFps()) &&
1249                     (supportsFrameRateOverride() || ranges.render.includes(mode.getFps()));
1250         };
1251 
1252         auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render);
1253         if (frameRateModes.empty()) {
1254             ALOGW("No matching frame rate modes for %s range. policy: %s", rangeName,
1255                   policy->toString().c_str());
1256             // TODO(b/292105422): Ideally DisplayManager should not send render ranges smaller than
1257             // the min supported. See b/292047939.
1258             //  For not we just ignore the render ranges.
1259             frameRateModes = createFrameRateModes(*policy, filterModes, {});
1260         }
1261         LOG_ALWAYS_FATAL_IF(frameRateModes.empty(),
1262                             "No matching frame rate modes for %s range even after ignoring the "
1263                             "render range. policy: %s",
1264                             rangeName, policy->toString().c_str());
1265 
1266         const auto stringifyModes = [&] {
1267             std::string str;
1268             for (const auto& frameRateMode : frameRateModes) {
1269                 str += to_string(frameRateMode) + " ";
1270             }
1271             return str;
1272         };
1273         ALOGV("%s render rates: %s", rangeName, stringifyModes().c_str());
1274 
1275         return frameRateModes;
1276     };
1277 
1278     mPrimaryFrameRates = filterRefreshRates(policy->primaryRanges, "primary");
1279     mAppRequestFrameRates = filterRefreshRates(policy->appRequestRanges, "app request");
1280 }
1281 
findClosestKnownFrameRate(Fps frameRate) const1282 Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const {
1283     using namespace fps_approx_ops;
1284 
1285     if (frameRate <= mKnownFrameRates.front()) {
1286         return mKnownFrameRates.front();
1287     }
1288 
1289     if (frameRate >= mKnownFrameRates.back()) {
1290         return mKnownFrameRates.back();
1291     }
1292 
1293     auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate,
1294                                        isStrictlyLess);
1295 
1296     const auto distance1 = std::abs(frameRate.getValue() - lowerBound->getValue());
1297     const auto distance2 = std::abs(frameRate.getValue() - std::prev(lowerBound)->getValue());
1298     return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
1299 }
1300 
getIdleTimerAction() const1301 auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction {
1302     std::lock_guard lock(mLock);
1303 
1304     const Fps deviceMinFps = mMinRefreshRateModeIt->second->getFps();
1305     const DisplayModePtr& minByPolicy = getMinRefreshRateByPolicyLocked();
1306 
1307     // Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
1308     // the min allowed refresh rate is higher than the device min, we do not want to enable the
1309     // timer.
1310     if (isStrictlyLess(deviceMinFps, minByPolicy->getFps())) {
1311         return KernelIdleTimerAction::TurnOff;
1312     }
1313 
1314     const DisplayModePtr& maxByPolicy =
1315             getMaxRefreshRateByPolicyLocked(getActiveModeLocked().modePtr->getGroup());
1316     if (minByPolicy == maxByPolicy) {
1317         // Turn on the timer when the min of the primary range is below the device min.
1318         if (const Policy* currentPolicy = getCurrentPolicyLocked();
1319             isApproxLess(currentPolicy->primaryRanges.physical.min, deviceMinFps)) {
1320             return KernelIdleTimerAction::TurnOn;
1321         }
1322         return KernelIdleTimerAction::TurnOff;
1323     }
1324 
1325     // Turn on the timer in all other cases.
1326     return KernelIdleTimerAction::TurnOn;
1327 }
1328 
getFrameRateDivisor(Fps displayRefreshRate,Fps layerFrameRate)1329 int RefreshRateSelector::getFrameRateDivisor(Fps displayRefreshRate, Fps layerFrameRate) {
1330     // This calculation needs to be in sync with the java code
1331     // in DisplayManagerService.getDisplayInfoForFrameRateOverride
1332 
1333     // The threshold must be smaller than 0.001 in order to differentiate
1334     // between the fractional pairs (e.g. 59.94 and 60).
1335     constexpr float kThreshold = 0.0009f;
1336     const auto numPeriods = displayRefreshRate.getValue() / layerFrameRate.getValue();
1337     const auto numPeriodsRounded = std::round(numPeriods);
1338     if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
1339         return 0;
1340     }
1341 
1342     return static_cast<int>(numPeriodsRounded);
1343 }
1344 
isFractionalPairOrMultiple(Fps smaller,Fps bigger)1345 bool RefreshRateSelector::isFractionalPairOrMultiple(Fps smaller, Fps bigger) {
1346     if (isStrictlyLess(bigger, smaller)) {
1347         return isFractionalPairOrMultiple(bigger, smaller);
1348     }
1349 
1350     const auto multiplier = std::round(bigger.getValue() / smaller.getValue());
1351     constexpr float kCoef = 1000.f / 1001.f;
1352     return isApproxEqual(bigger, Fps::fromValue(smaller.getValue() * multiplier / kCoef)) ||
1353             isApproxEqual(bigger, Fps::fromValue(smaller.getValue() * multiplier * kCoef));
1354 }
1355 
dump(utils::Dumper & dumper) const1356 void RefreshRateSelector::dump(utils::Dumper& dumper) const {
1357     using namespace std::string_view_literals;
1358 
1359     std::lock_guard lock(mLock);
1360 
1361     const auto activeMode = getActiveModeLocked();
1362     dumper.dump("activeMode"sv, to_string(activeMode));
1363 
1364     dumper.dump("displayModes"sv);
1365     {
1366         utils::Dumper::Indent indent(dumper);
1367         for (const auto& [id, mode] : mDisplayModes) {
1368             dumper.dump({}, to_string(*mode));
1369         }
1370     }
1371 
1372     dumper.dump("displayManagerPolicy"sv, mDisplayManagerPolicy.toString());
1373 
1374     if (const Policy& currentPolicy = *getCurrentPolicyLocked();
1375         mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
1376         dumper.dump("overridePolicy"sv, currentPolicy.toString());
1377     }
1378 
1379     dumper.dump("frameRateOverrideConfig"sv, *ftl::enum_name(mFrameRateOverrideConfig));
1380 
1381     dumper.dump("idleTimer"sv);
1382     {
1383         utils::Dumper::Indent indent(dumper);
1384         dumper.dump("interval"sv, mIdleTimer.transform(&OneShotTimer::interval));
1385         dumper.dump("controller"sv,
1386                     mConfig.kernelIdleTimerController
1387                             .and_then(&ftl::enum_name<KernelIdleTimerController>)
1388                             .value_or("Platform"sv));
1389     }
1390 }
1391 
getIdleTimerTimeout()1392 std::chrono::milliseconds RefreshRateSelector::getIdleTimerTimeout() {
1393     return mConfig.idleTimerTimeout;
1394 }
1395 
1396 } // namespace android::scheduler
1397 
1398 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1399 #pragma clang diagnostic pop // ignored "-Wextra"
1400