summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rachel Lee <rnlee@google.com> 2024-03-15 01:35:35 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-03-15 01:35:35 +0000
commit9672eff8020cbe884c3d8141966e96711d63eec2 (patch)
treef5e139353667d2ac593d3ffe9d062671d158025a
parente26310e499d36f2c869acfd559a095733014c954 (diff)
parent19f01d0e17ab896e3a5ab1f90608175ffca95718 (diff)
Merge "NoPreference frame rate category is no-op" into main
-rw-r--r--services/surfaceflinger/Scheduler/RefreshRateSelector.cpp18
-rw-r--r--services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp143
2 files changed, 147 insertions, 14 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index ad59f1a574..56c29e2574 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -506,6 +506,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
}
int noVoteLayers = 0;
+ // Layers that prefer the same mode ("no-op").
+ int noPreferenceLayers = 0;
int minVoteLayers = 0;
int maxVoteLayers = 0;
int explicitDefaultVoteLayers = 0;
@@ -549,10 +551,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
explicitCategoryVoteLayers++;
}
if (layer.frameRateCategory == FrameRateCategory::NoPreference) {
- // Count this layer for Min vote as well. The explicit vote avoids
- // touch boost and idle for choosing a category, while Min vote is for correct
- // behavior when all layers are Min or no vote.
- minVoteLayers++;
+ noPreferenceLayers++;
}
break;
case LayerVoteType::Heuristic:
@@ -612,6 +611,16 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
return {ranking, kNoSignals};
}
+ // If all layers are category NoPreference, use the current config.
+ if (noPreferenceLayers + noVoteLayers == layers.size()) {
+ ALOGV("All layers NoPreference");
+ const auto ascendingWithPreferred =
+ rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, activeMode.getId());
+ ATRACE_FORMAT_INSTANT("%s (All layers NoPreference)",
+ to_string(ascendingWithPreferred.front().frameRateMode.fps).c_str());
+ return {ascendingWithPreferred, kNoSignals};
+ }
+
const bool smoothSwitchOnly = categorySmoothSwitchOnlyLayers > 0;
const DisplayModeId activeModeId = activeMode.getId();
@@ -643,6 +652,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
ftl::enum_string(layer.frameRateCategory).c_str());
if (layer.isNoVote() || layer.frameRateCategory == FrameRateCategory::NoPreference ||
layer.vote == LayerVoteType::Min) {
+ ALOGV("%s scoring skipped due to vote", formatLayerInfo(layer, layer.weight).c_str());
continue;
}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index fe0e3d11ae..a155f5da74 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -295,6 +295,12 @@ protected:
<< "Did not get expected frame rate for frameRate="
<< to_string(testCase.desiredFrameRate)
<< " category=" << ftl::enum_string(testCase.frameRateCategory);
+ EXPECT_EQ(testCase.expectedModeId,
+ selector.getBestFrameRateMode(layers).modePtr->getId())
+ << "Did not get expected DisplayModeId for modeId="
+ << ftl::to_underlying(testCase.expectedModeId)
+ << " frameRate=" << to_string(testCase.desiredFrameRate)
+ << " category=" << ftl::enum_string(testCase.frameRateCategory);
}
}
};
@@ -1534,7 +1540,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60
{0_Hz, FrameRateCategory::High, 90_Hz},
{0_Hz, FrameRateCategory::Normal, 60_Hz},
{0_Hz, FrameRateCategory::Low, 30_Hz},
- {0_Hz, FrameRateCategory::NoPreference, 30_Hz},
+ {0_Hz, FrameRateCategory::NoPreference, 60_Hz},
// Cases that have both desired frame rate and frame rate category requirements.
{24_Hz, FrameRateCategory::High, 120_Hz},
@@ -1591,6 +1597,7 @@ TEST_P(RefreshRateSelectorTest,
// Expected result
Fps expectedFrameRate = 0_Hz;
+ DisplayModeId expectedModeId = kModeId90;
};
testFrameRateCategoryWithMultipleLayers(
@@ -1605,7 +1612,7 @@ TEST_P(RefreshRateSelectorTest,
testFrameRateCategoryWithMultipleLayers(
std::initializer_list<Case>{
- {0_Hz, FrameRateCategory::Normal, 60_Hz},
+ {0_Hz, FrameRateCategory::Normal, 60_Hz, kModeId60},
{0_Hz, FrameRateCategory::High, 90_Hz},
{0_Hz, FrameRateCategory::NoPreference, 90_Hz},
},
@@ -1614,18 +1621,18 @@ TEST_P(RefreshRateSelectorTest,
testFrameRateCategoryWithMultipleLayers(
std::initializer_list<Case>{
{30_Hz, FrameRateCategory::High, 90_Hz},
- {24_Hz, FrameRateCategory::High, 120_Hz},
- {12_Hz, FrameRateCategory::Normal, 120_Hz},
- {30_Hz, FrameRateCategory::NoPreference, 120_Hz},
+ {24_Hz, FrameRateCategory::High, 120_Hz, kModeId120},
+ {12_Hz, FrameRateCategory::Normal, 120_Hz, kModeId120},
+ {30_Hz, FrameRateCategory::NoPreference, 120_Hz, kModeId120},
},
selector);
testFrameRateCategoryWithMultipleLayers(
std::initializer_list<Case>{
- {24_Hz, FrameRateCategory::Default, 120_Hz},
- {30_Hz, FrameRateCategory::Default, 120_Hz},
- {120_Hz, FrameRateCategory::Default, 120_Hz},
+ {24_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
+ {30_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
+ {120_Hz, FrameRateCategory::Default, 120_Hz, kModeId120},
},
selector);
}
@@ -1640,6 +1647,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategoryMultiL
// Expected result
Fps expectedFrameRate = 0_Hz;
+ DisplayModeId expectedModeId = kModeId120;
};
testFrameRateCategoryWithMultipleLayers(std::initializer_list<
@@ -1970,6 +1978,122 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_Touch
}
TEST_P(RefreshRateSelectorTest,
+ getBestFrameRateMode_withFrameRateCategory_idleTimer_60_120_nonVrr) {
+ SET_FLAG_FOR_TEST(flags::vrr_config, false);
+ using KernelIdleTimerAction = RefreshRateSelector::KernelIdleTimerAction;
+ struct LayerArg {
+ // Params
+ FrameRateCategory frameRateCategory = FrameRateCategory::Default;
+ LayerVoteType voteType = LayerVoteType::ExplicitDefault;
+
+ // Expected result
+ Fps expectedFrameRate = 0_Hz;
+ DisplayModeId expectedModeId = kModeId60;
+ };
+
+ const auto runTest = [&](const TestableRefreshRateSelector& selector,
+ const std::initializer_list<LayerArg>& layerArgs,
+ const RefreshRateSelector::GlobalSignals& signals) {
+ std::vector<LayerRequirement> layers;
+ for (auto testCase : layerArgs) {
+ ALOGI("**** %s: Testing frameRateCategory=%s", __func__,
+ ftl::enum_string(testCase.frameRateCategory).c_str());
+
+ if (testCase.frameRateCategory != FrameRateCategory::Default) {
+ std::stringstream ss;
+ ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) << ")";
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = LayerVoteType::ExplicitCategory,
+ .frameRateCategory = testCase.frameRateCategory,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ if (testCase.voteType != LayerVoteType::ExplicitDefault) {
+ std::stringstream ss;
+ ss << ftl::enum_string(testCase.voteType);
+ LayerRequirement layer = {.name = ss.str(),
+ .vote = testCase.voteType,
+ .weight = 1.f};
+ layers.push_back(layer);
+ }
+
+ EXPECT_EQ(testCase.expectedFrameRate,
+ selector.getBestFrameRateMode(layers, signals).modePtr->getPeakFps())
+ << "Did not get expected frame rate for"
+ << " category=" << ftl::enum_string(testCase.frameRateCategory);
+ EXPECT_EQ(testCase.expectedModeId,
+ selector.getBestFrameRateMode(layers, signals).modePtr->getId())
+ << "Did not get expected DisplayModeId for modeId="
+ << ftl::to_underlying(testCase.expectedModeId)
+ << " category=" << ftl::enum_string(testCase.frameRateCategory);
+ }
+ };
+
+ {
+ // IdleTimer not configured
+ auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120);
+ ASSERT_EQ(0ms, selector.getIdleTimerTimeout());
+
+ runTest(selector,
+ std::initializer_list<LayerArg>{
+ // Rate does not change due to NoPreference.
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ {.voteType = LayerVoteType::NoVote,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ },
+ {.idle = false});
+ }
+
+ // IdleTimer configured
+ constexpr std::chrono::milliseconds kIdleTimerTimeoutMs = 10ms;
+ auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120,
+ Config{
+ .idleTimerTimeout = kIdleTimerTimeoutMs,
+ });
+ ASSERT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction());
+ ASSERT_EQ(kIdleTimerTimeoutMs, selector.getIdleTimerTimeout());
+ runTest(selector,
+ std::initializer_list<LayerArg>{
+ // Rate won't change immediately and will stay 120 due to NoPreference, as
+ // idle timer did not timeout yet.
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ {.voteType = LayerVoteType::NoVote,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 120_Hz,
+ .expectedModeId = kModeId120},
+ },
+ {.idle = false});
+
+ // Idle timer is triggered using GlobalSignals.
+ ASSERT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction());
+ ASSERT_EQ(kIdleTimerTimeoutMs, selector.getIdleTimerTimeout());
+ runTest(selector,
+ std::initializer_list<LayerArg>{
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 60_Hz,
+ .expectedModeId = kModeId60},
+ {.voteType = LayerVoteType::NoVote,
+ .expectedFrameRate = 60_Hz,
+ .expectedModeId = kModeId60},
+ {.frameRateCategory = FrameRateCategory::NoPreference,
+ .expectedFrameRate = 60_Hz,
+ .expectedModeId = kModeId60},
+ },
+ {.idle = true});
+}
+
+TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_nonVrr) {
if (GetParam() != Config::FrameRateOverride::Enabled) {
return;
@@ -1992,8 +2116,7 @@ TEST_P(RefreshRateSelectorTest,
const std::initializer_list<Case> testCases = {
// These layers may switch modes because smoothSwitchOnly=false.
{FrameRateCategory::Default, false, 120_Hz, kModeId120},
- // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate.
- {FrameRateCategory::NoPreference, false, 60_Hz, kModeId60},
+ {FrameRateCategory::NoPreference, false, 120_Hz, kModeId120},
{FrameRateCategory::Low, false, 30_Hz, kModeId60},
{FrameRateCategory::Normal, false, 60_Hz, kModeId60},
{FrameRateCategory::High, false, 120_Hz, kModeId120},