summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp')
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp870
1 files changed, 270 insertions, 600 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 0334d70bd5..8661b6ee0a 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -17,58 +17,20 @@
// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra"
-
#include "RefreshRateConfigs.h"
#include <android-base/stringprintf.h>
#include <utils/Trace.h>
#include <chrono>
#include <cmath>
-#include "../SurfaceFlingerProperties.h"
#undef LOG_TAG
#define LOG_TAG "RefreshRateConfigs"
namespace android::scheduler {
-namespace {
-std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) {
- return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %s", layer.name.c_str(),
- RefreshRateConfigs::layerVoteTypeString(layer.vote).c_str(), weight,
- toString(layer.seamlessness).c_str(),
- to_string(layer.desiredRefreshRate).c_str());
-}
-
-std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) {
- std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)};
- knownFrameRates.reserve(knownFrameRates.size() + modes.size());
-
- // Add all supported refresh rates to the set
- for (const auto& mode : modes) {
- const auto refreshRate = Fps::fromPeriodNsecs(mode->getVsyncPeriod());
- knownFrameRates.emplace_back(refreshRate);
- }
-
- // Sort and remove duplicates
- std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess);
- knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
- Fps::EqualsWithMargin()),
- knownFrameRates.end());
- return knownFrameRates;
-}
-
-} // namespace
using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType;
using RefreshRate = RefreshRateConfigs::RefreshRate;
-std::string RefreshRate::toString() const {
- return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}",
- getModeId().value(), mode->getHwcId(), getFps().getValue(),
- mode->getWidth(), mode->getHeight(), getModeGroup());
-}
-
std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) {
switch (vote) {
case LayerVoteType::NoVote:
@@ -83,184 +45,80 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) {
return "ExplicitDefault";
case LayerVoteType::ExplicitExactOrMultiple:
return "ExplicitExactOrMultiple";
- case LayerVoteType::ExplicitExact:
- return "ExplicitExact";
- }
-}
-
-std::string RefreshRateConfigs::Policy::toString() const {
- return base::StringPrintf("default mode ID: %d, allowGroupSwitching = %d"
- ", primary range: %s, app request range: %s",
- defaultMode.value(), allowGroupSwitching,
- primaryRange.toString().c_str(), appRequestRange.toString().c_str());
-}
-
-std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod,
- nsecs_t displayPeriod) const {
- auto [quotient, remainder] = std::div(layerPeriod, displayPeriod);
- if (remainder <= MARGIN_FOR_PERIOD_CALCULATION ||
- std::abs(remainder - displayPeriod) <= MARGIN_FOR_PERIOD_CALCULATION) {
- quotient++;
- remainder = 0;
}
-
- return {quotient, remainder};
}
-bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer,
- const RefreshRate& refreshRate) const {
- switch (layer.vote) {
- case LayerVoteType::ExplicitExactOrMultiple:
- case LayerVoteType::Heuristic:
- if (mConfig.frameRateMultipleThreshold != 0 &&
- refreshRate.fps.greaterThanOrEqualWithMargin(
- Fps(mConfig.frameRateMultipleThreshold)) &&
- layer.desiredRefreshRate.lessThanWithMargin(
- Fps(mConfig.frameRateMultipleThreshold / 2))) {
- // Don't vote high refresh rates past the threshold for layers with a low desired
- // refresh rate. For example, desired 24 fps with 120 Hz threshold means no vote for
- // 120 Hz, but desired 60 fps should have a vote.
- return false;
+const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(
+ const std::vector<LayerRequirement>& layers) const {
+ std::lock_guard lock(mLock);
+ int contentFramerate = 0;
+ int explicitContentFramerate = 0;
+ for (const auto& layer : layers) {
+ const auto desiredRefreshRateRound = round<int>(layer.desiredRefreshRate);
+ if (layer.vote == LayerVoteType::ExplicitDefault ||
+ layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
+ if (desiredRefreshRateRound > explicitContentFramerate) {
+ explicitContentFramerate = desiredRefreshRateRound;
+ }
+ } else {
+ if (desiredRefreshRateRound > contentFramerate) {
+ contentFramerate = desiredRefreshRateRound;
}
- break;
- case LayerVoteType::ExplicitDefault:
- case LayerVoteType::ExplicitExact:
- case LayerVoteType::Max:
- case LayerVoteType::Min:
- case LayerVoteType::NoVote:
- break;
- }
- return true;
-}
-
-float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer,
- const RefreshRate& refreshRate,
- bool isSeamlessSwitch) const {
- if (!isVoteAllowed(layer, refreshRate)) {
- return 0;
- }
-
- // Slightly prefer seamless switches.
- constexpr float kSeamedSwitchPenalty = 0.95f;
- const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
-
- // If the layer wants Max, give higher score to the higher refresh rate
- if (layer.vote == LayerVoteType::Max) {
- const auto ratio =
- refreshRate.fps.getValue() / mAppRequestRefreshRates.back()->fps.getValue();
- // use ratio^2 to get a lower score the more we get further from peak
- return ratio * ratio;
- }
-
- const auto displayPeriod = refreshRate.getVsyncPeriod();
- const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
- if (layer.vote == LayerVoteType::ExplicitDefault) {
- // Find the actual rate the layer will render, assuming
- // that layerPeriod is the minimal time to render a frame
- auto actualLayerPeriod = displayPeriod;
- int multiplier = 1;
- while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
- multiplier++;
- actualLayerPeriod = displayPeriod * multiplier;
- }
- return std::min(1.0f,
- static_cast<float>(layerPeriod) / static_cast<float>(actualLayerPeriod));
- }
-
- if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
- layer.vote == LayerVoteType::Heuristic) {
- // Calculate how many display vsyncs we need to present a single frame for this
- // layer
- const auto [displayFramesQuotient, displayFramesRemainder] =
- getDisplayFrames(layerPeriod, displayPeriod);
- static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
- if (displayFramesRemainder == 0) {
- // Layer desired refresh rate matches the display rate.
- return 1.0f * seamlessness;
- }
-
- if (displayFramesQuotient == 0) {
- // Layer desired refresh rate is higher than the display rate.
- return (static_cast<float>(layerPeriod) / static_cast<float>(displayPeriod)) *
- (1.0f / (MAX_FRAMES_TO_FIT + 1));
- }
-
- // Layer desired refresh rate is lower than the display rate. Check how well it fits
- // the cadence.
- auto diff = std::abs(displayFramesRemainder - (displayPeriod - displayFramesRemainder));
- int iter = 2;
- while (diff > MARGIN_FOR_PERIOD_CALCULATION && iter < MAX_FRAMES_TO_FIT) {
- diff = diff - (displayPeriod - diff);
- iter++;
}
-
- return (1.0f / iter) * seamlessness;
}
- if (layer.vote == LayerVoteType::ExplicitExact) {
- const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate);
- if (mSupportsFrameRateOverride) {
- // Since we support frame rate override, allow refresh rates which are
- // multiples of the layer's request, as those apps would be throttled
- // down to run at the desired refresh rate.
- return divider > 0;
- }
-
- return divider == 1;
+ if (explicitContentFramerate != 0) {
+ contentFramerate = explicitContentFramerate;
+ } else if (contentFramerate == 0) {
+ contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
}
+ ATRACE_INT("ContentFPS", contentFramerate);
- return 0;
-}
-
-struct RefreshRateScore {
- const RefreshRate* refreshRate;
- float score;
-};
-
-RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers,
- const GlobalSignals& globalSignals,
- GlobalSignals* outSignalsConsidered) const {
- std::lock_guard lock(mLock);
+ // Find the appropriate refresh rate with minimal error
+ auto iter = min_element(mPrimaryRefreshRates.cbegin(), mPrimaryRefreshRates.cend(),
+ [contentFramerate](const auto& lhs, const auto& rhs) -> bool {
+ return std::abs(lhs->fps - contentFramerate) <
+ std::abs(rhs->fps - contentFramerate);
+ });
- if (auto cached = getCachedBestRefreshRate(layers, globalSignals, outSignalsConsidered)) {
- return *cached;
+ // Some content aligns better on higher refresh rate. For example for 45fps we should choose
+ // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
+ // align well with both
+ const RefreshRate* bestSoFar = *iter;
+ constexpr float MARGIN = 0.05f;
+ float ratio = (*iter)->fps / contentFramerate;
+ if (std::abs(std::round(ratio) - ratio) > MARGIN) {
+ while (iter != mPrimaryRefreshRates.cend()) {
+ ratio = (*iter)->fps / contentFramerate;
+
+ if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
+ bestSoFar = *iter;
+ break;
+ }
+ ++iter;
+ }
}
- GlobalSignals signalsConsidered;
- RefreshRate result = getBestRefreshRateLocked(layers, globalSignals, &signalsConsidered);
- lastBestRefreshRateInvocation.emplace(
- GetBestRefreshRateInvocation{.layerRequirements = layers,
- .globalSignals = globalSignals,
- .outSignalsConsidered = signalsConsidered,
- .resultingBestRefreshRate = result});
- if (outSignalsConsidered) {
- *outSignalsConsidered = signalsConsidered;
- }
- return result;
+ return *bestSoFar;
}
-std::optional<RefreshRate> RefreshRateConfigs::getCachedBestRefreshRate(
- const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals,
- GlobalSignals* outSignalsConsidered) const {
- const bool sameAsLastCall = lastBestRefreshRateInvocation &&
- lastBestRefreshRateInvocation->layerRequirements == layers &&
- lastBestRefreshRateInvocation->globalSignals == globalSignals;
-
- if (sameAsLastCall) {
- if (outSignalsConsidered) {
- *outSignalsConsidered = lastBestRefreshRateInvocation->outSignalsConsidered;
- }
- return lastBestRefreshRateInvocation->resultingBestRefreshRate;
+std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod,
+ nsecs_t displayPeriod) const {
+ auto [displayFramesQuot, displayFramesRem] = std::div(layerPeriod, displayPeriod);
+ if (displayFramesRem <= MARGIN_FOR_PERIOD_CALCULATION ||
+ std::abs(displayFramesRem - displayPeriod) <= MARGIN_FOR_PERIOD_CALCULATION) {
+ displayFramesQuot++;
+ displayFramesRem = 0;
}
- return {};
+ return {displayFramesQuot, displayFramesRem};
}
-RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
+const RefreshRate& RefreshRateConfigs::getBestRefreshRate(
const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals,
GlobalSignals* outSignalsConsidered) const {
ATRACE_CALL();
- ALOGV("getBestRefreshRate %zu layers", layers.size());
+ ALOGV("getRefreshRateForContent %zu layers", layers.size());
if (outSignalsConsidered) *outSignalsConsidered = {};
const auto setTouchConsidered = [&] {
@@ -275,48 +133,32 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
}
};
+ std::lock_guard lock(mLock);
+
int noVoteLayers = 0;
int minVoteLayers = 0;
int maxVoteLayers = 0;
int explicitDefaultVoteLayers = 0;
int explicitExactOrMultipleVoteLayers = 0;
- int explicitExact = 0;
float maxExplicitWeight = 0;
- int seamedFocusedLayers = 0;
for (const auto& layer : layers) {
- switch (layer.vote) {
- case LayerVoteType::NoVote:
- noVoteLayers++;
- break;
- case LayerVoteType::Min:
- minVoteLayers++;
- break;
- case LayerVoteType::Max:
- maxVoteLayers++;
- break;
- case LayerVoteType::ExplicitDefault:
- explicitDefaultVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
- break;
- case LayerVoteType::ExplicitExactOrMultiple:
- explicitExactOrMultipleVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
- break;
- case LayerVoteType::ExplicitExact:
- explicitExact++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
- break;
- case LayerVoteType::Heuristic:
- break;
- }
-
- if (layer.seamlessness == Seamlessness::SeamedAndSeamless && layer.focused) {
- seamedFocusedLayers++;
+ if (layer.vote == LayerVoteType::NoVote) {
+ noVoteLayers++;
+ } else if (layer.vote == LayerVoteType::Min) {
+ minVoteLayers++;
+ } else if (layer.vote == LayerVoteType::Max) {
+ maxVoteLayers++;
+ } else if (layer.vote == LayerVoteType::ExplicitDefault) {
+ explicitDefaultVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+ } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
+ explicitExactOrMultipleVoteLayers++;
+ maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
}
}
- const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
- explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0;
+ const bool hasExplicitVoteLayers =
+ explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0;
// Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
// selected a refresh rate to see if we should apply touch boost.
@@ -330,8 +172,7 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
// move out the of range if layers explicitly request a different refresh
// rate.
const Policy* policy = getCurrentPolicyLocked();
- const bool primaryRangeIsSingleRate =
- policy->primaryRange.min.equalsWithMargin(policy->primaryRange.max);
+ const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max;
if (!globalSignals.touch && globalSignals.idle &&
!(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
@@ -351,19 +192,16 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
}
// Find the best refresh rate based on score
- std::vector<RefreshRateScore> scores;
+ std::vector<std::pair<const RefreshRate*, float>> scores;
scores.reserve(mAppRequestRefreshRates.size());
for (const auto refreshRate : mAppRequestRefreshRates) {
- scores.emplace_back(RefreshRateScore{refreshRate, 0.0f});
+ scores.emplace_back(refreshRate, 0.0f);
}
- const auto& defaultMode = mRefreshRates.at(policy->defaultMode);
-
for (const auto& layer : layers) {
- ALOGV("Calculating score for %s (%s, weight %.2f, desired %.2f) ", layer.name.c_str(),
- layerVoteTypeString(layer.vote).c_str(), layer.weight,
- layer.desiredRefreshRate.getValue());
+ ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(),
+ layerVoteTypeString(layer.vote).c_str(), layer.weight);
if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min) {
continue;
}
@@ -371,59 +209,88 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
auto weight = layer.weight;
for (auto i = 0u; i < scores.size(); i++) {
- const bool isSeamlessSwitch =
- scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup();
-
- if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
- ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
- formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ bool inPrimaryRange =
+ scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
+ if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
+ !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) {
+ // Only focused layers with ExplicitDefault frame rate settings are allowed to score
+ // refresh rates outside the primary range.
continue;
}
- if (layer.seamlessness == Seamlessness::SeamedAndSeamless && !isSeamlessSwitch &&
- !layer.focused) {
- ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
- " Current mode = %s",
- formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ // If the layer wants Max, give higher score to the higher refresh rate
+ if (layer.vote == LayerVoteType::Max) {
+ const auto ratio = scores[i].first->fps / scores.back().first->fps;
+ // use ratio^2 to get a lower score the more we get further from peak
+ const auto layerScore = ratio * ratio;
+ ALOGV("%s (Max, weight %.2f) gives %s score of %.2f", layer.name.c_str(), weight,
+ scores[i].first->name.c_str(), layerScore);
+ scores[i].second += weight * layerScore;
continue;
}
- // Layers with default seamlessness vote for the current mode group if
- // there are layers with seamlessness=SeamedAndSeamless and for the default
- // mode group otherwise. In second case, if the current mode group is different
- // from the default, this means a layer with seamlessness=SeamedAndSeamless has just
- // disappeared.
- const bool isInPolicyForDefault = seamedFocusedLayers > 0
- ? scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup()
- : scores[i].refreshRate->getModeGroup() == defaultMode->getModeGroup();
-
- if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) {
- ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->toString().c_str(),
- mCurrentRefreshRate->toString().c_str());
+ const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod();
+ const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
+ if (layer.vote == LayerVoteType::ExplicitDefault) {
+ const auto layerScore = [&]() {
+ // Find the actual rate the layer will render, assuming
+ // that layerPeriod is the minimal time to render a frame
+ auto actualLayerPeriod = displayPeriod;
+ int multiplier = 1;
+ while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
+ multiplier++;
+ actualLayerPeriod = displayPeriod * multiplier;
+ }
+ return std::min(1.0f,
+ static_cast<float>(layerPeriod) /
+ static_cast<float>(actualLayerPeriod));
+ }();
+
+ ALOGV("%s (ExplicitDefault, weight %.2f) %.2fHz gives %s score of %.2f",
+ layer.name.c_str(), weight, 1e9f / layerPeriod, scores[i].first->name.c_str(),
+ layerScore);
+ scores[i].second += weight * layerScore;
continue;
}
- bool inPrimaryRange = scores[i].refreshRate->inPolicy(policy->primaryRange.min,
- policy->primaryRange.max);
- if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
- !(layer.focused &&
- (layer.vote == LayerVoteType::ExplicitDefault ||
- layer.vote == LayerVoteType::ExplicitExact))) {
- // Only focused layers with ExplicitDefault frame rate settings are allowed to score
- // refresh rates outside the primary range.
+ if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
+ layer.vote == LayerVoteType::Heuristic) {
+ const auto layerScore = [&] {
+ // Calculate how many display vsyncs we need to present a single frame for this
+ // layer
+ const auto [displayFramesQuot, displayFramesRem] =
+ getDisplayFrames(layerPeriod, displayPeriod);
+ static constexpr size_t MAX_FRAMES_TO_FIT =
+ 10; // Stop calculating when score < 0.1
+ if (displayFramesRem == 0) {
+ // Layer desired refresh rate matches the display rate.
+ return 1.0f;
+ }
+
+ if (displayFramesQuot == 0) {
+ // Layer desired refresh rate is higher the display rate.
+ return (static_cast<float>(layerPeriod) /
+ static_cast<float>(displayPeriod)) *
+ (1.0f / (MAX_FRAMES_TO_FIT + 1));
+ }
+
+ // Layer desired refresh rate is lower the display rate. Check how well it fits
+ // the cadence
+ auto diff = std::abs(displayFramesRem - (displayPeriod - displayFramesRem));
+ int iter = 2;
+ while (diff > MARGIN_FOR_PERIOD_CALCULATION && iter < MAX_FRAMES_TO_FIT) {
+ diff = diff - (displayPeriod - diff);
+ iter++;
+ }
+
+ return 1.0f / iter;
+ }();
+ ALOGV("%s (%s, weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(),
+ layerVoteTypeString(layer.vote).c_str(), weight, 1e9f / layerPeriod,
+ scores[i].first->name.c_str(), layerScore);
+ scores[i].second += weight * layerScore;
continue;
}
-
- const auto layerScore =
- calculateLayerScoreLocked(layer, *scores[i].refreshRate, isSeamlessSwitch);
- ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
- scores[i].refreshRate->getName().c_str(), layerScore);
- scores[i].score += weight * layerScore;
}
}
@@ -438,7 +305,7 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
// If we never scored any layers, then choose the rate from the primary
// range instead of picking a random score from the app range.
if (std::all_of(scores.begin(), scores.end(),
- [](RefreshRateScore score) { return score.score == 0; })) {
+ [](std::pair<const RefreshRate*, float> p) { return p.second == 0; })) {
ALOGV("layers not scored - choose %s",
getMaxRefreshRateByPolicyLocked().getName().c_str());
return getMaxRefreshRateByPolicyLocked();
@@ -453,17 +320,8 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
// actually increase the refresh rate over the normal selection.
const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
- const bool touchBoostForExplicitExact = [&] {
- if (mSupportsFrameRateOverride) {
- // Enable touch boost if there are other layers besides exact
- return explicitExact + noVoteLayers != layers.size();
- } else {
- // Enable touch boost if there are no exact layers
- return explicitExact == 0;
- }
- }();
- if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
- bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) {
+ if (globalSignals.touch && explicitDefaultVoteLayers == 0 &&
+ bestRefreshRate->fps < touchRefreshRate.fps) {
setTouchConsidered();
ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
return touchRefreshRate;
@@ -472,124 +330,16 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(
return *bestRefreshRate;
}
-std::unordered_map<uid_t, std::vector<const RefreshRateConfigs::LayerRequirement*>>
-groupLayersByUid(const std::vector<RefreshRateConfigs::LayerRequirement>& layers) {
- std::unordered_map<uid_t, std::vector<const RefreshRateConfigs::LayerRequirement*>> layersByUid;
- for (const auto& layer : layers) {
- auto iter = layersByUid.emplace(layer.ownerUid,
- std::vector<const RefreshRateConfigs::LayerRequirement*>());
- auto& layersWithSameUid = iter.first->second;
- layersWithSameUid.push_back(&layer);
- }
-
- // Remove uids that can't have a frame rate override
- for (auto iter = layersByUid.begin(); iter != layersByUid.end();) {
- const auto& layersWithSameUid = iter->second;
- bool skipUid = false;
- for (const auto& layer : layersWithSameUid) {
- if (layer->vote == RefreshRateConfigs::LayerVoteType::Max ||
- layer->vote == RefreshRateConfigs::LayerVoteType::Heuristic) {
- skipUid = true;
- break;
- }
- }
- if (skipUid) {
- iter = layersByUid.erase(iter);
- } else {
- ++iter;
- }
- }
-
- return layersByUid;
-}
-
-std::vector<RefreshRateScore> initializeScoresForAllRefreshRates(
- const AllRefreshRatesMapType& refreshRates) {
- std::vector<RefreshRateScore> scores;
- scores.reserve(refreshRates.size());
- for (const auto& [ignored, refreshRate] : refreshRates) {
- scores.emplace_back(RefreshRateScore{refreshRate.get(), 0.0f});
- }
- std::sort(scores.begin(), scores.end(),
- [](const auto& a, const auto& b) { return *a.refreshRate < *b.refreshRate; });
- return scores;
-}
-
-RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides(
- const std::vector<LayerRequirement>& layers, Fps displayFrameRate, bool touch) const {
- ATRACE_CALL();
- if (!mSupportsFrameRateOverride) return {};
-
- ALOGV("getFrameRateOverrides %zu layers", layers.size());
- std::lock_guard lock(mLock);
- std::vector<RefreshRateScore> scores = initializeScoresForAllRefreshRates(mRefreshRates);
- std::unordered_map<uid_t, std::vector<const LayerRequirement*>> layersByUid =
- groupLayersByUid(layers);
- UidToFrameRateOverride frameRateOverrides;
- for (const auto& [uid, layersWithSameUid] : layersByUid) {
- // Layers with ExplicitExactOrMultiple expect touch boost
- const bool hasExplicitExactOrMultiple =
- std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(),
- [](const auto& layer) {
- return layer->vote == LayerVoteType::ExplicitExactOrMultiple;
- });
-
- if (touch && hasExplicitExactOrMultiple) {
- continue;
- }
-
- for (auto& score : scores) {
- score.score = 0;
- }
-
- for (const auto& layer : layersWithSameUid) {
- if (layer->vote == LayerVoteType::NoVote || layer->vote == LayerVoteType::Min) {
- continue;
- }
-
- LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
- layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
- layer->vote != LayerVoteType::ExplicitExact);
- for (RefreshRateScore& score : scores) {
- const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate,
- /*isSeamlessSwitch*/ true);
- score.score += layer->weight * layerScore;
- }
- }
-
- // We just care about the refresh rates which are a divider of the
- // display refresh rate
- auto iter =
- std::remove_if(scores.begin(), scores.end(), [&](const RefreshRateScore& score) {
- return getFrameRateDivider(displayFrameRate, score.refreshRate->getFps()) == 0;
- });
- scores.erase(iter, scores.end());
-
- // If we never scored any layers, we don't have a preferred frame rate
- if (std::all_of(scores.begin(), scores.end(),
- [](const RefreshRateScore& score) { return score.score == 0; })) {
- continue;
- }
-
- // Now that we scored all the refresh rates we need to pick the one that got the highest
- // score.
- const RefreshRate* bestRefreshRate = getBestRefreshRate(scores.begin(), scores.end());
- frameRateOverrides.emplace(uid, bestRefreshRate->getFps());
- }
-
- return frameRateOverrides;
-}
-
template <typename Iter>
const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
constexpr auto EPSILON = 0.001f;
- const RefreshRate* bestRefreshRate = begin->refreshRate;
- float max = begin->score;
+ const RefreshRate* bestRefreshRate = begin->first;
+ float max = begin->second;
for (auto i = begin; i != end; ++i) {
const auto [refreshRate, score] = *i;
- ALOGV("%s scores %.2f", refreshRate->getName().c_str(), score);
+ ALOGV("%s scores %.2f", refreshRate->name.c_str(), score);
- ATRACE_INT(refreshRate->getName().c_str(), round<int>(score * 100));
+ ATRACE_INT(refreshRate->name.c_str(), round<int>(score * 100));
if (score > max * (1 + EPSILON)) {
max = score;
@@ -600,60 +350,34 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end)
return bestRefreshRate;
}
-std::optional<Fps> RefreshRateConfigs::onKernelTimerChanged(
- std::optional<DisplayModeId> desiredActiveConfigId, bool timerExpired) const {
- std::lock_guard lock(mLock);
-
- const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId)
- : *mCurrentRefreshRate;
- const auto& min = *mMinSupportedRefreshRate;
-
- if (current != min) {
- const auto& refreshRate = timerExpired ? min : current;
- return refreshRate.getFps();
- }
+const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const {
+ return mRefreshRates;
+}
- return {};
+const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const {
+ std::lock_guard lock(mLock);
+ return getMinRefreshRateByPolicyLocked();
}
const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
- for (auto refreshRate : mPrimaryRefreshRates) {
- if (mCurrentRefreshRate->getModeGroup() == refreshRate->getModeGroup()) {
- return *refreshRate;
- }
- }
- ALOGE("Can't find min refresh rate by policy with the same mode group"
- " as the current mode %s",
- mCurrentRefreshRate->toString().c_str());
- // Defaulting to the lowest refresh rate
return *mPrimaryRefreshRates.front();
}
-RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
+const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
return getMaxRefreshRateByPolicyLocked();
}
const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
- for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); it++) {
- const auto& refreshRate = (**it);
- if (mCurrentRefreshRate->getModeGroup() == refreshRate.getModeGroup()) {
- return refreshRate;
- }
- }
- ALOGE("Can't find max refresh rate by policy with the same mode group"
- " as the current mode %s",
- mCurrentRefreshRate->toString().c_str());
- // Defaulting to the highest refresh rate
return *mPrimaryRefreshRates.back();
}
-RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const {
+const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const {
std::lock_guard lock(mLock);
return *mCurrentRefreshRate;
}
-RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
+const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const {
std::lock_guard lock(mLock);
return getCurrentRefreshRateByPolicyLocked();
}
@@ -663,95 +387,60 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() con
mCurrentRefreshRate) != mAppRequestRefreshRates.end()) {
return *mCurrentRefreshRate;
}
- return *mRefreshRates.at(getCurrentPolicyLocked()->defaultMode);
-}
-
-void RefreshRateConfigs::setCurrentModeId(DisplayModeId modeId) {
- std::lock_guard lock(mLock);
-
- // Invalidate the cached invocation to getBestRefreshRate. This forces
- // the refresh rate to be recomputed on the next call to getBestRefreshRate.
- lastBestRefreshRateInvocation.reset();
-
- mCurrentRefreshRate = mRefreshRates.at(modeId).get();
-}
-
-RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
- Config config)
- : mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
- updateDisplayModes(modes, currentModeId);
+ return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
}
-void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,
- DisplayModeId currentModeId) {
+void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
std::lock_guard lock(mLock);
-
- // The current mode should be supported
- LOG_ALWAYS_FATAL_IF(std::none_of(modes.begin(), modes.end(), [&](DisplayModePtr mode) {
- return mode->getId() == currentModeId;
- }));
-
- // Invalidate the cached invocation to getBestRefreshRate. This forces
- // the refresh rate to be recomputed on the next call to getBestRefreshRate.
- lastBestRefreshRateInvocation.reset();
-
- mRefreshRates.clear();
- for (const auto& mode : modes) {
- const auto modeId = mode->getId();
- mRefreshRates.emplace(modeId,
- std::make_unique<RefreshRate>(modeId, mode, mode->getFps(),
+ mCurrentRefreshRate = mRefreshRates.at(configId).get();
+}
+
+RefreshRateConfigs::RefreshRateConfigs(
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
+ HwcConfigIndexType currentConfigId)
+ : mKnownFrameRates(constructKnownFrameRates(configs)) {
+ LOG_ALWAYS_FATAL_IF(configs.empty());
+ LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());
+
+ for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) {
+ const auto& config = configs.at(static_cast<size_t>(configId.value()));
+ const float fps = 1e9f / config->getVsyncPeriod();
+ mRefreshRates.emplace(configId,
+ std::make_unique<RefreshRate>(configId, config,
+ base::StringPrintf("%.0ffps", fps), fps,
RefreshRate::ConstructorTag(0)));
- if (modeId == currentModeId) {
- mCurrentRefreshRate = mRefreshRates.at(modeId).get();
- }
- }
-
- std::vector<const RefreshRate*> sortedModes;
- getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes);
- // Reset the policy because the old one may no longer be valid.
- mDisplayManagerPolicy = {};
- mDisplayManagerPolicy.defaultMode = currentModeId;
- mMinSupportedRefreshRate = sortedModes.front();
- mMaxSupportedRefreshRate = sortedModes.back();
-
- mSupportsFrameRateOverride = false;
- if (mConfig.enableFrameRateOverride) {
- for (const auto& mode1 : sortedModes) {
- for (const auto& mode2 : sortedModes) {
- if (getFrameRateDivider(mode1->getFps(), mode2->getFps()) >= 2) {
- mSupportsFrameRateOverride = true;
- break;
- }
- }
+ if (configId == currentConfigId) {
+ mCurrentRefreshRate = mRefreshRates.at(configId).get();
}
}
+ std::vector<const RefreshRate*> sortedConfigs;
+ getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
+ mDisplayManagerPolicy.defaultConfig = currentConfigId;
+ mMinSupportedRefreshRate = sortedConfigs.front();
+ mMaxSupportedRefreshRate = sortedConfigs.back();
constructAvailableRefreshRates();
}
-bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const {
- // defaultMode must be a valid mode, and within the given refresh rate range.
- auto iter = mRefreshRates.find(policy.defaultMode);
+bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
+ // defaultConfig must be a valid config, and within the given refresh rate range.
+ auto iter = mRefreshRates.find(policy.defaultConfig);
if (iter == mRefreshRates.end()) {
- ALOGE("Default mode is not found.");
return false;
}
const RefreshRate& refreshRate = *iter->second;
if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) {
- ALOGE("Default mode is not in the primary range.");
return false;
}
- return policy.appRequestRange.min.lessThanOrEqualWithMargin(policy.primaryRange.min) &&
- policy.appRequestRange.max.greaterThanOrEqualWithMargin(policy.primaryRange.max);
+ return policy.appRequestRange.min <= policy.primaryRange.min &&
+ policy.appRequestRange.max >= policy.primaryRange.max;
}
status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
std::lock_guard lock(mLock);
- if (!isPolicyValidLocked(policy)) {
- ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
+ if (!isPolicyValid(policy)) {
return BAD_VALUE;
}
- lastBestRefreshRateInvocation.reset();
Policy previousPolicy = *getCurrentPolicyLocked();
mDisplayManagerPolicy = policy;
if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -763,10 +452,9 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) {
status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) {
std::lock_guard lock(mLock);
- if (policy && !isPolicyValidLocked(*policy)) {
+ if (policy && !isPolicyValid(*policy)) {
return BAD_VALUE;
}
- lastBestRefreshRateInvocation.reset();
Policy previousPolicy = *getCurrentPolicyLocked();
mOverridePolicy = policy;
if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -790,76 +478,79 @@ RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const {
return mDisplayManagerPolicy;
}
-bool RefreshRateConfigs::isModeAllowed(DisplayModeId modeId) const {
+bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const {
std::lock_guard lock(mLock);
for (const RefreshRate* refreshRate : mAppRequestRefreshRates) {
- if (refreshRate->modeId == modeId) {
+ if (refreshRate->configId == config) {
return true;
}
}
return false;
}
-void RefreshRateConfigs::getSortedRefreshRateListLocked(
+void RefreshRateConfigs::getSortedRefreshRateList(
const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate,
std::vector<const RefreshRate*>* outRefreshRates) {
outRefreshRates->clear();
outRefreshRates->reserve(mRefreshRates.size());
for (const auto& [type, refreshRate] : mRefreshRates) {
if (shouldAddRefreshRate(*refreshRate)) {
- ALOGV("getSortedRefreshRateListLocked: mode %d added to list policy",
- refreshRate->modeId.value());
+ ALOGV("getSortedRefreshRateList: config %d added to list policy",
+ refreshRate->configId.value());
outRefreshRates->push_back(refreshRate.get());
}
}
std::sort(outRefreshRates->begin(), outRefreshRates->end(),
[](const auto refreshRate1, const auto refreshRate2) {
- if (refreshRate1->mode->getVsyncPeriod() !=
- refreshRate2->mode->getVsyncPeriod()) {
- return refreshRate1->mode->getVsyncPeriod() >
- refreshRate2->mode->getVsyncPeriod();
+ if (refreshRate1->hwcConfig->getVsyncPeriod() !=
+ refreshRate2->hwcConfig->getVsyncPeriod()) {
+ return refreshRate1->hwcConfig->getVsyncPeriod() >
+ refreshRate2->hwcConfig->getVsyncPeriod();
} else {
- return refreshRate1->mode->getGroup() > refreshRate2->mode->getGroup();
+ return refreshRate1->hwcConfig->getConfigGroup() >
+ refreshRate2->hwcConfig->getConfigGroup();
}
});
}
void RefreshRateConfigs::constructAvailableRefreshRates() {
- // Filter modes based on current policy and sort based on vsync period
+ // Filter configs based on current policy and sort based on vsync period
const Policy* policy = getCurrentPolicyLocked();
- const auto& defaultMode = mRefreshRates.at(policy->defaultMode)->mode;
- ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str());
-
- auto filterRefreshRates =
- [&](Fps min, Fps max, const char* listName,
- std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock) {
- getSortedRefreshRateListLocked(
- [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
- const auto& mode = refreshRate.mode;
-
- return mode->getHeight() == defaultMode->getHeight() &&
- mode->getWidth() == defaultMode->getWidth() &&
- mode->getDpiX() == defaultMode->getDpiX() &&
- mode->getDpiY() == defaultMode->getDpiY() &&
- (policy->allowGroupSwitching ||
- mode->getGroup() == defaultMode->getGroup()) &&
- refreshRate.inPolicy(min, max);
- },
- outRefreshRates);
-
- LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
- "No matching modes for %s range: min=%s max=%s", listName,
- to_string(min).c_str(), to_string(max).c_str());
- auto stringifyRefreshRates = [&]() -> std::string {
- std::string str;
- for (auto refreshRate : *outRefreshRates) {
- base::StringAppendF(&str, "%s ", refreshRate->getName().c_str());
- }
- return str;
- };
- ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
- };
+ const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
+ ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]"
+ " appRequestRange=[%.2f %.2f]",
+ policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min,
+ policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max);
+
+ auto filterRefreshRates = [&](float min, float max, const char* listName,
+ std::vector<const RefreshRate*>* outRefreshRates) {
+ getSortedRefreshRateList(
+ [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
+ const auto& hwcConfig = refreshRate.hwcConfig;
+
+ return hwcConfig->getHeight() == defaultConfig->getHeight() &&
+ hwcConfig->getWidth() == defaultConfig->getWidth() &&
+ hwcConfig->getDpiX() == defaultConfig->getDpiX() &&
+ hwcConfig->getDpiY() == defaultConfig->getDpiY() &&
+ (policy->allowGroupSwitching ||
+ hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) &&
+ refreshRate.inPolicy(min, max);
+ },
+ outRefreshRates);
+
+ LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
+ "No matching configs for %s range: min=%.0f max=%.0f", listName, min,
+ max);
+ auto stringifyRefreshRates = [&]() -> std::string {
+ std::string str;
+ for (auto refreshRate : *outRefreshRates) {
+ base::StringAppendF(&str, "%s ", refreshRate->name.c_str());
+ }
+ return str;
+ };
+ ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
+ };
filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary",
&mPrimaryRefreshRates);
@@ -867,29 +558,47 @@ void RefreshRateConfigs::constructAvailableRefreshRates() {
&mAppRequestRefreshRates);
}
-Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const {
- if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) {
+std::vector<float> RefreshRateConfigs::constructKnownFrameRates(
+ const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
+ std::vector<float> knownFrameRates = {24.0f, 30.0f, 45.0f, 60.0f, 72.0f};
+ knownFrameRates.reserve(knownFrameRates.size() + configs.size());
+
+ // Add all supported refresh rates to the set
+ for (const auto& config : configs) {
+ const auto refreshRate = 1e9f / config->getVsyncPeriod();
+ knownFrameRates.emplace_back(refreshRate);
+ }
+
+ // Sort and remove duplicates
+ const auto frameRatesEqual = [](float a, float b) { return std::abs(a - b) <= 0.01f; };
+ std::sort(knownFrameRates.begin(), knownFrameRates.end());
+ knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(),
+ frameRatesEqual),
+ knownFrameRates.end());
+ return knownFrameRates;
+}
+
+float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const {
+ if (frameRate <= *mKnownFrameRates.begin()) {
return *mKnownFrameRates.begin();
}
- if (frameRate.greaterThanOrEqualWithMargin(*std::prev(mKnownFrameRates.end()))) {
+ if (frameRate >= *std::prev(mKnownFrameRates.end())) {
return *std::prev(mKnownFrameRates.end());
}
- auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate,
- Fps::comparesLess);
+ auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate);
- const auto distance1 = std::abs((frameRate.getValue() - lowerBound->getValue()));
- const auto distance2 = std::abs((frameRate.getValue() - std::prev(lowerBound)->getValue()));
+ const auto distance1 = std::abs(frameRate - *lowerBound);
+ const auto distance2 = std::abs(frameRate - *std::prev(lowerBound));
return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
}
RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const {
std::lock_guard lock(mLock);
- const auto& deviceMin = *mMinSupportedRefreshRate;
+ const auto& deviceMin = getMinRefreshRate();
const auto& minByPolicy = getMinRefreshRateByPolicyLocked();
const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked();
- const auto& currentPolicy = getCurrentPolicyLocked();
// Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that
// the min allowed refresh rate is higher than the device min, we do not want to enable the
@@ -898,9 +607,10 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
if (minByPolicy == maxByPolicy) {
- // when min primary range in display manager policy is below device min turn on the timer.
- if (currentPolicy->primaryRange.min.lessThanWithMargin(deviceMin.getFps())) {
- return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
+ // Do not sent the call to toggle off kernel idle timer if the device min and policy min and
+ // max are all the same. This saves us extra unnecessary calls to sysprop.
+ if (deviceMin == minByPolicy) {
+ return RefreshRateConfigs::KernelIdleTimerAction::NoChange;
}
return RefreshRateConfigs::KernelIdleTimerAction::TurnOff;
}
@@ -908,44 +618,4 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction
return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
}
-int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate) {
- // This calculation needs to be in sync with the java code
- // in DisplayManagerService.getDisplayInfoForFrameRateOverride
- constexpr float kThreshold = 0.1f;
- const auto numPeriods = displayFrameRate.getValue() / layerFrameRate.getValue();
- const auto numPeriodsRounded = std::round(numPeriods);
- if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
- return 0;
- }
-
- return static_cast<int>(numPeriodsRounded);
-}
-
-void RefreshRateConfigs::dump(std::string& result) const {
- std::lock_guard lock(mLock);
- base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",
- mDisplayManagerPolicy.toString().c_str());
- scheduler::RefreshRateConfigs::Policy currentPolicy = *getCurrentPolicyLocked();
- if (mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
- base::StringAppendF(&result, "DesiredDisplayModeSpecs (Override): %s\n\n",
- currentPolicy.toString().c_str());
- }
-
- auto mode = mCurrentRefreshRate->mode;
- base::StringAppendF(&result, "Current mode: %s\n", mCurrentRefreshRate->toString().c_str());
-
- result.append("Refresh rates:\n");
- for (const auto& [id, refreshRate] : mRefreshRates) {
- mode = refreshRate->mode;
- base::StringAppendF(&result, "\t%s\n", refreshRate->toString().c_str());
- }
-
- base::StringAppendF(&result, "Supports Frame Rate Override: %s\n",
- mSupportsFrameRateOverride ? "yes" : "no");
- result.append("\n");
-}
-
} // namespace android::scheduler
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"