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 #include "RefreshRateConfigs.h"
21 #include <android-base/stringprintf.h>
22 #include <utils/Trace.h>
23 #include <chrono>
24 #include <cmath>
25 
26 #undef LOG_TAG
27 #define LOG_TAG "RefreshRateConfigs"
28 
29 namespace android::scheduler {
30 
31 using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
32 using RefreshRate = RefreshRateConfigs::RefreshRate;
33 
layerVoteTypeString(LayerVoteType vote)34 std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) {
35     switch (vote) {
36         case LayerVoteType::NoVote:
37             return "NoVote";
38         case LayerVoteType::Min:
39             return "Min";
40         case LayerVoteType::Max:
41             return "Max";
42         case LayerVoteType::Heuristic:
43             return "Heuristic";
44         case LayerVoteType::ExplicitDefault:
45             return "ExplicitDefault";
46         case LayerVoteType::ExplicitExactOrMultiple:
47             return "ExplicitExactOrMultiple";
48     }
49 }
50 
getRefreshRateForContent(const std::vector<LayerRequirement> & layers) const51 const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(
52         const std::vector<LayerRequirement>& layers) const {
53     std::lock_guard lock(mLock);
54     int contentFramerate = 0;
55     int explicitContentFramerate = 0;
56     for (const auto& layer : layers) {
57         const auto desiredRefreshRateRound = round<int>(layer.desiredRefreshRate);
58         if (layer.vote == LayerVoteType::ExplicitDefault ||
59             layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
60             if (desiredRefreshRateRound > explicitContentFramerate) {
61                 explicitContentFramerate = desiredRefreshRateRound;
62             }
63         } else {
64             if (desiredRefreshRateRound > contentFramerate) {
65                 contentFramerate = desiredRefreshRateRound;
66             }
67         }
68     }
69 
70     if (explicitContentFramerate != 0) {
71         contentFramerate = explicitContentFramerate;
72     } else if (contentFramerate == 0) {
73         contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
74     }
75     ATRACE_INT("ContentFPS", contentFramerate);
76 
77     // Find the appropriate refresh rate with minimal error
78     auto iter = min_element(mPrimaryRefreshRates.cbegin(), mPrimaryRefreshRates.cend(),
79                             [contentFramerate](const auto& lhs, const auto& rhs) -> bool {
80                                 return std::abs(lhs->fps - contentFramerate) <
81                                         std::abs(rhs->fps - contentFramerate);
82                             });
83 
84     // Some content aligns better on higher refresh rate. For example for 45fps we should choose
85     // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
86     // align well with both
87     const RefreshRate* bestSoFar = *iter;
88     constexpr float MARGIN = 0.05f;
89     float ratio = (*iter)->fps / contentFramerate;
90     if (std::abs(std::round(ratio) - ratio) > MARGIN) {
91         while (iter != mPrimaryRefreshRates.cend()) {
92             ratio = (*iter)->fps / contentFramerate;
93 
94             if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
95                 bestSoFar = *iter;
96                 break;
97             }
98             ++iter;
99         }
100     }
101 
102     return *bestSoFar;
103 }
104 
getDisplayFrames(nsecs_t layerPeriod,nsecs_t displayPeriod) const105 std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod,
106                                                                  nsecs_t displayPeriod) const {
107     auto [displayFramesQuot, displayFramesRem] = std::div(layerPeriod, displayPeriod);
108     if (displayFramesRem <= MARGIN_FOR_PERIOD_CALCULATION ||
109         std::abs(displayFramesRem - displayPeriod) <= MARGIN_FOR_PERIOD_CALCULATION) {
110         displayFramesQuot++;
111         displayFramesRem = 0;
112     }
113 
114     return {displayFramesQuot, displayFramesRem};
115 }
116 
getBestRefreshRate(const std::vector<LayerRequirement> & layers,const GlobalSignals & globalSignals,GlobalSignals * outSignalsConsidered) const117 const RefreshRate& RefreshRateConfigs::getBestRefreshRate(
118         const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals,
119         GlobalSignals* outSignalsConsidered) const {
120     ATRACE_CALL();
121     ALOGV("getRefreshRateForContent %zu layers", layers.size());
122 
123     if (outSignalsConsidered) *outSignalsConsidered = {};
124     const auto setTouchConsidered = [&] {
125         if (outSignalsConsidered) {
126             outSignalsConsidered->touch = true;
127         }
128     };
129 
130     const auto setIdleConsidered = [&] {
131         if (outSignalsConsidered) {
132             outSignalsConsidered->idle = true;
133         }
134     };
135 
136     std::lock_guard lock(mLock);
137 
138     int noVoteLayers = 0;
139     int minVoteLayers = 0;
140     int maxVoteLayers = 0;
141     int explicitDefaultVoteLayers = 0;
142     int explicitExactOrMultipleVoteLayers = 0;
143     float maxExplicitWeight = 0;
144     for (const auto& layer : layers) {
145         if (layer.vote == LayerVoteType::NoVote) {
146             noVoteLayers++;
147         } else if (layer.vote == LayerVoteType::Min) {
148             minVoteLayers++;
149         } else if (layer.vote == LayerVoteType::Max) {
150             maxVoteLayers++;
151         } else if (layer.vote == LayerVoteType::ExplicitDefault) {
152             explicitDefaultVoteLayers++;
153             maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
154         } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
155             explicitExactOrMultipleVoteLayers++;
156             maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
157         }
158     }
159 
160     const bool hasExplicitVoteLayers =
161             explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0;
162 
163     // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
164     // selected a refresh rate to see if we should apply touch boost.
165     if (globalSignals.touch && !hasExplicitVoteLayers) {
166         ALOGV("TouchBoost - choose %s", getMaxRefreshRateByPolicyLocked().getName().c_str());
167         setTouchConsidered();
168         return getMaxRefreshRateByPolicyLocked();
169     }
170 
171     // If the primary range consists of a single refresh rate then we can only
172     // move out the of range if layers explicitly request a different refresh
173     // rate.
174     const Policy* policy = getCurrentPolicyLocked();
175     const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max;
176 
177     if (!globalSignals.touch && globalSignals.idle &&
178         !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
179         ALOGV("Idle - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str());
180         setIdleConsidered();
181         return getMinRefreshRateByPolicyLocked();
182     }
183 
184     if (layers.empty() || noVoteLayers == layers.size()) {
185         return getMaxRefreshRateByPolicyLocked();
186     }
187 
188     // Only if all layers want Min we should return Min
189     if (noVoteLayers + minVoteLayers == layers.size()) {
190         ALOGV("all layers Min - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str());
191         return getMinRefreshRateByPolicyLocked();
192     }
193 
194     // Find the best refresh rate based on score
195     std::vector<std::pair<const RefreshRate*, float>> scores;
196     scores.reserve(mAppRequestRefreshRates.size());
197 
198     for (const auto refreshRate : mAppRequestRefreshRates) {
199         scores.emplace_back(refreshRate, 0.0f);
200     }
201 
202     for (const auto& layer : layers) {
203         ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(),
204               layerVoteTypeString(layer.vote).c_str(), layer.weight);
205         if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min) {
206             continue;
207         }
208 
209         auto weight = layer.weight;
210 
211         for (auto i = 0u; i < scores.size(); i++) {
212             bool inPrimaryRange =
213                     scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
214             if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
215                 !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) {
216                 // Only focused layers with ExplicitDefault frame rate settings are allowed to score
217                 // refresh rates outside the primary range.
218                 continue;
219             }
220 
221             // If the layer wants Max, give higher score to the higher refresh rate
222             if (layer.vote == LayerVoteType::Max) {
223                 const auto ratio = scores[i].first->fps / scores.back().first->fps;
224                 // use ratio^2 to get a lower score the more we get further from peak
225                 const auto layerScore = ratio * ratio;
226                 ALOGV("%s (Max, weight %.2f) gives %s score of %.2f", layer.name.c_str(), weight,
227                       scores[i].first->name.c_str(), layerScore);
228                 scores[i].second += weight * layerScore;
229                 continue;
230             }
231 
232             const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod();
233             const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
234             if (layer.vote == LayerVoteType::ExplicitDefault) {
235                 const auto layerScore = [&]() {
236                     // Find the actual rate the layer will render, assuming
237                     // that layerPeriod is the minimal time to render a frame
238                     auto actualLayerPeriod = displayPeriod;
239                     int multiplier = 1;
240                     while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
241                         multiplier++;
242                         actualLayerPeriod = displayPeriod * multiplier;
243                     }
244                     return std::min(1.0f,
245                                     static_cast<float>(layerPeriod) /
246                                             static_cast<float>(actualLayerPeriod));
247                 }();
248 
249                 ALOGV("%s (ExplicitDefault, weight %.2f) %.2fHz gives %s score of %.2f",
250                       layer.name.c_str(), weight, 1e9f / layerPeriod, scores[i].first->name.c_str(),
251                       layerScore);
252                 scores[i].second += weight * layerScore;
253                 continue;
254             }
255 
256             if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
257                 layer.vote == LayerVoteType::Heuristic) {
258                 const auto layerScore = [&] {
259                     // Calculate how many display vsyncs we need to present a single frame for this
260                     // layer
261                     const auto [displayFramesQuot, displayFramesRem] =
262                             getDisplayFrames(layerPeriod, displayPeriod);
263                     static constexpr size_t MAX_FRAMES_TO_FIT =
264                             10; // Stop calculating when score < 0.1
265                     if (displayFramesRem == 0) {
266                         // Layer desired refresh rate matches the display rate.
267                         return 1.0f;
268                     }
269 
270                     if (displayFramesQuot == 0) {
271                         // Layer desired refresh rate is higher the display rate.
272                         return (static_cast<float>(layerPeriod) /
273                                 static_cast<float>(displayPeriod)) *
274                                 (1.0f / (MAX_FRAMES_TO_FIT + 1));
275                     }
276 
277                     // Layer desired refresh rate is lower the display rate. Check how well it fits
278                     // the cadence
279                     auto diff = std::abs(displayFramesRem - (displayPeriod - displayFramesRem));
280                     int iter = 2;
281                     while (diff > MARGIN_FOR_PERIOD_CALCULATION && iter < MAX_FRAMES_TO_FIT) {
282                         diff = diff - (displayPeriod - diff);
283                         iter++;
284                     }
285 
286                     return 1.0f / iter;
287                 }();
288                 ALOGV("%s (%s, weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(),
289                       layerVoteTypeString(layer.vote).c_str(), weight, 1e9f / layerPeriod,
290                       scores[i].first->name.c_str(), layerScore);
291                 scores[i].second += weight * layerScore;
292                 continue;
293             }
294         }
295     }
296 
297     // Now that we scored all the refresh rates we need to pick the one that got the highest score.
298     // In case of a tie we will pick the higher refresh rate if any of the layers wanted Max,
299     // or the lower otherwise.
300     const RefreshRate* bestRefreshRate = maxVoteLayers > 0
301             ? getBestRefreshRate(scores.rbegin(), scores.rend())
302             : getBestRefreshRate(scores.begin(), scores.end());
303 
304     if (primaryRangeIsSingleRate) {
305         // If we never scored any layers, then choose the rate from the primary
306         // range instead of picking a random score from the app range.
307         if (std::all_of(scores.begin(), scores.end(),
308                         [](std::pair<const RefreshRate*, float> p) { return p.second == 0; })) {
309             ALOGV("layers not scored - choose %s",
310                   getMaxRefreshRateByPolicyLocked().getName().c_str());
311             return getMaxRefreshRateByPolicyLocked();
312         } else {
313             return *bestRefreshRate;
314         }
315     }
316 
317     // Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly
318     // interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
319     // vote we should not change it if we get a touch event. Only apply touch boost if it will
320     // actually increase the refresh rate over the normal selection.
321     const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
322 
323     if (globalSignals.touch && explicitDefaultVoteLayers == 0 &&
324         bestRefreshRate->fps < touchRefreshRate.fps) {
325         setTouchConsidered();
326         ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
327         return touchRefreshRate;
328     }
329 
330     return *bestRefreshRate;
331 }
332 
333 template <typename Iter>
getBestRefreshRate(Iter begin,Iter end) const334 const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
335     constexpr auto EPSILON = 0.001f;
336     const RefreshRate* bestRefreshRate = begin->first;
337     float max = begin->second;
338     for (auto i = begin; i != end; ++i) {
339         const auto [refreshRate, score] = *i;
340         ALOGV("%s scores %.2f", refreshRate->name.c_str(), score);
341 
342         ATRACE_INT(refreshRate->name.c_str(), round<int>(score * 100));
343 
344         if (score > max * (1 + EPSILON)) {
345             max = score;
346             bestRefreshRate = refreshRate;
347         }
348     }
349 
350     return bestRefreshRate;
351 }
352 
getAllRefreshRates() const353 const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const {
354     return mRefreshRates;
355 }
356 
getMinRefreshRateByPolicy() const357 const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const {
358     std::lock_guard lock(mLock);
359     return getMinRefreshRateByPolicyLocked();
360 }
361 
getMinRefreshRateByPolicyLocked() const362 const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
363     return *mPrimaryRefreshRates.front();
364 }
365 
getMaxRefreshRateByPolicy() const366 const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
367     std::lock_guard lock(mLock);
368     return getMaxRefreshRateByPolicyLocked();
369 }
370 
getMaxRefreshRateByPolicyLocked() const371 const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
372     return *mPrimaryRefreshRates.back();
373 }
374 
getCurrentRefreshRate() const375 const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const {
376     std::lock_guard lock(mLock);
377     return *mCurrentRefreshRate;
378 }
379 
getCurrentRefreshRateByPolicy() const380 const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
381     std::lock_guard lock(mLock);
382     return getCurrentRefreshRateByPolicyLocked();
383 }
384 
getCurrentRefreshRateByPolicyLocked() const385 const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() const {
386     if (std::find(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(),
387                   mCurrentRefreshRate) != mAppRequestRefreshRates.end()) {
388         return *mCurrentRefreshRate;
389     }
390     return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
391 }
392 
setCurrentConfigId(HwcConfigIndexType configId)393 void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
394     std::lock_guard lock(mLock);
395     mCurrentRefreshRate = mRefreshRates.at(configId).get();
396 }
397 
RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>> & configs,HwcConfigIndexType currentConfigId)398 RefreshRateConfigs::RefreshRateConfigs(
399         const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
400         HwcConfigIndexType currentConfigId)
401       : mKnownFrameRates(constructKnownFrameRates(configs)) {
402     LOG_ALWAYS_FATAL_IF(configs.empty());
403     LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());
404 
405     for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) {
406         const auto& config = configs.at(static_cast<size_t>(configId.value()));
407         const float fps = 1e9f / config->getVsyncPeriod();
408         mRefreshRates.emplace(configId,
409                               std::make_unique<RefreshRate>(configId, config,
410                                                             base::StringPrintf("%.0ffps", fps), fps,
411                                                             RefreshRate::ConstructorTag(0)));
412         if (configId == currentConfigId) {
413             mCurrentRefreshRate = mRefreshRates.at(configId).get();
414         }
415     }
416 
417     std::vector<const RefreshRate*> sortedConfigs;
418     getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
419     mDisplayManagerPolicy.defaultConfig = currentConfigId;
420     mMinSupportedRefreshRate = sortedConfigs.front();
421     mMaxSupportedRefreshRate = sortedConfigs.back();
422     constructAvailableRefreshRates();
423 }
424 
isPolicyValid(const Policy & policy)425 bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
426     // defaultConfig must be a valid config, and within the given refresh rate range.
427     auto iter = mRefreshRates.find(policy.defaultConfig);
428     if (iter == mRefreshRates.end()) {
429         return false;
430     }
431     const RefreshRate& refreshRate = *iter->second;
432     if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) {
433         return false;
434     }
435     return policy.appRequestRange.min <= policy.primaryRange.min &&
436             policy.appRequestRange.max >= policy.primaryRange.max;
437 }
438 
setDisplayManagerPolicy(const Policy & policy)439 status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
440     std::lock_guard lock(mLock);
441     if (!isPolicyValid(policy)) {
442         return BAD_VALUE;
443     }
444     Policy previousPolicy = *getCurrentPolicyLocked();
445     mDisplayManagerPolicy = policy;
446     if (*getCurrentPolicyLocked() == previousPolicy) {
447         return CURRENT_POLICY_UNCHANGED;
448     }
449     constructAvailableRefreshRates();
450     return NO_ERROR;
451 }
452 
setOverridePolicy(const std::optional<Policy> & policy)453 status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
454     std::lock_guard lock(mLock);
455     if (policy && !isPolicyValid(*policy)) {
456         return BAD_VALUE;
457     }
458     Policy previousPolicy = *getCurrentPolicyLocked();
459     mOverridePolicy = policy;
460     if (*getCurrentPolicyLocked() == previousPolicy) {
461         return CURRENT_POLICY_UNCHANGED;
462     }
463     constructAvailableRefreshRates();
464     return NO_ERROR;
465 }
466 
getCurrentPolicyLocked() const467 const RefreshRateConfigs::Policy* RefreshRateConfigs::getCurrentPolicyLocked() const {
468     return mOverridePolicy ? &mOverridePolicy.value() : &mDisplayManagerPolicy;
469 }
470 
getCurrentPolicy() const471 RefreshRateConfigs::Policy RefreshRateConfigs::getCurrentPolicy() const {
472     std::lock_guard lock(mLock);
473     return *getCurrentPolicyLocked();
474 }
475 
getDisplayManagerPolicy() const476 RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const {
477     std::lock_guard lock(mLock);
478     return mDisplayManagerPolicy;
479 }
480 
isConfigAllowed(HwcConfigIndexType config) const481 bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
482     std::lock_guard lock(mLock);
483     for (const RefreshRate* refreshRate : mAppRequestRefreshRates) {
484         if (refreshRate->configId == config) {
485             return true;
486         }
487     }
488     return false;
489 }
490 
getSortedRefreshRateList(const std::function<bool (const RefreshRate &)> & shouldAddRefreshRate,std::vector<const RefreshRate * > * outRefreshRates)491 void RefreshRateConfigs::getSortedRefreshRateList(
492         const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
493         std::vector<const RefreshRate*>* outRefreshRates) {
494     outRefreshRates->clear();
495     outRefreshRates->reserve(mRefreshRates.size());
496     for (const auto& [type, refreshRate] : mRefreshRates) {
497         if (shouldAddRefreshRate(*refreshRate)) {
498             ALOGV("getSortedRefreshRateList: config %d added to list policy",
499                   refreshRate->configId.value());
500             outRefreshRates->push_back(refreshRate.get());
501         }
502     }
503 
504     std::sort(outRefreshRates->begin(), outRefreshRates->end(),
505               [](const auto refreshRate1, const auto refreshRate2) {
506                   if (refreshRate1->hwcConfig->getVsyncPeriod() !=
507                       refreshRate2->hwcConfig->getVsyncPeriod()) {
508                       return refreshRate1->hwcConfig->getVsyncPeriod() >
509                               refreshRate2->hwcConfig->getVsyncPeriod();
510                   } else {
511                       return refreshRate1->hwcConfig->getConfigGroup() >
512                               refreshRate2->hwcConfig->getConfigGroup();
513                   }
514               });
515 }
516 
constructAvailableRefreshRates()517 void RefreshRateConfigs::constructAvailableRefreshRates() {
518     // Filter configs based on current policy and sort based on vsync period
519     const Policy* policy = getCurrentPolicyLocked();
520     const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
521     ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]"
522           " appRequestRange=[%.2f %.2f]",
523           policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min,
524           policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max);
525 
526     auto filterRefreshRates = [&](float min, float max, const char* listName,
527                                   std::vector<const RefreshRate*>* outRefreshRates) {
528         getSortedRefreshRateList(
529                 [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
530                     const auto& hwcConfig = refreshRate.hwcConfig;
531 
532                     return hwcConfig->getHeight() == defaultConfig->getHeight() &&
533                             hwcConfig->getWidth() == defaultConfig->getWidth() &&
534                             hwcConfig->getDpiX() == defaultConfig->getDpiX() &&
535                             hwcConfig->getDpiY() == defaultConfig->getDpiY() &&
536                             (policy->allowGroupSwitching ||
537                              hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) &&
538                             refreshRate.inPolicy(min, max);
539                 },
540                 outRefreshRates);
541 
542         LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
543                             "No matching configs for %s range: min=%.0f max=%.0f", listName, min,
544                             max);
545         auto stringifyRefreshRates = [&]() -> std::string {
546             std::string str;
547             for (auto refreshRate : *outRefreshRates) {
548                 base::StringAppendF(&str, "%s ", refreshRate->name.c_str());
549             }
550             return str;
551         };
552         ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
553     };
554 
555     filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary",
556                        &mPrimaryRefreshRates);
557     filterRefreshRates(policy->appRequestRange.min, policy->appRequestRange.max, "app request",
558                        &mAppRequestRefreshRates);
559 }
560 
constructKnownFrameRates(const std::vector<std::shared_ptr<const HWC2::Display::Config>> & configs)561 std::vector<float> RefreshRateConfigs::constructKnownFrameRates(
562         const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
563     std::vector<float> knownFrameRates = {24.0f, 30.0f, 45.0f, 60.0f, 72.0f};
564     knownFrameRates.reserve(knownFrameRates.size() + configs.size());
565 
566     // Add all supported refresh rates to the set
567     for (const auto& config : configs) {
568         const auto refreshRate = 1e9f / config->getVsyncPeriod();
569         knownFrameRates.emplace_back(refreshRate);
570     }
571 
572     // Sort and remove duplicates
573     const auto frameRatesEqual = [](float a, float b) { return std::abs(a - b) <= 0.01f; };
574     std::sort(knownFrameRates.begin(), knownFrameRates.end());
575     knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
576                                       frameRatesEqual),
577                           knownFrameRates.end());
578     return knownFrameRates;
579 }
580 
findClosestKnownFrameRate(float frameRate) const581 float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const {
582     if (frameRate <= *mKnownFrameRates.begin()) {
583         return *mKnownFrameRates.begin();
584     }
585 
586     if (frameRate >= *std::prev(mKnownFrameRates.end())) {
587         return *std::prev(mKnownFrameRates.end());
588     }
589 
590     auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate);
591 
592     const auto distance1 = std::abs(frameRate - *lowerBound);
593     const auto distance2 = std::abs(frameRate - *std::prev(lowerBound));
594     return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
595 }
596 
getIdleTimerAction() const597 RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const {
598     std::lock_guard lock(mLock);
599     const auto& deviceMin = getMinRefreshRate();
600     const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
601     const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();
602 
603     // Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
604     // the min allowed refresh rate is higher than the device min, we do not want to enable the
605     // timer.
606     if (deviceMin < minByPolicy) {
607         return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
608     }
609     if (minByPolicy == maxByPolicy) {
610         // Do not sent the call to toggle off kernel idle timer if the device min and policy min and
611         // max are all the same. This saves us extra unnecessary calls to sysprop.
612         if (deviceMin == minByPolicy) {
613             return RefreshRateConfigs::KernelIdleTimerAction::NoChange;
614         }
615         return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
616     }
617     // Turn on the timer in all other cases.
618     return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
619 }
620 
621 } // namespace android::scheduler
622