Loading services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +16 −2 Original line number Diff line number Diff line Loading @@ -722,13 +722,17 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi const bool inPrimaryPhysicalRange = policy->primaryRanges.physical.includes(modePtr->getPeakFps()); const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps); if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) || if (!mIsVrrDevice.load() && ((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) || !inPrimaryRenderRange) && !(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. ALOGV("%s ignores %s (primaryRangeIsSingleRate). Current mode = %s", formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(), to_string(activeMode).c_str()); continue; } Loading Loading @@ -852,7 +856,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi to_string(descending.front().frameRateMode.fps).c_str()); return {descending, kNoSignals}; } else { ALOGV("primaryRangeIsSingleRate"); ALOGV("%s (primaryRangeIsSingleRate)", to_string(ranking.front().frameRateMode.fps).c_str()); SFTRACE_FORMAT_INSTANT("%s (primaryRangeIsSingleRate)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals}; Loading Loading @@ -932,6 +937,8 @@ PerUidLayerRequirements groupLayersByUid( using LayerVoteType = RefreshRateSelector::LayerVoteType; if (layer->vote == LayerVoteType::Max || layer->vote == LayerVoteType::Heuristic) { ALOGV("%s: %s skips uid=%d due to the vote", __func__, formatLayerInfo(*layer, layer->weight).c_str(), layer->ownerUid); skipUid = true; break; } Loading Loading @@ -1014,12 +1021,14 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme // Layers with ExplicitExactOrMultiple expect touch boost if (globalSignals.touch && hasExplicitExactOrMultiple) { ALOGV("%s: Skipping for touch (input signal): uid=%d", __func__, uid); continue; } // Mirrors getRankedFrameRates. If there is no ExplicitDefault, expect touch boost and // skip frame rate override. if (hasHighHint && !hasExplicitDefault) { ALOGV("%s: Skipping for touch (HighHint): uid=%d", __func__, uid); continue; } Loading @@ -1043,6 +1052,9 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme constexpr bool isSeamlessSwitch = true; const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch); score += layer->weight * layerScore; ALOGV("%s: %s gives %s fps score of %.4f", __func__, formatLayerInfo(*layer, layer->weight).c_str(), to_string(fps).c_str(), layerScore); } } Loading Loading @@ -1297,6 +1309,8 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a LOG_ALWAYS_FATAL_IF(!activeModeOpt); mActiveModeOpt = FrameRateMode{activeModeOpt->get()->getPeakFps(), ftl::as_non_null(activeModeOpt->get())}; mIsVrrDevice = FlagManager::getInstance().vrr_config() && activeModeOpt->get()->getVrrConfig().has_value(); const auto sortedModes = sortByRefreshRate(mDisplayModes); mMinRefreshRateModeIt = sortedModes.front(); Loading services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +128 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,42 @@ protected: << " category=" << ftl::enum_string(testCase.frameRateCategory); } } template <class T> std::vector<LayerRequirement> createLayers(const std::initializer_list<T>& surfaceVotes) { std::vector<LayerRequirement> layers; for (auto surfaceVote : surfaceVotes) { ALOGI("**** %s: Adding layers for %s: (desiredFrameRate=%s, voteType=%s), " "(frameRateCategory=%s)", __func__, surfaceVote.name.c_str(), to_string(surfaceVote.desiredFrameRate).c_str(), ftl::enum_string(surfaceVote.voteType).c_str(), ftl::enum_string(surfaceVote.frameRateCategory).c_str()); if (surfaceVote.desiredFrameRate.isValid()) { std::stringstream ss; ss << surfaceVote.name << " (" << surfaceVote.weight << "): ExplicitDefault (" << to_string(surfaceVote.desiredFrameRate) << ")"; LayerRequirement layer = {.name = ss.str(), .vote = surfaceVote.voteType, .desiredRefreshRate = surfaceVote.desiredFrameRate, .weight = surfaceVote.weight}; layers.push_back(layer); } if (surfaceVote.frameRateCategory != FrameRateCategory::Default) { std::stringstream ss; ss << surfaceVote.name << " (" << surfaceVote.weight << "): ExplicitCategory (" << ftl::enum_string(surfaceVote.frameRateCategory) << ")"; LayerRequirement layer = {.name = ss.str(), .vote = LayerVoteType::ExplicitCategory, .frameRateCategory = surfaceVote.frameRateCategory, .weight = surfaceVote.weight}; layers.push_back(layer); } } return layers; } }; RefreshRateSelectorTest::RefreshRateSelectorTest() { Loading Loading @@ -1776,6 +1812,98 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategoryMultiL selector); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multiSurface_arr) { if (GetParam() != Config::FrameRateOverride::Enabled) { return; } SET_FLAG_FOR_TEST(flags::vrr_config, true); auto selector = createSelector(kVrrMode_120, kModeId120); // Switch the policy to be more like an ARR device (primary range is a single rate). constexpr FpsRange k120_120Hz = {120_Hz, 120_Hz}; constexpr FpsRange k0_120Hz = {0_Hz, 120_Hz}; constexpr FpsRanges kPrimaryRanges = {/*physical*/ k120_120Hz, /*render*/ k120_120Hz}; constexpr FpsRanges kAppRequestRanges = {/*physical*/ k120_120Hz, /*render*/ k0_120Hz}; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy( {/*defaultMode*/ kModeId120, kPrimaryRanges, kAppRequestRanges})); // Surface can translate to multiple layers in SF scheduler due to category and frame rate // value. struct SurfaceVote { // Params std::string name = ""; Fps desiredFrameRate = 0_Hz; LayerVoteType voteType = LayerVoteType::ExplicitDefault; FrameRateCategory frameRateCategory = FrameRateCategory::Default; float weight = 1.f; }; auto layers = createLayers( std::initializer_list<SurfaceVote>{{.name = "60 fixed source", .desiredFrameRate = 60_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .weight = 0.27f}, {.name = "1 fixed source + NoPreference", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); auto actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(60_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers( std::initializer_list<SurfaceVote>{{.name = "60 fixed source", .desiredFrameRate = 60_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .weight = 0.27f}, {.name = "1 fixed source + Normal", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::Normal}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(60_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "30 fixed source + NoPreference", .desiredFrameRate = 30_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(30_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "1 fixed source + NoPreference", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); // Result affected by RefreshRateSelector.kMinSupportedFrameRate. EXPECT_EQ(20_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "24 fixed source + NoPreference", .desiredFrameRate = 24_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(24_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "23.976 fixed source + NoPreference", .desiredFrameRate = 23.976_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); // Chooses 120 unless certain threshold is set, see tests test23976Chooses120 and // test23976Chooses60IfThresholdIs120. EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_120) { auto selector = createSelector(makeModes(kMode60, kMode120), kModeId60); Loading Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +16 −2 Original line number Diff line number Diff line Loading @@ -722,13 +722,17 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi const bool inPrimaryPhysicalRange = policy->primaryRanges.physical.includes(modePtr->getPeakFps()); const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps); if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) || if (!mIsVrrDevice.load() && ((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) || !inPrimaryRenderRange) && !(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. ALOGV("%s ignores %s (primaryRangeIsSingleRate). Current mode = %s", formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(), to_string(activeMode).c_str()); continue; } Loading Loading @@ -852,7 +856,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi to_string(descending.front().frameRateMode.fps).c_str()); return {descending, kNoSignals}; } else { ALOGV("primaryRangeIsSingleRate"); ALOGV("%s (primaryRangeIsSingleRate)", to_string(ranking.front().frameRateMode.fps).c_str()); SFTRACE_FORMAT_INSTANT("%s (primaryRangeIsSingleRate)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals}; Loading Loading @@ -932,6 +937,8 @@ PerUidLayerRequirements groupLayersByUid( using LayerVoteType = RefreshRateSelector::LayerVoteType; if (layer->vote == LayerVoteType::Max || layer->vote == LayerVoteType::Heuristic) { ALOGV("%s: %s skips uid=%d due to the vote", __func__, formatLayerInfo(*layer, layer->weight).c_str(), layer->ownerUid); skipUid = true; break; } Loading Loading @@ -1014,12 +1021,14 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme // Layers with ExplicitExactOrMultiple expect touch boost if (globalSignals.touch && hasExplicitExactOrMultiple) { ALOGV("%s: Skipping for touch (input signal): uid=%d", __func__, uid); continue; } // Mirrors getRankedFrameRates. If there is no ExplicitDefault, expect touch boost and // skip frame rate override. if (hasHighHint && !hasExplicitDefault) { ALOGV("%s: Skipping for touch (HighHint): uid=%d", __func__, uid); continue; } Loading @@ -1043,6 +1052,9 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme constexpr bool isSeamlessSwitch = true; const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch); score += layer->weight * layerScore; ALOGV("%s: %s gives %s fps score of %.4f", __func__, formatLayerInfo(*layer, layer->weight).c_str(), to_string(fps).c_str(), layerScore); } } Loading Loading @@ -1297,6 +1309,8 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a LOG_ALWAYS_FATAL_IF(!activeModeOpt); mActiveModeOpt = FrameRateMode{activeModeOpt->get()->getPeakFps(), ftl::as_non_null(activeModeOpt->get())}; mIsVrrDevice = FlagManager::getInstance().vrr_config() && activeModeOpt->get()->getVrrConfig().has_value(); const auto sortedModes = sortByRefreshRate(mDisplayModes); mMinRefreshRateModeIt = sortedModes.front(); Loading
services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +128 −0 Original line number Diff line number Diff line Loading @@ -308,6 +308,42 @@ protected: << " category=" << ftl::enum_string(testCase.frameRateCategory); } } template <class T> std::vector<LayerRequirement> createLayers(const std::initializer_list<T>& surfaceVotes) { std::vector<LayerRequirement> layers; for (auto surfaceVote : surfaceVotes) { ALOGI("**** %s: Adding layers for %s: (desiredFrameRate=%s, voteType=%s), " "(frameRateCategory=%s)", __func__, surfaceVote.name.c_str(), to_string(surfaceVote.desiredFrameRate).c_str(), ftl::enum_string(surfaceVote.voteType).c_str(), ftl::enum_string(surfaceVote.frameRateCategory).c_str()); if (surfaceVote.desiredFrameRate.isValid()) { std::stringstream ss; ss << surfaceVote.name << " (" << surfaceVote.weight << "): ExplicitDefault (" << to_string(surfaceVote.desiredFrameRate) << ")"; LayerRequirement layer = {.name = ss.str(), .vote = surfaceVote.voteType, .desiredRefreshRate = surfaceVote.desiredFrameRate, .weight = surfaceVote.weight}; layers.push_back(layer); } if (surfaceVote.frameRateCategory != FrameRateCategory::Default) { std::stringstream ss; ss << surfaceVote.name << " (" << surfaceVote.weight << "): ExplicitCategory (" << ftl::enum_string(surfaceVote.frameRateCategory) << ")"; LayerRequirement layer = {.name = ss.str(), .vote = LayerVoteType::ExplicitCategory, .frameRateCategory = surfaceVote.frameRateCategory, .weight = surfaceVote.weight}; layers.push_back(layer); } } return layers; } }; RefreshRateSelectorTest::RefreshRateSelectorTest() { Loading Loading @@ -1776,6 +1812,98 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategoryMultiL selector); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multiSurface_arr) { if (GetParam() != Config::FrameRateOverride::Enabled) { return; } SET_FLAG_FOR_TEST(flags::vrr_config, true); auto selector = createSelector(kVrrMode_120, kModeId120); // Switch the policy to be more like an ARR device (primary range is a single rate). constexpr FpsRange k120_120Hz = {120_Hz, 120_Hz}; constexpr FpsRange k0_120Hz = {0_Hz, 120_Hz}; constexpr FpsRanges kPrimaryRanges = {/*physical*/ k120_120Hz, /*render*/ k120_120Hz}; constexpr FpsRanges kAppRequestRanges = {/*physical*/ k120_120Hz, /*render*/ k0_120Hz}; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy( {/*defaultMode*/ kModeId120, kPrimaryRanges, kAppRequestRanges})); // Surface can translate to multiple layers in SF scheduler due to category and frame rate // value. struct SurfaceVote { // Params std::string name = ""; Fps desiredFrameRate = 0_Hz; LayerVoteType voteType = LayerVoteType::ExplicitDefault; FrameRateCategory frameRateCategory = FrameRateCategory::Default; float weight = 1.f; }; auto layers = createLayers( std::initializer_list<SurfaceVote>{{.name = "60 fixed source", .desiredFrameRate = 60_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .weight = 0.27f}, {.name = "1 fixed source + NoPreference", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); auto actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(60_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers( std::initializer_list<SurfaceVote>{{.name = "60 fixed source", .desiredFrameRate = 60_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .weight = 0.27f}, {.name = "1 fixed source + Normal", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::Normal}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(60_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "30 fixed source + NoPreference", .desiredFrameRate = 30_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(30_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "1 fixed source + NoPreference", .desiredFrameRate = 1_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); // Result affected by RefreshRateSelector.kMinSupportedFrameRate. EXPECT_EQ(20_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "24 fixed source + NoPreference", .desiredFrameRate = 24_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); EXPECT_EQ(24_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); layers = createLayers(std::initializer_list<SurfaceVote>{ {.name = "23.976 fixed source + NoPreference", .desiredFrameRate = 23.976_Hz, .voteType = LayerVoteType::ExplicitExactOrMultiple, .frameRateCategory = FrameRateCategory::NoPreference}}); actualRankedFrameRates = selector.getRankedFrameRates(layers); // Chooses 120 unless certain threshold is set, see tests test23976Chooses120 and // test23976Chooses60IfThresholdIs120. EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_120) { auto selector = createSelector(makeModes(kMode60, kMode120), kModeId60); Loading