SF: avoid changing refresh rate for ExplicitExact
When a layer with ExplicitExact vote is present and the corresponding
refresh rate is not available, the refresh rate should remain the same.
Bug: 246230302
Test: SF unit tests
Change-Id: I3e1712d6494fc9fc46b8d26fdae310231f57e7b1
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index c10b817..30483a2 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -314,7 +314,8 @@
// Keep the display at max refresh rate for the duration of powering on the display.
if (signals.powerOnImminent) {
ALOGV("Power On Imminent");
- return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending),
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
GlobalSignals{.powerOnImminent = true}};
}
@@ -374,7 +375,8 @@
// selected a refresh rate to see if we should apply touch boost.
if (signals.touch && !hasExplicitVoteLayers) {
ALOGV("Touch Boost");
- return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
GlobalSignals{.touch = true}};
}
@@ -386,20 +388,23 @@
if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
ALOGV("Idle");
- return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
GlobalSignals{.idle = true}};
}
if (layers.empty() || noVoteLayers == layers.size()) {
ALOGV("No layers with votes");
- return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
kNoSignals};
}
// Only if all layers want Min we should return Min
if (noVoteLayers + minVoteLayers == layers.size()) {
ALOGV("All layers Min");
- return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
kNoSignals};
}
@@ -560,13 +565,17 @@
return RefreshRateRanking{score.modeIt->second, score.overallScore};
});
+ const bool noLayerScore = std::all_of(scores.begin(), scores.end(), [](RefreshRateScore score) {
+ return score.overallScore == 0;
+ });
+
if (primaryRangeIsSingleRate) {
// 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.overallScore == 0; })) {
+ if (noLayerScore) {
ALOGV("Layers not scored");
- return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
+ /*preferredDisplayModeOpt*/ std::nullopt),
kNoSignals};
} else {
return {rankedRefreshRates, kNoSignals};
@@ -588,7 +597,8 @@
}();
const auto& touchRefreshRates =
- getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending);
+ getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
+ /*preferredDisplayModeOpt*/ std::nullopt);
using fps_approx_ops::operator<;
if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
@@ -598,6 +608,15 @@
return {touchRefreshRates, GlobalSignals{.touch = true}};
}
+ // If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
+ // current config
+ if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) {
+ const auto preferredDisplayMode = activeMode.getId();
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Ascending,
+ preferredDisplayMode),
+ kNoSignals};
+ }
+
return {rankedRefreshRates, kNoSignals};
}
@@ -765,15 +784,29 @@
}
std::vector<RefreshRateRanking> RefreshRateConfigs::getRefreshRatesByPolicyLocked(
- std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
- std::vector<RefreshRateRanking> rankings;
+ std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder,
+ std::optional<DisplayModeId> preferredDisplayModeOpt) const {
+ std::deque<RefreshRateRanking> rankings;
const auto makeRanking = [&](const DisplayModeIterator it) REQUIRES(mLock) {
const auto& mode = it->second;
- const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending);
- const float score = calculateRefreshRateScoreForFps(mode->getFps());
- if (!anchorGroupOpt || mode->getGroup() == anchorGroupOpt) {
- rankings.push_back(RefreshRateRanking{mode, inverseScore ? 1.0f / score : score});
+ if (anchorGroupOpt && mode->getGroup() != anchorGroupOpt) {
+ return;
}
+
+ float score = calculateRefreshRateScoreForFps(mode->getFps());
+ const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending);
+ if (inverseScore) {
+ score = 1.0f / score;
+ }
+ if (preferredDisplayModeOpt) {
+ if (*preferredDisplayModeOpt == mode->getId()) {
+ rankings.push_front(RefreshRateRanking{mode, /*score*/ 1.0f});
+ return;
+ }
+ constexpr float kNonPreferredModePenalty = 0.95f;
+ score *= kNonPreferredModePenalty;
+ }
+ rankings.push_back(RefreshRateRanking{mode, score});
};
if (refreshRateOrder == RefreshRateOrder::Ascending) {
@@ -783,14 +816,15 @@
}
if (!rankings.empty() || !anchorGroupOpt) {
- return rankings;
+ return {rankings.begin(), rankings.end()};
}
ALOGW("Can't find %s refresh rate by policy with the same mode group"
" as the mode group %d",
refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());
- return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder);
+ return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder,
+ preferredDisplayModeOpt);
}
DisplayModePtr RefreshRateConfigs::getActiveModePtr() const {