Loading services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +27 −7 Original line number Diff line number Diff line Loading @@ -474,21 +474,23 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay } auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const -> RankedFrameRates { GlobalSignals signals, Fps pacesetterFps) const -> RankedFrameRates { GetRankedFrameRatesCache cache{layers, signals, pacesetterFps}; std::lock_guard lock(mLock); if (mGetRankedFrameRatesCache && mGetRankedFrameRatesCache->arguments == std::make_pair(layers, signals)) { if (mGetRankedFrameRatesCache && mGetRankedFrameRatesCache->matches(cache)) { return mGetRankedFrameRatesCache->result; } const auto result = getRankedFrameRatesLocked(layers, signals); mGetRankedFrameRatesCache = GetRankedFrameRatesCache{{layers, signals}, result}; return result; cache.result = getRankedFrameRatesLocked(layers, signals, pacesetterFps); mGetRankedFrameRatesCache = std::move(cache); return mGetRankedFrameRatesCache->result; } auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const GlobalSignals signals, Fps pacesetterFps) const -> RankedFrameRates { using namespace fps_approx_ops; ATRACE_CALL(); Loading @@ -496,6 +498,24 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi const auto& activeMode = *getActiveModeLocked().modePtr; if (pacesetterFps.isValid()) { ALOGV("Follower display"); const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending, std::nullopt, [&](FrameRateMode mode) { return mode.modePtr->getPeakFps() == pacesetterFps; }); if (!ranking.empty()) { ATRACE_FORMAT_INSTANT("%s (Follower display)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals, pacesetterFps}; } ALOGW("Follower display cannot follow the pacesetter"); } // Keep the display at max frame rate for the duration of powering on the display. if (signals.powerOnImminent) { ALOGV("Power On Imminent"); Loading services/surfaceflinger/Scheduler/RefreshRateSelector.h +18 −5 Original line number Diff line number Diff line Loading @@ -233,14 +233,18 @@ public: struct RankedFrameRates { FrameRateRanking ranking; // Ordered by descending score. GlobalSignals consideredSignals; Fps pacesetterFps; bool operator==(const RankedFrameRates& other) const { return ranking == other.ranking && consideredSignals == other.consideredSignals; return ranking == other.ranking && consideredSignals == other.consideredSignals && isApproxEqual(pacesetterFps, other.pacesetterFps); } }; RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); // If valid, `pacesetterFps` (used by follower displays) filters the ranking to modes matching // that refresh rate. RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals, Fps pacesetterFps = {}) const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); Loading Loading @@ -415,7 +419,8 @@ private: const FrameRateMode& getActiveModeLocked() const REQUIRES(mLock); RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const REQUIRES(mLock); GlobalSignals signals, Fps pacesetterFps) const REQUIRES(mLock); // Returns number of display frames and remainder when dividing the layer refresh period by // display refresh period. Loading Loading @@ -534,8 +539,16 @@ private: Config::FrameRateOverride mFrameRateOverrideConfig; struct GetRankedFrameRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; std::vector<LayerRequirement> layers; GlobalSignals signals; Fps pacesetterFps; RankedFrameRates result; bool matches(const GetRankedFrameRatesCache& other) const { return layers == other.layers && signals == other.signals && isApproxEqual(pacesetterFps, other.pacesetterFps); } }; mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock); Loading services/surfaceflinger/Scheduler/Scheduler.cpp +19 −26 Original line number Diff line number Diff line Loading @@ -1149,38 +1149,31 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { ATRACE_CALL(); using RankedRefreshRates = RefreshRateSelector::RankedFrameRates; ui::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking; DisplayModeChoiceMap modeChoices; const auto globalSignals = makeGlobalSignals(); Fps pacesetterFps; for (const auto& [id, display] : mDisplays) { const Fps pacesetterFps = [&]() REQUIRES(mPolicyLock, mDisplayLock, kMainThreadContext) { auto rankedFrameRates = display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, pacesetterSelectorPtrLocked()->getRankedFrameRates(mPolicy.contentRequirements, globalSignals); if (id == *mPacesetterDisplayId) { pacesetterFps = rankedFrameRates.ranking.front().frameRateMode.fps; } perDisplayRanking.push_back(std::move(rankedFrameRates)); } DisplayModeChoiceMap modeChoices; using fps_approx_ops::operator==; const Fps pacesetterFps = rankedFrameRates.ranking.front().frameRateMode.fps; for (auto& [rankings, signals] : perDisplayRanking) { const auto chosenFrameRateMode = ftl::find_if(rankings, [&](const auto& ranking) { return ranking.frameRateMode.fps == pacesetterFps; }) .transform([](const auto& scoredFrameRate) { return scoredFrameRate.get().frameRateMode; }) .value_or(rankings.front().frameRateMode); modeChoices.try_emplace(*mPacesetterDisplayId, DisplayModeChoice::from(std::move(rankedFrameRates))); return pacesetterFps; }(); for (const auto& [id, display] : mDisplays) { if (id == *mPacesetterDisplayId) continue; modeChoices.try_emplace(chosenFrameRateMode.modePtr->getPhysicalDisplayId(), DisplayModeChoice{chosenFrameRateMode, signals}); auto rankedFrameRates = display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals, pacesetterFps); modeChoices.try_emplace(id, DisplayModeChoice::from(std::move(rankedFrameRates))); } return modeChoices; } Loading services/surfaceflinger/Scheduler/Scheduler.h +5 −0 Original line number Diff line number Diff line Loading @@ -402,6 +402,11 @@ private: DisplayModeChoice(FrameRateMode mode, GlobalSignals consideredSignals) : mode(std::move(mode)), consideredSignals(consideredSignals) {} static DisplayModeChoice from(RefreshRateSelector::RankedFrameRates rankedFrameRates) { return {rankedFrameRates.ranking.front().frameRateMode, rankedFrameRates.consideredSignals}; } FrameRateMode mode; GlobalSignals consideredSignals; Loading services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +46 −19 Original line number Diff line number Diff line Loading @@ -103,8 +103,9 @@ struct TestableRefreshRateSelector : RefreshRateSelector { auto& mutableGetRankedRefreshRatesCache() { return mGetRankedFrameRatesCache; } auto getRankedFrameRates(const std::vector<LayerRequirement>& layers, GlobalSignals signals = {}) const { const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals); GlobalSignals signals = {}, Fps pacesetterFps = {}) const { const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals, pacesetterFps); EXPECT_TRUE(std::is_sorted(result.ranking.begin(), result.ranking.end(), ScoredFrameRate::DescendingScore{})); Loading @@ -114,8 +115,8 @@ struct TestableRefreshRateSelector : RefreshRateSelector { auto getRankedRefreshRatesAsPair(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const { const auto [ranking, consideredSignals] = getRankedFrameRates(layers, signals); return std::make_pair(ranking, consideredSignals); const auto result = getRankedFrameRates(layers, signals); return std::make_pair(result.ranking, result.consideredSignals); } FrameRateMode getBestFrameRateMode(const std::vector<LayerRequirement>& layers = {}, Loading Loading @@ -1387,7 +1388,7 @@ TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); auto [refreshRates, signals] = selector.getRankedFrameRates({}, {}); auto [refreshRates, signals, _] = selector.getRankedFrameRates({}, {}); EXPECT_FALSE(signals.powerOnImminent); auto expectedRefreshRates = []() -> std::vector<FrameRateMode> { Loading Loading @@ -1471,10 +1472,32 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { } } TEST_P(RefreshRateSelectorTest, pacesetterConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); constexpr RefreshRateSelector::GlobalSignals kNoSignals; std::vector<LayerRequirement> layers = {{.weight = 1.f}}; layers[0].vote = LayerVoteType::Min; // The pacesetterFps takes precedence over the LayerRequirement. { const auto result = selector.getRankedFrameRates(layers, {}, 90_Hz); EXPECT_EQ(kMode90, result.ranking.front().frameRateMode.modePtr); EXPECT_EQ(kNoSignals, result.consideredSignals); } // The pacesetterFps takes precedence over GlobalSignals. { const auto result = selector.getRankedFrameRates(layers, {.touch = true}, 60_Hz); EXPECT_EQ(kMode60, result.ranking.front().frameRateMode.modePtr); EXPECT_EQ(kNoSignals, result.consideredSignals); } } TEST_P(RefreshRateSelectorTest, touchConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); auto [_, signals] = selector.getRankedFrameRates({}, {}); auto signals = selector.getRankedFrameRates({}, {}).consideredSignals; EXPECT_FALSE(signals.touch); std::tie(std::ignore, signals) = selector.getRankedRefreshRatesAsPair({}, {.touch = true}); Loading Loading @@ -2363,7 +2386,7 @@ TEST_P(RefreshRateSelectorTest, lr.name = "60Hz ExplicitDefault"; lr.focused = true; const auto [rankedFrameRate, signals] = const auto [rankedFrameRate, signals, _] = selector.getRankedFrameRates(layers, {.touch = true, .idle = true}); EXPECT_EQ(rankedFrameRate.begin()->frameRateMode.modePtr, kMode60); Loading Loading @@ -2587,7 +2610,7 @@ TEST_P(RefreshRateSelectorTest, EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {k90, k90}, {k60_90, k60_90}})); const auto [ranking, signals] = selector.getRankedFrameRates({}, {}); const auto [ranking, signals, _] = selector.getRankedFrameRates({}, {}); EXPECT_EQ(ranking.front().frameRateMode.modePtr, kMode90); EXPECT_FALSE(signals.touch); Loading Loading @@ -2971,7 +2994,7 @@ TEST_P(RefreshRateSelectorTest, idle) { layers[0].vote = voteType; layers[0].desiredRefreshRate = 90_Hz; const auto [ranking, signals] = const auto [ranking, signals, _] = selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); // Refresh rate will be chosen by either touch state or idle state. Loading Loading @@ -3121,16 +3144,17 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ReadsCache) { auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); using GlobalSignals = RefreshRateSelector::GlobalSignals; const auto args = std::make_pair(std::vector<LayerRequirement>{}, GlobalSignals{.touch = true, .idle = true}); const RefreshRateSelector::RankedFrameRates result = {{RefreshRateSelector::ScoredFrameRate{ {90_Hz, kMode90}}}, GlobalSignals{.touch = true}}; selector.mutableGetRankedRefreshRatesCache() = {args, result}; selector.mutableGetRankedRefreshRatesCache() = {.layers = std::vector<LayerRequirement>{}, .signals = GlobalSignals{.touch = true, .idle = true}, .result = result}; EXPECT_EQ(result, selector.getRankedFrameRates(args.first, args.second)); const auto& cache = *selector.mutableGetRankedRefreshRatesCache(); EXPECT_EQ(result, selector.getRankedFrameRates(cache.layers, cache.signals)); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_WritesCache) { Loading @@ -3138,15 +3162,18 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_WritesCache) { EXPECT_FALSE(selector.mutableGetRankedRefreshRatesCache()); std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; RefreshRateSelector::GlobalSignals globalSignals{.touch = true, .idle = true}; const std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; const RefreshRateSelector::GlobalSignals globalSignals{.touch = true, .idle = true}; const Fps pacesetterFps = 60_Hz; const auto result = selector.getRankedFrameRates(layers, globalSignals); const auto result = selector.getRankedFrameRates(layers, globalSignals, pacesetterFps); const auto& cache = selector.mutableGetRankedRefreshRatesCache(); ASSERT_TRUE(cache); EXPECT_EQ(cache->arguments, std::make_pair(layers, globalSignals)); EXPECT_EQ(cache->layers, layers); EXPECT_EQ(cache->signals, globalSignals); EXPECT_EQ(cache->pacesetterFps, pacesetterFps); EXPECT_EQ(cache->result, result); } Loading Loading @@ -4073,7 +4100,7 @@ TEST_P(RefreshRateSelectorTest, idleWhenLowestRefreshRateIsNotDivisor) { layers[0].vote = voteType; layers[0].desiredRefreshRate = 90_Hz; const auto [ranking, signals] = const auto [ranking, signals, _] = selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); // Refresh rate will be chosen by either touch state or idle state. Loading Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +27 −7 Original line number Diff line number Diff line Loading @@ -474,21 +474,23 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay } auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const -> RankedFrameRates { GlobalSignals signals, Fps pacesetterFps) const -> RankedFrameRates { GetRankedFrameRatesCache cache{layers, signals, pacesetterFps}; std::lock_guard lock(mLock); if (mGetRankedFrameRatesCache && mGetRankedFrameRatesCache->arguments == std::make_pair(layers, signals)) { if (mGetRankedFrameRatesCache && mGetRankedFrameRatesCache->matches(cache)) { return mGetRankedFrameRatesCache->result; } const auto result = getRankedFrameRatesLocked(layers, signals); mGetRankedFrameRatesCache = GetRankedFrameRatesCache{{layers, signals}, result}; return result; cache.result = getRankedFrameRatesLocked(layers, signals, pacesetterFps); mGetRankedFrameRatesCache = std::move(cache); return mGetRankedFrameRatesCache->result; } auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const GlobalSignals signals, Fps pacesetterFps) const -> RankedFrameRates { using namespace fps_approx_ops; ATRACE_CALL(); Loading @@ -496,6 +498,24 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi const auto& activeMode = *getActiveModeLocked().modePtr; if (pacesetterFps.isValid()) { ALOGV("Follower display"); const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending, std::nullopt, [&](FrameRateMode mode) { return mode.modePtr->getPeakFps() == pacesetterFps; }); if (!ranking.empty()) { ATRACE_FORMAT_INSTANT("%s (Follower display)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals, pacesetterFps}; } ALOGW("Follower display cannot follow the pacesetter"); } // Keep the display at max frame rate for the duration of powering on the display. if (signals.powerOnImminent) { ALOGV("Power On Imminent"); Loading
services/surfaceflinger/Scheduler/RefreshRateSelector.h +18 −5 Original line number Diff line number Diff line Loading @@ -233,14 +233,18 @@ public: struct RankedFrameRates { FrameRateRanking ranking; // Ordered by descending score. GlobalSignals consideredSignals; Fps pacesetterFps; bool operator==(const RankedFrameRates& other) const { return ranking == other.ranking && consideredSignals == other.consideredSignals; return ranking == other.ranking && consideredSignals == other.consideredSignals && isApproxEqual(pacesetterFps, other.pacesetterFps); } }; RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock); // If valid, `pacesetterFps` (used by follower displays) filters the ranking to modes matching // that refresh rate. RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals, Fps pacesetterFps = {}) const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); Loading Loading @@ -415,7 +419,8 @@ private: const FrameRateMode& getActiveModeLocked() const REQUIRES(mLock); RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const REQUIRES(mLock); GlobalSignals signals, Fps pacesetterFps) const REQUIRES(mLock); // Returns number of display frames and remainder when dividing the layer refresh period by // display refresh period. Loading Loading @@ -534,8 +539,16 @@ private: Config::FrameRateOverride mFrameRateOverrideConfig; struct GetRankedFrameRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; std::vector<LayerRequirement> layers; GlobalSignals signals; Fps pacesetterFps; RankedFrameRates result; bool matches(const GetRankedFrameRatesCache& other) const { return layers == other.layers && signals == other.signals && isApproxEqual(pacesetterFps, other.pacesetterFps); } }; mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock); Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +19 −26 Original line number Diff line number Diff line Loading @@ -1149,38 +1149,31 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { ATRACE_CALL(); using RankedRefreshRates = RefreshRateSelector::RankedFrameRates; ui::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking; DisplayModeChoiceMap modeChoices; const auto globalSignals = makeGlobalSignals(); Fps pacesetterFps; for (const auto& [id, display] : mDisplays) { const Fps pacesetterFps = [&]() REQUIRES(mPolicyLock, mDisplayLock, kMainThreadContext) { auto rankedFrameRates = display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, pacesetterSelectorPtrLocked()->getRankedFrameRates(mPolicy.contentRequirements, globalSignals); if (id == *mPacesetterDisplayId) { pacesetterFps = rankedFrameRates.ranking.front().frameRateMode.fps; } perDisplayRanking.push_back(std::move(rankedFrameRates)); } DisplayModeChoiceMap modeChoices; using fps_approx_ops::operator==; const Fps pacesetterFps = rankedFrameRates.ranking.front().frameRateMode.fps; for (auto& [rankings, signals] : perDisplayRanking) { const auto chosenFrameRateMode = ftl::find_if(rankings, [&](const auto& ranking) { return ranking.frameRateMode.fps == pacesetterFps; }) .transform([](const auto& scoredFrameRate) { return scoredFrameRate.get().frameRateMode; }) .value_or(rankings.front().frameRateMode); modeChoices.try_emplace(*mPacesetterDisplayId, DisplayModeChoice::from(std::move(rankedFrameRates))); return pacesetterFps; }(); for (const auto& [id, display] : mDisplays) { if (id == *mPacesetterDisplayId) continue; modeChoices.try_emplace(chosenFrameRateMode.modePtr->getPhysicalDisplayId(), DisplayModeChoice{chosenFrameRateMode, signals}); auto rankedFrameRates = display.selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals, pacesetterFps); modeChoices.try_emplace(id, DisplayModeChoice::from(std::move(rankedFrameRates))); } return modeChoices; } Loading
services/surfaceflinger/Scheduler/Scheduler.h +5 −0 Original line number Diff line number Diff line Loading @@ -402,6 +402,11 @@ private: DisplayModeChoice(FrameRateMode mode, GlobalSignals consideredSignals) : mode(std::move(mode)), consideredSignals(consideredSignals) {} static DisplayModeChoice from(RefreshRateSelector::RankedFrameRates rankedFrameRates) { return {rankedFrameRates.ranking.front().frameRateMode, rankedFrameRates.consideredSignals}; } FrameRateMode mode; GlobalSignals consideredSignals; Loading
services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +46 −19 Original line number Diff line number Diff line Loading @@ -103,8 +103,9 @@ struct TestableRefreshRateSelector : RefreshRateSelector { auto& mutableGetRankedRefreshRatesCache() { return mGetRankedFrameRatesCache; } auto getRankedFrameRates(const std::vector<LayerRequirement>& layers, GlobalSignals signals = {}) const { const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals); GlobalSignals signals = {}, Fps pacesetterFps = {}) const { const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals, pacesetterFps); EXPECT_TRUE(std::is_sorted(result.ranking.begin(), result.ranking.end(), ScoredFrameRate::DescendingScore{})); Loading @@ -114,8 +115,8 @@ struct TestableRefreshRateSelector : RefreshRateSelector { auto getRankedRefreshRatesAsPair(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const { const auto [ranking, consideredSignals] = getRankedFrameRates(layers, signals); return std::make_pair(ranking, consideredSignals); const auto result = getRankedFrameRates(layers, signals); return std::make_pair(result.ranking, result.consideredSignals); } FrameRateMode getBestFrameRateMode(const std::vector<LayerRequirement>& layers = {}, Loading Loading @@ -1387,7 +1388,7 @@ TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); auto [refreshRates, signals] = selector.getRankedFrameRates({}, {}); auto [refreshRates, signals, _] = selector.getRankedFrameRates({}, {}); EXPECT_FALSE(signals.powerOnImminent); auto expectedRefreshRates = []() -> std::vector<FrameRateMode> { Loading Loading @@ -1471,10 +1472,32 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { } } TEST_P(RefreshRateSelectorTest, pacesetterConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); constexpr RefreshRateSelector::GlobalSignals kNoSignals; std::vector<LayerRequirement> layers = {{.weight = 1.f}}; layers[0].vote = LayerVoteType::Min; // The pacesetterFps takes precedence over the LayerRequirement. { const auto result = selector.getRankedFrameRates(layers, {}, 90_Hz); EXPECT_EQ(kMode90, result.ranking.front().frameRateMode.modePtr); EXPECT_EQ(kNoSignals, result.consideredSignals); } // The pacesetterFps takes precedence over GlobalSignals. { const auto result = selector.getRankedFrameRates(layers, {.touch = true}, 60_Hz); EXPECT_EQ(kMode60, result.ranking.front().frameRateMode.modePtr); EXPECT_EQ(kNoSignals, result.consideredSignals); } } TEST_P(RefreshRateSelectorTest, touchConsidered) { auto selector = createSelector(kModes_60_90, kModeId60); auto [_, signals] = selector.getRankedFrameRates({}, {}); auto signals = selector.getRankedFrameRates({}, {}).consideredSignals; EXPECT_FALSE(signals.touch); std::tie(std::ignore, signals) = selector.getRankedRefreshRatesAsPair({}, {.touch = true}); Loading Loading @@ -2363,7 +2386,7 @@ TEST_P(RefreshRateSelectorTest, lr.name = "60Hz ExplicitDefault"; lr.focused = true; const auto [rankedFrameRate, signals] = const auto [rankedFrameRate, signals, _] = selector.getRankedFrameRates(layers, {.touch = true, .idle = true}); EXPECT_EQ(rankedFrameRate.begin()->frameRateMode.modePtr, kMode60); Loading Loading @@ -2587,7 +2610,7 @@ TEST_P(RefreshRateSelectorTest, EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {k90, k90}, {k60_90, k60_90}})); const auto [ranking, signals] = selector.getRankedFrameRates({}, {}); const auto [ranking, signals, _] = selector.getRankedFrameRates({}, {}); EXPECT_EQ(ranking.front().frameRateMode.modePtr, kMode90); EXPECT_FALSE(signals.touch); Loading Loading @@ -2971,7 +2994,7 @@ TEST_P(RefreshRateSelectorTest, idle) { layers[0].vote = voteType; layers[0].desiredRefreshRate = 90_Hz; const auto [ranking, signals] = const auto [ranking, signals, _] = selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); // Refresh rate will be chosen by either touch state or idle state. Loading Loading @@ -3121,16 +3144,17 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ReadsCache) { auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); using GlobalSignals = RefreshRateSelector::GlobalSignals; const auto args = std::make_pair(std::vector<LayerRequirement>{}, GlobalSignals{.touch = true, .idle = true}); const RefreshRateSelector::RankedFrameRates result = {{RefreshRateSelector::ScoredFrameRate{ {90_Hz, kMode90}}}, GlobalSignals{.touch = true}}; selector.mutableGetRankedRefreshRatesCache() = {args, result}; selector.mutableGetRankedRefreshRatesCache() = {.layers = std::vector<LayerRequirement>{}, .signals = GlobalSignals{.touch = true, .idle = true}, .result = result}; EXPECT_EQ(result, selector.getRankedFrameRates(args.first, args.second)); const auto& cache = *selector.mutableGetRankedRefreshRatesCache(); EXPECT_EQ(result, selector.getRankedFrameRates(cache.layers, cache.signals)); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_WritesCache) { Loading @@ -3138,15 +3162,18 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_WritesCache) { EXPECT_FALSE(selector.mutableGetRankedRefreshRatesCache()); std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; RefreshRateSelector::GlobalSignals globalSignals{.touch = true, .idle = true}; const std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; const RefreshRateSelector::GlobalSignals globalSignals{.touch = true, .idle = true}; const Fps pacesetterFps = 60_Hz; const auto result = selector.getRankedFrameRates(layers, globalSignals); const auto result = selector.getRankedFrameRates(layers, globalSignals, pacesetterFps); const auto& cache = selector.mutableGetRankedRefreshRatesCache(); ASSERT_TRUE(cache); EXPECT_EQ(cache->arguments, std::make_pair(layers, globalSignals)); EXPECT_EQ(cache->layers, layers); EXPECT_EQ(cache->signals, globalSignals); EXPECT_EQ(cache->pacesetterFps, pacesetterFps); EXPECT_EQ(cache->result, result); } Loading Loading @@ -4073,7 +4100,7 @@ TEST_P(RefreshRateSelectorTest, idleWhenLowestRefreshRateIsNotDivisor) { layers[0].vote = voteType; layers[0].desiredRefreshRate = 90_Hz; const auto [ranking, signals] = const auto [ranking, signals, _] = selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); // Refresh rate will be chosen by either touch state or idle state. Loading