From 686360612b52e825e516ccc706e9c7c43e316c65 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 16 Nov 2022 17:07:25 -0800 Subject: SF: add render frame rate dimension to RefreshRateSelector RefreshRateSelector will now select the render frame rate in addition to the display refresh rate. This will allow SF (in follow up CL) to schedule frames based on the render frame rate instead of being tied to the display refresh rate. The render frame rate is a divisor of the display refresh rate. Bug: 257071863 Test: atest libsurfaceflinger_unittest Change-Id: Id6aaa389b431514fc06190d88d16eb9fcf0ba348 --- services/surfaceflinger/Layer.cpp | 2 +- .../Scheduler/RefreshRateSelector.cpp | 416 +++--- .../surfaceflinger/Scheduler/RefreshRateSelector.h | 91 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 25 +- .../Scheduler/include/scheduler/Fps.h | 13 + .../Scheduler/include/scheduler/FrameRateMode.h | 44 + services/surfaceflinger/SurfaceFlinger.cpp | 6 +- .../fuzzer/surfaceflinger_scheduler_fuzzer.cpp | 2 +- .../tests/unittests/RefreshRateSelectorTest.cpp | 1389 ++++++++++++-------- 9 files changed, 1278 insertions(+), 710 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index be5fffc017..37eb20ba91 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1123,7 +1123,7 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for // the same reason we are allowing touch boost for those layers. See - // RefreshRateSelector::rankRefreshRates for details. + // RefreshRateSelector::rankFrameRates for details. const auto layerVotedWithDefaultCompatibility = frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote; diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index 8d4ea0520a..fd1a733b7a 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include "../SurfaceFlingerProperties.h" @@ -43,7 +45,7 @@ namespace android::scheduler { namespace { struct RefreshRateScore { - DisplayModeIterator modeIt; + FrameRateMode frameRateMode; float overallScore; struct { float modeBelowThreshold; @@ -77,19 +79,11 @@ std::vector constructKnownFrameRates(const DisplayModes& modes) { return knownFrameRates; } -// The Filter is a `bool(const DisplayMode&)` predicate. -template -std::vector sortByRefreshRate(const DisplayModes& modes, Filter&& filter) { +std::vector sortByRefreshRate(const DisplayModes& modes) { std::vector sortedModes; sortedModes.reserve(modes.size()); - for (auto it = modes.begin(); it != modes.end(); ++it) { - const auto& [id, mode] = *it; - - if (filter(*mode)) { - ALOGV("%s: including mode %d", __func__, id.value()); - sortedModes.push_back(it); - } + sortedModes.push_back(it); } std::sort(sortedModes.begin(), sortedModes.end(), [](auto it1, auto it2) { @@ -106,6 +100,21 @@ std::vector sortByRefreshRate(const DisplayModes& modes, Fi return sortedModes; } +std::pair divisorRange(Fps fps, FpsRange range, + RefreshRateSelector::Config::FrameRateOverride config) { + if (config != RefreshRateSelector::Config::FrameRateOverride::Enabled) { + return {1, 1}; + } + + using fps_approx_ops::operator/; + const auto start = std::max(1u, fps / range.max - 1); + const auto end = fps / + std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate, + fps_approx_ops::operator<); + + return {start, end}; +} + bool shouldEnableFrameRateOverride(const std::vector& sortedModes) { for (const auto it1 : sortedModes) { const auto& mode1 = it1->second; @@ -136,27 +145,109 @@ std::string toString(const RefreshRateSelector::PolicyVariant& policy) { } // namespace +auto RefreshRateSelector::createFrameRateModes( + std::function&& filterModes, const FpsRange& renderRange) const + -> std::vector { + struct Key { + Fps fps; + int32_t group; + }; + + struct KeyLess { + bool operator()(const Key& a, const Key& b) const { + using namespace fps_approx_ops; + if (a.fps != b.fps) { + return a.fps < b.fps; + } + + // For the same fps the order doesn't really matter, but we still + // want the behaviour of a strictly less operator. + // We use the group id as the secondary ordering for that. + return a.group < b.group; + } + }; + + std::map ratesMap; + for (auto it = mDisplayModes.begin(); it != mDisplayModes.end(); ++it) { + const auto& [id, mode] = *it; + + if (!filterModes(*mode)) { + continue; + } + const auto [start, end] = + divisorRange(mode->getFps(), renderRange, mConfig.enableFrameRateOverride); + for (auto divisor = start; divisor <= end; divisor++) { + const auto fps = mode->getFps() / divisor; + using fps_approx_ops::operator<; + if (fps < kMinSupportedFrameRate) { + break; + } + + if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Enabled && + !renderRange.includes(fps)) { + continue; + } + + if (mConfig.enableFrameRateOverride == + Config::FrameRateOverride::AppOverrideNativeRefreshRates && + !isNativeRefreshRate(fps)) { + continue; + } + + const auto [existingIter, emplaceHappened] = + ratesMap.try_emplace(Key{fps, mode->getGroup()}, it); + if (emplaceHappened) { + ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(), + to_string(mode->getFps()).c_str()); + } else { + // We might need to update the map as we found a lower refresh rate + if (isStrictlyLess(mode->getFps(), existingIter->second->second->getFps())) { + existingIter->second = it; + ALOGV("%s: changing %s (%s)", __func__, to_string(fps).c_str(), + to_string(mode->getFps()).c_str()); + } + } + } + } + + std::vector frameRateModes; + frameRateModes.reserve(ratesMap.size()); + for (const auto& [key, mode] : ratesMap) { + frameRateModes.emplace_back(FrameRateMode{key.fps, mode->second}); + } + + // We always want that the lowest frame rate will be corresponding to the + // lowest mode for power saving. + const auto lowestRefreshRateIt = + std::min_element(frameRateModes.begin(), frameRateModes.end(), + [](const FrameRateMode& lhs, const FrameRateMode& rhs) { + return isStrictlyLess(lhs.modePtr->getFps(), + rhs.modePtr->getFps()); + }); + frameRateModes.erase(frameRateModes.begin(), lowestRefreshRateIt); + + return frameRateModes; +} + struct RefreshRateSelector::RefreshRateScoreComparator { bool operator()(const RefreshRateScore& lhs, const RefreshRateScore& rhs) const { - const auto& [modeIt, overallScore, _] = lhs; + const auto& [frameRateMode, overallScore, _] = lhs; - std::string name = to_string(modeIt->second->getFps()); - ALOGV("%s sorting scores %.2f", name.c_str(), overallScore); + std::string name = to_string(frameRateMode); + ALOGV("%s sorting scores %.2f", name.c_str(), overallScore); ATRACE_INT(name.c_str(), static_cast(std::round(overallScore * 100))); - if (!ScoredRefreshRate::scoresEqual(overallScore, rhs.overallScore)) { + if (!ScoredFrameRate::scoresEqual(overallScore, rhs.overallScore)) { return overallScore > rhs.overallScore; } - // If overallScore tie we will pick the higher refresh rate if - // high refresh rate is the priority else the lower refresh rate. if (refreshRateOrder == RefreshRateOrder::Descending) { using fps_approx_ops::operator>; - return modeIt->second->getFps() > rhs.modeIt->second->getFps(); + return frameRateMode.fps > rhs.frameRateMode.fps; } else { using fps_approx_ops::operator<; - return modeIt->second->getFps() < rhs.modeIt->second->getFps(); + return frameRateMode.fps < rhs.frameRateMode.fps; } } @@ -210,7 +301,15 @@ float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const Layer if (layer.vote == LayerVoteType::ExplicitExactOrMultiple || layer.vote == LayerVoteType::Heuristic) { - if (isFractionalPairOrMultiple(refreshRate, layer.desiredRefreshRate)) { + const float multiplier = refreshRate.getValue() / layer.desiredRefreshRate.getValue(); + + // We only want to score this layer as a fractional pair if the content is not + // significantly faster than the display rate, at it would cause a significant frame drop. + // It is more appropriate to choose a higher display rate even if + // a pull-down will be required. + constexpr float kMinMultiplier = 0.25f; + if (multiplier >= kMinMultiplier && + isFractionalPairOrMultiple(refreshRate, layer.desiredRefreshRate)) { return kScoreForFractionalPairs; } @@ -245,9 +344,9 @@ float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const Layer return 0; } -float RefreshRateSelector::calculateRefreshRateScoreForFps(Fps refreshRate) const { - const float ratio = - refreshRate.getValue() / mAppRequestRefreshRates.back()->second->getFps().getValue(); +float RefreshRateSelector::calculateDistanceScoreFromMax(Fps refreshRate) const { + const auto& maxFps = mAppRequestFrameRates.back().fps; + const float ratio = refreshRate.getValue() / maxFps.getValue(); // Use ratio^2 to get a lower score the more we get further from peak return ratio * ratio; } @@ -260,12 +359,12 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { - return calculateRefreshRateScoreForFps(refreshRate); + return calculateDistanceScoreFromMax(refreshRate); } if (layer.vote == LayerVoteType::ExplicitExact) { const int divisor = getFrameRateDivisor(refreshRate, layer.desiredRefreshRate); - if (supportsFrameRateOverrideByContent()) { + if (supportsAppFrameRateOverrideByContent()) { // 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. @@ -289,33 +388,33 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay kNonExactMatchingPenalty; } -auto RefreshRateSelector::getRankedRefreshRates(const std::vector& layers, - GlobalSignals signals) const -> RankedRefreshRates { +auto RefreshRateSelector::getRankedFrameRates(const std::vector& layers, + GlobalSignals signals) const -> RankedFrameRates { std::lock_guard lock(mLock); - if (mGetRankedRefreshRatesCache && - mGetRankedRefreshRatesCache->arguments == std::make_pair(layers, signals)) { - return mGetRankedRefreshRatesCache->result; + if (mGetRankedFrameRatesCache && + mGetRankedFrameRatesCache->arguments == std::make_pair(layers, signals)) { + return mGetRankedFrameRatesCache->result; } - const auto result = getRankedRefreshRatesLocked(layers, signals); - mGetRankedRefreshRatesCache = GetRankedRefreshRatesCache{{layers, signals}, result}; + const auto result = getRankedFrameRatesLocked(layers, signals); + mGetRankedFrameRatesCache = GetRankedFrameRatesCache{{layers, signals}, result}; return result; } -auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector& layers, - GlobalSignals signals) const - -> RankedRefreshRates { +auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector& layers, + GlobalSignals signals) const + -> RankedFrameRates { using namespace fps_approx_ops; ATRACE_CALL(); ALOGV("%s: %zu layers", __func__, layers.size()); const auto& activeMode = *getActiveModeItLocked()->second; - // Keep the display at max refresh rate for the duration of powering on the display. + // Keep the display at max frame rate for the duration of powering on the display. if (signals.powerOnImminent) { ALOGV("Power On Imminent"); - return {rankRefreshRates(activeMode.getGroup(), RefreshRateOrder::Descending), + return {rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Descending), GlobalSignals{.powerOnImminent = true}}; } @@ -375,7 +474,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector scores; - scores.reserve(mAppRequestRefreshRates.size()); + scores.reserve(mAppRequestFrameRates.size()); - for (const DisplayModeIterator modeIt : mAppRequestRefreshRates) { - scores.emplace_back(RefreshRateScore{modeIt, 0.0f}); + for (const FrameRateMode& it : mAppRequestFrameRates) { + scores.emplace_back(RefreshRateScore{it, 0.0f}); } for (const auto& layer : layers) { @@ -420,13 +519,13 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorgetGroup() == activeMode.getGroup(); + for (auto& [mode, overallScore, fixedRateBelowThresholdLayersScore] : scores) { + const auto& [fps, modePtr] = mode; + const bool isSeamlessSwitch = modePtr->getGroup() == activeMode.getGroup(); if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) { ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s", - formatLayerInfo(layer, weight).c_str(), to_string(*mode).c_str(), + formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(), to_string(activeMode).c_str()); continue; } @@ -435,7 +534,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorgetGroup() == anchorGroup; + const bool isInPolicyForDefault = modePtr->getGroup() == anchorGroup; if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault) { ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(), - to_string(*mode).c_str(), to_string(activeMode).c_str()); + to_string(*modePtr).c_str(), to_string(activeMode).c_str()); continue; } - const bool inPrimaryRange = policy->primaryRanges.physical.includes(mode->getFps()); + const bool inPrimaryRange = policy->primaryRanges.physical.includes(modePtr->getFps()); if ((primaryRangeIsSingleRate || !inPrimaryRange) && !(layer.focused && (layer.vote == LayerVoteType::ExplicitDefault || @@ -462,8 +561,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorgetFps(), isSeamlessSwitch); + const float layerScore = calculateLayerScoreLocked(layer, fps, isSeamlessSwitch); const float weightedLayerScore = weight * layerScore; // Layer with fixed source has a special consideration which depends on the @@ -491,21 +589,21 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorgetFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); + modePtr->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); if (modeAboveThreshold) { - ALOGV("%s gives %s fixed source (above threshold) score of %.4f", - formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), - layerScore); + ALOGV("%s gives %s (%s) fixed source (above threshold) score of %.4f", + formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(), + to_string(modePtr->getFps()).c_str(), layerScore); fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore; } else { - ALOGV("%s gives %s fixed source (below threshold) score of %.4f", - formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), - layerScore); + ALOGV("%s gives %s (%s) fixed source (below threshold) score of %.4f", + formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(), + to_string(modePtr->getFps()).c_str(), layerScore); fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore; } } else { - ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(), - to_string(mode->getFps()).c_str(), layerScore); + ALOGV("%s gives %s (%s) score of %.4f", formatLayerInfo(layer, weight).c_str(), + to_string(fps).c_str(), to_string(modePtr->getFps()).c_str(), layerScore); overallScore += weightedLayerScore; } } @@ -524,25 +622,26 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector max.overallScore; + return current.overallScore > max.overallScore; }); - ALOGV("%s is the best refresh rate without fixed source layers. It is %s the threshold for " + ALOGV("%s (%s) is the best refresh rate without fixed source layers. It is %s the " + "threshold for " "refresh rate multiples", - to_string(maxScoreIt->modeIt->second->getFps()).c_str(), + to_string(maxScoreIt->frameRateMode.fps).c_str(), + to_string(maxScoreIt->frameRateMode.modePtr->getFps()).c_str(), maxScoreAboveThreshold ? "above" : "below"); - return maxScoreIt->modeIt->second->getFps() >= + return maxScoreIt->frameRateMode.modePtr->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); }(); // Now we can add the fixed rate layers score - for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { + for (auto& [frameRateMode, overallScore, fixedRateBelowThresholdLayersScore] : scores) { overallScore += fixedRateBelowThresholdLayersScore.modeBelowThreshold; if (maxScoreAboveThreshold) { overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold; } - ALOGV("%s adjusted overallScore is %.4f", to_string(modeIt->second->getFps()).c_str(), - overallScore); + ALOGV("%s (%s) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(), + to_string(frameRateMode.modePtr->getFps()).c_str(), overallScore); } // Now that we scored all the refresh rates we need to pick the one that got the highest @@ -552,12 +651,12 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorsecond, score.overallScore}; + return ScoredFrameRate{score.frameRateMode, score.overallScore}; }); const bool noLayerScore = std::all_of(scores.begin(), scores.end(), [](RefreshRateScore score) { @@ -569,7 +668,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vectorsecond->getFps() < touchRefreshRates.front().modePtr->getFps()) { + scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) { ALOGV("Touch Boost"); return {touchRefreshRates, GlobalSignals{.touch = true}}; } @@ -603,7 +701,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector UidToFrameRateOverride { ATRACE_CALL(); - ALOGV("%s: %zu layers", __func__, layers.size()); + if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Disabled) { + return {}; + } + ALOGV("%s: %zu layers", __func__, layers.size()); std::lock_guard lock(mLock); - // Prepare a set of supported display refresh rates for easy lookup - constexpr size_t kStaticCapacity = 8; - ftl::SmallMap supportedDisplayRefreshRates; - if (mConfig.enableFrameRateOverride == - Config::FrameRateOverride::EnabledForNativeRefreshRates) { - for (const auto& [_, modePtr] : mDisplayModes) { - supportedDisplayRefreshRates.try_emplace(modePtr->getFps(), ftl::unit); - } - } - const auto* policyPtr = getCurrentPolicyLocked(); // We don't want to run lower than 30fps const Fps minFrameRate = std::max(policyPtr->appRequestRanges.render.min, 30_Hz, isApproxLess); @@ -676,8 +767,8 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector 0; n--) { const Fps divisor = displayRefreshRate / n; if (mConfig.enableFrameRateOverride == - Config::FrameRateOverride::EnabledForNativeRefreshRates && - !supportedDisplayRefreshRates.contains(divisor)) { + Config::FrameRateOverride::AppOverrideNativeRefreshRates && + !isNativeRefreshRate(divisor)) { continue; } @@ -736,7 +827,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector RefreshRateSelector::onKernelTimerChanged( const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const { const auto& activeMode = *getActiveModeItLocked()->second; - for (const DisplayModeIterator modeIt : mPrimaryRefreshRates) { - const auto& mode = modeIt->second; - if (activeMode.getGroup() == mode->getGroup()) { - return mode; + for (const FrameRateMode& mode : mPrimaryFrameRates) { + if (activeMode.getGroup() == mode.modePtr->getGroup()) { + return mode.modePtr; } } @@ -776,55 +866,72 @@ const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() con to_string(activeMode).c_str()); // Default to the lowest refresh rate. - return mPrimaryRefreshRates.front()->second; + return mPrimaryFrameRates.front().modePtr; } const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int anchorGroup) const { - for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); ++it) { - const auto& mode = (*it)->second; - if (anchorGroup == mode->getGroup()) { - return mode; + const DisplayModePtr* maxByAnchor = &mPrimaryFrameRates.back().modePtr; + const DisplayModePtr* max = &mPrimaryFrameRates.back().modePtr; + + bool maxByAnchorFound = false; + for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) { + using namespace fps_approx_ops; + if (it->modePtr->getFps() > (*max)->getFps()) { + max = &it->modePtr; } + + if (anchorGroup == it->modePtr->getGroup() && + it->modePtr->getFps() >= (*maxByAnchor)->getFps()) { + maxByAnchorFound = true; + maxByAnchor = &it->modePtr; + } + } + + if (maxByAnchorFound) { + return *maxByAnchor; } ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup); // Default to the highest refresh rate. - return mPrimaryRefreshRates.back()->second; + return *max; } -auto RefreshRateSelector::rankRefreshRates( - std::optional anchorGroupOpt, RefreshRateOrder refreshRateOrder, - std::optional preferredDisplayModeOpt) const -> RefreshRateRanking { - std::deque ranking; - - const auto rankRefreshRate = [&](DisplayModeIterator it) REQUIRES(mLock) { - const auto& mode = it->second; - if (anchorGroupOpt && mode->getGroup() != anchorGroupOpt) { +auto RefreshRateSelector::rankFrameRates(std::optional anchorGroupOpt, + RefreshRateOrder refreshRateOrder, + std::optional preferredDisplayModeOpt) const + -> FrameRateRanking { + const char* const whence = __func__; + std::deque ranking; + const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) { + const auto& modePtr = frameRateMode.modePtr; + if (anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) { return; } - float score = calculateRefreshRateScoreForFps(mode->getFps()); + float score = calculateDistanceScoreFromMax(frameRateMode.fps); const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending); if (inverseScore) { score = 1.0f / score; } if (preferredDisplayModeOpt) { - if (*preferredDisplayModeOpt == mode->getId()) { + if (*preferredDisplayModeOpt == modePtr->getId()) { constexpr float kScore = std::numeric_limits::max(); - ranking.push_front(ScoredRefreshRate{mode, kScore}); + ranking.emplace_front(ScoredFrameRate{frameRateMode, kScore}); return; } constexpr float kNonPreferredModePenalty = 0.95f; score *= kNonPreferredModePenalty; } - ranking.push_back(ScoredRefreshRate{mode, score}); + ALOGV("%s(%s) %s (%s) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(), + to_string(frameRateMode.fps).c_str(), to_string(modePtr->getFps()).c_str(), score); + ranking.emplace_back(ScoredFrameRate{frameRateMode, score}); }; if (refreshRateOrder == RefreshRateOrder::Ascending) { - std::for_each(mPrimaryRefreshRates.begin(), mPrimaryRefreshRates.end(), rankRefreshRate); + std::for_each(mPrimaryFrameRates.begin(), mPrimaryFrameRates.end(), rankFrameRate); } else { - std::for_each(mPrimaryRefreshRates.rbegin(), mPrimaryRefreshRates.rend(), rankRefreshRate); + std::for_each(mPrimaryFrameRates.rbegin(), mPrimaryFrameRates.rend(), rankFrameRate); } if (!ranking.empty() || !anchorGroupOpt) { @@ -836,7 +943,7 @@ auto RefreshRateSelector::rankRefreshRates( refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value()); constexpr std::optional kNoAnchorGroup = std::nullopt; - return rankRefreshRates(kNoAnchorGroup, refreshRateOrder, preferredDisplayModeOpt); + return rankFrameRates(kNoAnchorGroup, refreshRateOrder, preferredDisplayModeOpt); } DisplayModePtr RefreshRateSelector::getActiveModePtr() const { @@ -858,9 +965,9 @@ DisplayModeIterator RefreshRateSelector::getActiveModeItLocked() const { void RefreshRateSelector::setActiveModeId(DisplayModeId modeId) { std::lock_guard lock(mLock); - // Invalidate the cached invocation to getRankedRefreshRates. This forces - // the refresh rate to be recomputed on the next call to getRankedRefreshRates. - mGetRankedRefreshRatesCache.reset(); + // Invalidate the cached invocation to getRankedFrameRates. This forces + // the refresh rate to be recomputed on the next call to getRankedFrameRates. + mGetRankedFrameRatesCache.reset(); mActiveModeIt = mDisplayModes.find(modeId); LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end()); @@ -895,16 +1002,15 @@ void RefreshRateSelector::initializeIdleTimer() { void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) { std::lock_guard lock(mLock); - // Invalidate the cached invocation to getRankedRefreshRates. This forces - // the refresh rate to be recomputed on the next call to getRankedRefreshRates. - mGetRankedRefreshRatesCache.reset(); + // Invalidate the cached invocation to getRankedFrameRates. This forces + // the refresh rate to be recomputed on the next call to getRankedFrameRates. + mGetRankedFrameRatesCache.reset(); mDisplayModes = std::move(modes); mActiveModeIt = mDisplayModes.find(activeModeId); LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end()); - const auto sortedModes = - sortByRefreshRate(mDisplayModes, [](const DisplayMode&) { return true; }); + const auto sortedModes = sortByRefreshRate(mDisplayModes); mMinRefreshRateModeIt = sortedModes.front(); mMaxRefreshRateModeIt = sortedModes.back(); @@ -915,15 +1021,23 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a mFrameRateOverrideConfig = [&] { switch (mConfig.enableFrameRateOverride) { case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverride: case Config::FrameRateOverride::Enabled: return mConfig.enableFrameRateOverride; - case Config::FrameRateOverride::EnabledForNativeRefreshRates: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: return shouldEnableFrameRateOverride(sortedModes) - ? Config::FrameRateOverride::EnabledForNativeRefreshRates + ? Config::FrameRateOverride::AppOverrideNativeRefreshRates : Config::FrameRateOverride::Disabled; } }(); + if (mConfig.enableFrameRateOverride == + Config::FrameRateOverride::AppOverrideNativeRefreshRates) { + for (const auto& [_, mode] : mDisplayModes) { + mAppOverrideNativeRefreshRates.try_emplace(mode->getFps(), ftl::unit); + } + } + constructAvailableRefreshRates(); } @@ -939,9 +1053,13 @@ bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const { return false; } - using namespace fps_approx_ops; - return policy.appRequestRanges.physical.min <= policy.primaryRanges.physical.min && - policy.appRequestRanges.physical.max >= policy.primaryRanges.physical.max; + const auto& primaryRanges = policy.primaryRanges; + const auto& appRequestRanges = policy.appRequestRanges; + ALOGE_IF(!appRequestRanges.physical.includes(primaryRanges.physical), + "Physical range is invalid"); + ALOGE_IF(!appRequestRanges.render.includes(primaryRanges.render), "Render range is invalid"); + + return primaryRanges.valid() && appRequestRanges.valid(); } auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyResult { @@ -979,7 +1097,7 @@ auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyRes return SetPolicyResult::Invalid; } - mGetRankedRefreshRatesCache.reset(); + mGetRankedFrameRatesCache.reset(); if (*getCurrentPolicyLocked() == oldPolicy) { return SetPolicyResult::Unchanged; @@ -1016,9 +1134,9 @@ auto RefreshRateSelector::getDisplayManagerPolicy() const -> Policy { bool RefreshRateSelector::isModeAllowed(DisplayModeId modeId) const { std::lock_guard lock(mLock); - return std::any_of(mAppRequestRefreshRates.begin(), mAppRequestRefreshRates.end(), - [modeId](DisplayModeIterator modeIt) { - return modeIt->second->getId() == modeId; + return std::any_of(mAppRequestFrameRates.begin(), mAppRequestFrameRates.end(), + [modeId](const FrameRateMode& frameRateMode) { + return frameRateMode.modePtr->getId() == modeId; }); } @@ -1029,33 +1147,35 @@ void RefreshRateSelector::constructAvailableRefreshRates() { const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get(); - const auto filterRefreshRates = [&](FpsRange range, const char* rangeName) REQUIRES(mLock) { - const auto filter = [&](const DisplayMode& mode) { + const auto filterRefreshRates = [&](const FpsRanges& ranges, + const char* rangeName) REQUIRES(mLock) { + const auto filterModes = [&](const DisplayMode& mode) { return mode.getResolution() == defaultMode->getResolution() && mode.getDpi() == defaultMode->getDpi() && (policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) && - range.includes(mode.getFps()); + ranges.physical.includes(mode.getFps()) && + (supportsFrameRateOverride() || ranges.render.includes(mode.getFps())); }; - const auto modes = sortByRefreshRate(mDisplayModes, filter); - LOG_ALWAYS_FATAL_IF(modes.empty(), "No matching modes for %s range %s", rangeName, - to_string(range).c_str()); + const auto frameRateModes = createFrameRateModes(filterModes, ranges.render); + LOG_ALWAYS_FATAL_IF(frameRateModes.empty(), + "No matching frame rate modes for %s physicalRange %s", rangeName, + to_string(ranges.physical).c_str()); const auto stringifyModes = [&] { std::string str; - for (const auto modeIt : modes) { - str += to_string(modeIt->second->getFps()); - str.push_back(' '); + for (const auto& frameRateMode : frameRateModes) { + str += to_string(frameRateMode) + " "; } return str; }; - ALOGV("%s refresh rates: %s", rangeName, stringifyModes().c_str()); + ALOGV("%s render rates: %s", rangeName, stringifyModes().c_str()); - return modes; + return frameRateModes; }; - mPrimaryRefreshRates = filterRefreshRates(policy->primaryRanges.physical, "primary"); - mAppRequestRefreshRates = filterRefreshRates(policy->appRequestRanges.physical, "app request"); + mPrimaryFrameRates = filterRefreshRates(policy->primaryRanges, "primary"); + mAppRequestFrameRates = filterRefreshRates(policy->appRequestRanges, "app request"); } Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const { diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 65ee487112..89ebeeaff7 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -24,9 +24,11 @@ #include #include +#include #include #include +#include #include #include "DisplayHardware/DisplayMode.h" @@ -58,6 +60,9 @@ public: static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION = std::chrono::nanoseconds(800us).count(); + // The lowest Render Frame Rate that will ever be selected + static constexpr Fps kMinSupportedFrameRate = 20_Hz; + class Policy { static constexpr int kAllowGroupSwitchingDefault = false; @@ -196,12 +201,12 @@ public: } }; - struct ScoredRefreshRate { - DisplayModePtr modePtr; + struct ScoredFrameRate { + FrameRateMode frameRateMode; float score = 0.0f; - bool operator==(const ScoredRefreshRate& other) const { - return modePtr == other.modePtr && score == other.score; + bool operator==(const ScoredFrameRate& other) const { + return frameRateMode == other.frameRateMode && score == other.score; } static bool scoresEqual(float lhs, float rhs) { @@ -210,25 +215,25 @@ public: } struct DescendingScore { - bool operator()(const ScoredRefreshRate& lhs, const ScoredRefreshRate& rhs) const { + bool operator()(const ScoredFrameRate& lhs, const ScoredFrameRate& rhs) const { return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score); } }; }; - using RefreshRateRanking = std::vector; + using FrameRateRanking = std::vector; - struct RankedRefreshRates { - RefreshRateRanking ranking; // Ordered by descending score. + struct RankedFrameRates { + FrameRateRanking ranking; // Ordered by descending score. GlobalSignals consideredSignals; - bool operator==(const RankedRefreshRates& other) const { + bool operator==(const RankedFrameRates& other) const { return ranking == other.ranking && consideredSignals == other.consideredSignals; } }; - RankedRefreshRates getRankedRefreshRates(const std::vector&, - GlobalSignals) const EXCLUDES(mLock); + RankedFrameRates getRankedFrameRates(const std::vector&, GlobalSignals) const + EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); @@ -257,9 +262,12 @@ public: // Override the frame rate for an app to a value which is also // a display refresh rate - EnabledForNativeRefreshRates, + AppOverrideNativeRefreshRates, // Override the frame rate for an app to any value + AppOverride, + + // Override the frame rate for all apps and all values. Enabled, ftl_last = Enabled @@ -291,10 +299,13 @@ public: // Returns whether switching modes (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only - // differ in resolution. + // differ in resolution. Once Config::FrameRateOverride::Enabled becomes the default, + // we can probably remove canSwitch altogether since all devices will be able + // to switch to a frame rate divisor. bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); - return mDisplayModes.size() > 1; + return mDisplayModes.size() > 1 || + mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; } // Class to enumerate options around toggling the kernel timer on and off. @@ -307,10 +318,14 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; - bool supportsFrameRateOverrideByContent() const { + bool supportsAppFrameRateOverrideByContent() const { return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled; } + bool supportsFrameRateOverride() const { + return mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled; + } + // Return the display refresh rate divisor to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the // layer refresh rate. @@ -387,8 +402,8 @@ private: // See mActiveModeIt for thread safety. DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock); - RankedRefreshRates getRankedRefreshRatesLocked(const std::vector&, - GlobalSignals) const REQUIRES(mLock); + RankedFrameRates getRankedFrameRatesLocked(const std::vector& layers, + GlobalSignals signals) const REQUIRES(mLock); // Returns number of display frames and remainder when dividing the layer refresh period by // display refresh period. @@ -404,18 +419,24 @@ private: struct RefreshRateScoreComparator; - enum class RefreshRateOrder { Ascending, Descending }; + enum class RefreshRateOrder { + Ascending, + Descending, + + ftl_last = Descending + }; // Only uses the primary range, not the app request range. - RefreshRateRanking rankRefreshRates(std::optional anchorGroupOpt, RefreshRateOrder, - std::optional preferredDisplayModeOpt = - std::nullopt) const REQUIRES(mLock); + FrameRateRanking rankFrameRates( + std::optional anchorGroupOpt, RefreshRateOrder refreshRateOrder, + std::optional preferredDisplayModeOpt = std::nullopt) const + REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1. - float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock); + float calculateDistanceScoreFromMax(Fps refreshRate) const REQUIRES(mLock); // calculates a score for a layer. Used to determine the display refresh rate // and the frame rate override for certains applications. float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate, @@ -436,11 +457,27 @@ private: : mIdleTimerCallbacks->platform; } + bool isNativeRefreshRate(Fps fps) const REQUIRES(mLock) { + LOG_ALWAYS_FATAL_IF(mConfig.enableFrameRateOverride != + Config::FrameRateOverride::AppOverrideNativeRefreshRates, + "should only be called when " + "Config::FrameRateOverride::AppOverrideNativeRefreshRates is used"); + return mAppOverrideNativeRefreshRates.contains(fps); + } + + std::vector createFrameRateModes( + std::function&& filterModes, const FpsRange&) const + REQUIRES(mLock); + // The display modes of the active display. The DisplayModeIterators below are pointers into // this container, so must be invalidated whenever the DisplayModes change. The Policy below // is also dependent, so must be reset as well. DisplayModes mDisplayModes GUARDED_BY(mLock); + // Set of supported display refresh rates for easy lookup + // when FrameRateOverride::AppOverrideNativeRefreshRates is in use. + ftl::SmallMap mAppOverrideNativeRefreshRates; + // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext // need not be under mLock. DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext); @@ -449,8 +486,8 @@ private: DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock); // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate. - std::vector mPrimaryRefreshRates GUARDED_BY(mLock); - std::vector mAppRequestRefreshRates GUARDED_BY(mLock); + std::vector mPrimaryFrameRates GUARDED_BY(mLock); + std::vector mAppRequestFrameRates GUARDED_BY(mLock); Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional mOverridePolicy GUARDED_BY(mLock); @@ -466,11 +503,11 @@ private: const Config mConfig; Config::FrameRateOverride mFrameRateOverrideConfig; - struct GetRankedRefreshRatesCache { + struct GetRankedFrameRatesCache { std::pair, GlobalSignals> arguments; - RankedRefreshRates result; + RankedFrameRates result; }; - mutable std::optional mGetRankedRefreshRatesCache GUARDED_BY(mLock); + mutable std::optional mGetRankedFrameRatesCache GUARDED_BY(mLock); // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed. std::mutex mIdleTimerCallbacksMutex; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index f1fcc884e5..0c541f9a5a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -152,7 +152,7 @@ std::unique_ptr Scheduler::makePrimaryDispSyncSource( std::optional Scheduler::getFrameRateOverride(uid_t uid) const { const bool supportsFrameRateOverrideByContent = - leaderSelectorPtr()->supportsFrameRateOverrideByContent(); + leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); return mFrameRateOverrideMappings .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent); } @@ -268,7 +268,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) { const bool supportsFrameRateOverrideByContent = - leaderSelectorPtr()->supportsFrameRateOverrideByContent(); + leaderSelectorPtr()->supportsAppFrameRateOverrideByContent(); std::vector overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent); @@ -707,7 +707,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { ATRACE_CALL(); - using RankedRefreshRates = RefreshRateSelector::RankedRefreshRates; + using RankedRefreshRates = RefreshRateSelector::RankedFrameRates; display::PhysicalDisplayVector perDisplayRanking; // Tallies the score of a refresh rate across `displayCount` displays. @@ -726,9 +726,10 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (const auto& [id, selectorPtr] : mRefreshRateSelectors) { auto rankedRefreshRates = - selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals); + selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals); - for (const auto& [modePtr, score] : rankedRefreshRates.ranking) { + for (const auto& [frameRateMode, score] : rankedRefreshRates.ranking) { + const auto& modePtr = frameRateMode.modePtr; const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score); if (!inserted) { @@ -771,16 +772,18 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { for (auto& [ranking, signals] : perDisplayRanking) { if (!chosenFps) { - auto& [modePtr, _] = ranking.front(); + const auto& [frameRateMode, _] = ranking.front(); + const auto& modePtr = frameRateMode.modePtr; modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), - DisplayModeChoice{std::move(modePtr), signals}); + DisplayModeChoice{modePtr, signals}); continue; } - for (auto& [modePtr, _] : ranking) { + for (auto& [frameRateMode, _] : ranking) { + const auto& modePtr = frameRateMode.modePtr; if (modePtr->getFps() == *chosenFps) { modeChoices.try_emplace(modePtr->getPhysicalDisplayId(), - DisplayModeChoice{std::move(modePtr), signals}); + DisplayModeChoice{modePtr, signals}); break; } } @@ -804,10 +807,10 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() { if (mPolicy.mode) { const auto ranking = leaderSelectorPtr() - ->getRankedRefreshRates(mPolicy.contentRequirements, makeGlobalSignals()) + ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals()) .ranking; - mPolicy.mode = ranking.front().modePtr; + mPolicy.mode = ranking.front().frameRateMode.modePtr; } return mPolicy.mode; } diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h index 31b1d6901c..5522ff80c8 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h @@ -66,6 +66,7 @@ struct FpsRange { Fps max = Fps::fromValue(std::numeric_limits::max()); bool includes(Fps) const; + bool includes(FpsRange) const; }; struct FpsRanges { @@ -75,6 +76,8 @@ struct FpsRanges { // the range of frame rates that refers to the render rate, which is // the rate that frames are swapped. FpsRange render; + + bool valid() const; }; static_assert(std::is_trivially_copyable_v); @@ -159,6 +162,16 @@ inline bool FpsRange::includes(Fps fps) const { return min <= fps && fps <= max; } +inline bool FpsRange::includes(FpsRange range) const { + using namespace fps_approx_ops; + return min <= range.min && max >= range.max; +} + +inline bool FpsRanges::valid() const { + using fps_approx_ops::operator>=; + return physical.max >= render.max; +} + struct FpsApproxEqual { bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); } }; diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h new file mode 100644 index 0000000000..670ab4583a --- /dev/null +++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h @@ -0,0 +1,44 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +// TODO(b/241285191): Pull this to +#include "DisplayHardware/DisplayMode.h" + +namespace android::scheduler { + +struct FrameRateMode { + Fps fps; // The render frame rate, which is a divisor of modePtr->getFps(). + DisplayModePtr modePtr; + + bool operator==(const FrameRateMode& other) const { + return isApproxEqual(fps, other.fps) && modePtr == other.modePtr; + } + + bool operator!=(const FrameRateMode& other) const { return !(*this == other); } +}; + +inline std::string to_string(const FrameRateMode& mode) { + if (mode.modePtr) { + return to_string(mode.fps) + " (" + to_string(mode.modePtr->getFps()) + ")"; + } + return "{invalid}"; +} + +} // namespace android::scheduler \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dc9129ce78..a723a7d6cd 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2793,7 +2793,11 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( } if (sysprop::frame_rate_override_for_native_rates(true)) { - return Config::FrameRateOverride::EnabledForNativeRefreshRates; + return Config::FrameRateOverride::AppOverrideNativeRefreshRates; + } + + if (!base::GetBoolProperty("debug.sf.frame_rate_override_global"s, false)) { + return Config::FrameRateOverride::AppOverride; } return Config::FrameRateOverride::Enabled; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp index bd11a37a06..950e6d36bf 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp @@ -353,7 +353,7 @@ void SchedulerFuzzer::fuzzRefreshRateSelector() { const RefreshRateSelector::GlobalSignals globalSignals = {.touch = false, .idle = false}; std::vector layers = {{.weight = mFdp.ConsumeFloatingPoint()}}; - refreshRateSelector.getRankedRefreshRates(layers, globalSignals); + refreshRateSelector.getRankedFrameRates(layers, globalSignals); layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength); layers[0].ownerUid = mFdp.ConsumeIntegral(); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index cedb7eb6ee..8757e63c91 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -26,6 +26,7 @@ #include #include +#include #include "DisplayHardware/HWC2.h" #include "FpsOps.h" #include "Scheduler/RefreshRateSelector.h" @@ -44,9 +45,13 @@ using SetPolicyResult = RefreshRateSelector::SetPolicyResult; using mock::createDisplayMode; +// Use a C style macro to keep the line numbers printed in gtest +#define EXPECT_SCORED_FRAME_RATE(modePtr, fps, scored) \ + EXPECT_EQ((FrameRateMode{(fps), (modePtr)}), (scored).frameRateMode) + struct TestableRefreshRateSelector : RefreshRateSelector { + using RefreshRateSelector::FrameRateRanking; using RefreshRateSelector::RefreshRateOrder; - using RefreshRateSelector::RefreshRateRanking; using RefreshRateSelector::RefreshRateSelector; @@ -80,36 +85,41 @@ struct TestableRefreshRateSelector : RefreshRateSelector { return getMaxRefreshRateByPolicyLocked(getActiveModeItLocked()->second->getGroup()); } - RefreshRateRanking rankRefreshRates(std::optional anchorGroupOpt, - RefreshRateOrder refreshRateOrder) const { + FrameRateRanking rankRefreshRates(std::optional anchorGroupOpt, + RefreshRateOrder refreshRateOrder) const { std::lock_guard lock(mLock); - return RefreshRateSelector::rankRefreshRates(anchorGroupOpt, refreshRateOrder); + return RefreshRateSelector::rankFrameRates(anchorGroupOpt, refreshRateOrder); } const std::vector& knownFrameRates() const { return mKnownFrameRates; } - using RefreshRateSelector::GetRankedRefreshRatesCache; - auto& mutableGetRankedRefreshRatesCache() { return mGetRankedRefreshRatesCache; } + using RefreshRateSelector::GetRankedFrameRatesCache; + auto& mutableGetRankedRefreshRatesCache() { return mGetRankedFrameRatesCache; } - auto getRankedRefreshRates(const std::vector& layers, - GlobalSignals signals) const { - const auto result = RefreshRateSelector::getRankedRefreshRates(layers, signals); + auto getRankedFrameRates(const std::vector& layers, + GlobalSignals signals) const { + const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals); EXPECT_TRUE(std::is_sorted(result.ranking.begin(), result.ranking.end(), - ScoredRefreshRate::DescendingScore{})); + ScoredFrameRate::DescendingScore{})); return result; } auto getRankedRefreshRatesAsPair(const std::vector& layers, GlobalSignals signals) const { - const auto [ranking, consideredSignals] = getRankedRefreshRates(layers, signals); + const auto [ranking, consideredSignals] = getRankedFrameRates(layers, signals); return std::make_pair(ranking, consideredSignals); } - DisplayModePtr getBestRefreshRate(const std::vector& layers = {}, - GlobalSignals signals = {}) const { - return getRankedRefreshRates(layers, signals).ranking.front().modePtr; + DisplayModePtr getBestFrameRateMode(const std::vector& layers = {}, + GlobalSignals signals = {}) const { + return getRankedFrameRates(layers, signals).ranking.front().frameRateMode.modePtr; + } + + ScoredFrameRate getBestScoredFrameRate(const std::vector& layers = {}, + GlobalSignals signals = {}) const { + return getRankedFrameRates(layers, signals).ranking.front(); } SetPolicyResult setPolicy(const PolicyVariant& policy) { @@ -120,9 +130,11 @@ struct TestableRefreshRateSelector : RefreshRateSelector { SetPolicyResult setDisplayManagerPolicy(const DisplayManagerPolicy& policy) { return setPolicy(policy); } + + const auto& getPrimaryFrameRates() const { return mPrimaryFrameRates; } }; -class RefreshRateSelectorTest : public testing::Test { +class RefreshRateSelectorTest : public testing::TestWithParam { protected: using RefreshRateOrder = TestableRefreshRateSelector::RefreshRateOrder; @@ -140,6 +152,7 @@ protected: static constexpr DisplayModeId kModeId24Frac{8}; static constexpr DisplayModeId kModeId30Frac{9}; static constexpr DisplayModeId kModeId60Frac{10}; + static constexpr DisplayModeId kModeId35{11}; static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz); static inline const DisplayModePtr kMode60Frac = createDisplayMode(kModeId60Frac, 59.94_Hz); @@ -156,12 +169,14 @@ protected: static inline const DisplayModePtr kMode30Frac = createDisplayMode(kModeId30Frac, 29.97_Hz); static inline const DisplayModePtr kMode25 = createDisplayMode(kModeId25, 25_Hz); static inline const DisplayModePtr kMode25_G1 = createDisplayMode(kModeId25, 25_Hz, 1); + static inline const DisplayModePtr kMode35 = createDisplayMode(kModeId35, 35_Hz); static inline const DisplayModePtr kMode50 = createDisplayMode(kModeId50, 50_Hz); static inline const DisplayModePtr kMode24 = createDisplayMode(kModeId24, 24_Hz); static inline const DisplayModePtr kMode24Frac = createDisplayMode(kModeId24Frac, 23.976_Hz); // Test configurations. static inline const DisplayModes kModes_60 = makeModes(kMode60); + static inline const DisplayModes kModes_35_60_90 = makeModes(kMode35, kMode60, kMode90); static inline const DisplayModes kModes_60_90 = makeModes(kMode60, kMode90); static inline const DisplayModes kModes_60_90_G1 = makeModes(kMode60, kMode90_G1); static inline const DisplayModes kModes_60_90_4K = makeModes(kMode60, kMode90_4K); @@ -185,6 +200,13 @@ protected: static inline const DisplayModes kModes_24_25_30_50_60_Frac = makeModes(kMode24, kMode24Frac, kMode25, kMode30, kMode30Frac, kMode50, kMode60, kMode60Frac); + + static TestableRefreshRateSelector createSelector(DisplayModes modes, + DisplayModeId activeModeId, + Config config = {}) { + config.enableFrameRateOverride = GetParam(); + return TestableRefreshRateSelector(modes, activeModeId, config); + } }; RefreshRateSelectorTest::RefreshRateSelectorTest() { @@ -201,13 +223,23 @@ RefreshRateSelectorTest::~RefreshRateSelectorTest() { namespace { -TEST_F(RefreshRateSelectorTest, oneMode_canSwitch) { - RefreshRateSelector selector(kModes_60, kModeId60); - EXPECT_FALSE(selector.canSwitch()); +INSTANTIATE_TEST_SUITE_P(PerOverrideConfig, RefreshRateSelectorTest, + testing::Values(Config::FrameRateOverride::Disabled, + Config::FrameRateOverride::AppOverrideNativeRefreshRates, + Config::FrameRateOverride::AppOverride, + Config::FrameRateOverride::Enabled)); + +TEST_P(RefreshRateSelectorTest, oneMode_canSwitch) { + auto selector = createSelector(kModes_60, kModeId60); + if (GetParam() == Config::FrameRateOverride::Enabled) { + EXPECT_TRUE(selector.canSwitch()); + } else { + EXPECT_FALSE(selector.canSwitch()); + } } -TEST_F(RefreshRateSelectorTest, invalidPolicy) { - TestableRefreshRateSelector selector(kModes_60, kModeId60); +TEST_P(RefreshRateSelectorTest, invalidPolicy) { + auto selector = createSelector(kModes_60, kModeId60); EXPECT_EQ(SetPolicyResult::Invalid, selector.setDisplayManagerPolicy({DisplayModeId(10), {60_Hz, 60_Hz}})); @@ -215,8 +247,8 @@ TEST_F(RefreshRateSelectorTest, invalidPolicy) { selector.setDisplayManagerPolicy({kModeId60, {20_Hz, 40_Hz}})); } -TEST_F(RefreshRateSelectorTest, unchangedPolicy) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, unchangedPolicy) { + auto selector = createSelector(kModes_60_90, kModeId60); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {60_Hz, 90_Hz}})); @@ -236,8 +268,8 @@ TEST_F(RefreshRateSelectorTest, unchangedPolicy) { selector.setDisplayManagerPolicy({kModeId90, {30_Hz, 90_Hz}})); } -TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap) { + auto selector = createSelector(kModes_60_90, kModeId60); const auto minRate = selector.getMinSupportedRefreshRate(); const auto performanceRate = selector.getMaxSupportedRefreshRate(); @@ -252,8 +284,8 @@ TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap) { EXPECT_EQ(performanceRateByPolicy, performanceRate); } -TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentGroups) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentGroups) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); const auto minRate = selector.getMinRefreshRateByPolicy(); const auto performanceRate = selector.getMaxSupportedRefreshRate(); @@ -276,8 +308,8 @@ TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentGroup EXPECT_EQ(kMode90_G1, performanceRate90); } -TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentResolutions) { - TestableRefreshRateSelector selector(kModes_60_90_4K, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentResolutions) { + auto selector = createSelector(kModes_60_90_4K, kModeId60); const auto minRate = selector.getMinRefreshRateByPolicy(); const auto performanceRate = selector.getMaxSupportedRefreshRate(); @@ -300,8 +332,8 @@ TEST_F(RefreshRateSelectorTest, twoModes_storesFullRefreshRateMap_differentResol EXPECT_EQ(kMode90_4K, performanceRate90); } -TEST_F(RefreshRateSelectorTest, twoModes_policyChange) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_policyChange) { + auto selector = createSelector(kModes_60_90, kModeId60); const auto minRate = selector.getMinRefreshRateByPolicy(); const auto performanceRate = selector.getMaxRefreshRateByPolicy(); @@ -319,8 +351,8 @@ TEST_F(RefreshRateSelectorTest, twoModes_policyChange) { EXPECT_EQ(kMode60, performanceRate60); } -TEST_F(RefreshRateSelectorTest, twoModes_getActiveMode) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_getActiveMode) { + auto selector = createSelector(kModes_60_90, kModeId60); { const auto& mode = selector.getActiveMode(); EXPECT_EQ(mode.getId(), kModeId60); @@ -340,31 +372,31 @@ TEST_F(RefreshRateSelectorTest, twoModes_getActiveMode) { } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_noLayers) { +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_noLayers) { { - TestableRefreshRateSelector selector(kModes_60_72_90, kModeId72); + auto selector = createSelector(kModes_60_72_90, kModeId72); // If there are no layers we select the default frame rate, which is the max of the primary // range. - EXPECT_EQ(kMode90, selector.getBestRefreshRate()); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode()); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}})); - EXPECT_EQ(kMode60, selector.getBestRefreshRate()); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode()); } { // We select max even when this will cause a non-seamless switch. - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); + auto selector = createSelector(kModes_60_90_G1, kModeId60); constexpr bool kAllowGroupSwitching = true; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy( {kModeId90, {0_Hz, 90_Hz}, kAllowGroupSwitching})); - EXPECT_EQ(kMode90_G1, selector.getBestRefreshRate()); + EXPECT_EQ(kMode90_G1, selector.getBestFrameRateMode()); } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_exactDontChangeRefreshRateWhenNotInPolicy) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId72); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_exactDontChangeRefreshRateWhenNotInPolicy) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId72); std::vector layers = {{.weight = 1.f}}; layers[0].vote = LayerVoteType::ExplicitExact; @@ -372,188 +404,187 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_exactDontChangeRefreshRateWhe EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId72, {0_Hz, 90_Hz}})); - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_60_90) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_90) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.name = ""; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 120_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_multipleThreshold_60_90) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60, - {.frameRateMultipleThreshold = 90}); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multipleThreshold_60_90) { + auto selector = createSelector(kModes_60_90, kModeId60, {.frameRateMultipleThreshold = 90}); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_60_72_90) { - TestableRefreshRateSelector selector(kModes_60_72_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_72_90) { + auto selector = createSelector(kModes_60_72_90, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_72_90_120) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90_120) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -563,23 +594,23 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_72_90_120) { lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -591,7 +622,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -599,7 +630,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -607,7 +638,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -615,7 +646,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -623,7 +654,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -631,7 +662,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; @@ -639,7 +670,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -647,7 +678,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -655,12 +686,13 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes) lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_multipleThreshold) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60, - {.frameRateMultipleThreshold = 120}); +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_30_60_90_120_DifferentTypes_multipleThreshold) { + auto selector = + createSelector(kModes_30_60_72_90_120, kModeId60, {.frameRateMultipleThreshold = 120}); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -673,7 +705,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -681,7 +713,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -689,7 +721,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -697,7 +729,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -705,7 +737,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -713,7 +745,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; @@ -721,7 +753,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -729,7 +761,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -737,14 +769,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -752,7 +784,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "120Hz ExplicitDefault"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -760,7 +792,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::ExplicitExact; lr2.name = "120Hz ExplicitExact"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 10_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -768,7 +800,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "120Hz ExplicitExact"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); lr1.desiredRefreshRate = 30_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -779,86 +811,86 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_90_120_DifferentTypes_m lr3.vote = LayerVoteType::Heuristic; lr3.desiredRefreshRate = 120_Hz; lr3.name = "120Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60) { - TestableRefreshRateSelector selector(kModes_30_60, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60) { + auto selector = createSelector(kModes_30_60, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_30_60_72_90) { - TestableRefreshRateSelector selector(kModes_30_60_72_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90) { + auto selector = createSelector(kModes_30_60_72_90, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr.desiredRefreshRate = 24_Hz; lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_PriorityTest) { - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_PriorityTest) { + auto selector = createSelector(kModes_30_60_90, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -866,43 +898,43 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 15_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 30_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_24FpsVideo) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -910,15 +942,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_24FpsVideo) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestRefreshRate(layers); + const auto mode = selector.getBestFrameRateMode(layers); EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getFps()); } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_24FpsVideo_multipleThreshold_60_120) { - TestableRefreshRateSelector selector(kModes_60_120, kModeId60, - {.frameRateMultipleThreshold = 120}); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo_multipleThreshold_60_120) { + auto selector = createSelector(kModes_60_120, kModeId60, {.frameRateMultipleThreshold = 120}); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -926,14 +957,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_24FpsVideo_multipleThreshold_ lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestRefreshRate(layers); + const auto mode = selector.getBestFrameRateMode(layers); EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getFps()); } } -TEST_F(RefreshRateSelectorTest, twoModes_getBestRefreshRate_Explicit) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, twoModes_getBestFrameRateMode_Explicit) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -943,23 +974,23 @@ TEST_F(RefreshRateSelectorTest, twoModes_getBestRefreshRate_Explicit) { lr1.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitDefault; lr1.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_75HzContent) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_75HzContent) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -967,14 +998,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_75HzContent) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestRefreshRate(layers, {}); + const auto mode = selector.getBestFrameRateMode(layers, {}); EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getFps()); } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_Multiples) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_Multiples) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -986,7 +1017,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; @@ -994,14 +1025,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_Multiples) { lr2.vote = LayerVoteType::ExplicitDefault; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30_Hz; @@ -1009,18 +1040,18 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30_Hz; lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; @@ -1031,28 +1062,28 @@ TEST_F(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); // The other layer starts to provide buffers lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1061,49 +1092,70 @@ TEST_F(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) { +TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) { // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the // different group. - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId60); - + auto selector = createSelector(kModes_30_60_90, kModeId60); const auto refreshRates = selector.rankRefreshRates(selector.getActiveMode().getGroup(), RefreshRateOrder::Descending); - const std::array expectedRefreshRates = {kMode90, kMode60, kMode30}; + const auto expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {30_Hz, kMode30}}; + case Config::FrameRateOverride::Enabled: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {45_Hz, kMode90}, {30_Hz, kMode30}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, getMinRefreshRatesByPolicy) { +TEST_P(RefreshRateSelectorTest, getMinRefreshRatesByPolicy) { // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the // different group. - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId60); + auto selector = createSelector(kModes_30_60_90, kModeId60); const auto refreshRates = selector.rankRefreshRates(selector.getActiveMode().getGroup(), RefreshRateOrder::Ascending); - const std::array expectedRefreshRates = {kMode30, kMode60, kMode90}; + const auto expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}}; + case Config::FrameRateOverride::Enabled: + return {{30_Hz, kMode30}, {45_Hz, kMode90}, {60_Hz, kMode60}, {90_Hz, kMode90}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, getMinRefreshRatesByPolicyOutsideTheGroup) { +TEST_P(RefreshRateSelectorTest, getMinRefreshRatesByPolicyOutsideTheGroup) { // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the // different group. - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId72); + auto selector = createSelector(kModes_30_60_90, kModeId72); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}})); @@ -1111,20 +1163,31 @@ TEST_F(RefreshRateSelectorTest, getMinRefreshRatesByPolicyOutsideTheGroup) { const auto refreshRates = selector.rankRefreshRates(/*anchorGroupOpt*/ std::nullopt, RefreshRateOrder::Ascending); - const std::array expectedRefreshRates = {kMode30, kMode60, kMode90}; + const auto expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}}; + case Config::FrameRateOverride::Enabled: + return {{30_Hz, kMode30}, {45_Hz, kMode90}, {60_Hz, kMode60}, {90_Hz, kMode90}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { +TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the // different group. - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId72); + auto selector = createSelector(kModes_30_60_90, kModeId72); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}})); @@ -1132,29 +1195,52 @@ TEST_F(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { const auto refreshRates = selector.rankRefreshRates(/*anchorGroupOpt*/ std::nullopt, RefreshRateOrder::Descending); - const std::array expectedRefreshRates = {kMode90, kMode60, kMode30}; + const auto expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {30_Hz, kMode30}}; + case Config::FrameRateOverride::Enabled: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {45_Hz, kMode90}, {30_Hz, kMode30}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, powerOnImminentConsidered) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { + auto selector = createSelector(kModes_60_90, kModeId60); - auto [refreshRates, signals] = selector.getRankedRefreshRates({}, {}); + auto [refreshRates, signals] = selector.getRankedFrameRates({}, {}); EXPECT_FALSE(signals.powerOnImminent); - std::array expectedRefreshRates = {kMode90, kMode60}; + auto expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{90_Hz, kMode90}, {60_Hz, kMode60}}; + case Config::FrameRateOverride::Enabled: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {45_Hz, kMode90}, + {30_Hz, kMode60}, {22.5_Hz, kMode90}, {20_Hz, kMode60}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } std::tie(refreshRates, signals) = @@ -1164,9 +1250,11 @@ TEST_F(RefreshRateSelectorTest, powerOnImminentConsidered) { ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } std::vector layers = {{.weight = 1.f}}; @@ -1182,29 +1270,43 @@ TEST_F(RefreshRateSelectorTest, powerOnImminentConsidered) { ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } std::tie(refreshRates, signals) = selector.getRankedRefreshRatesAsPair(layers, {.powerOnImminent = false}); EXPECT_FALSE(signals.powerOnImminent); - expectedRefreshRates = {kMode60, kMode90}; + expectedRefreshRates = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{60_Hz, kMode60}, {90_Hz, kMode90}}; + case Config::FrameRateOverride::Enabled: + return {{60_Hz, kMode60}, {90_Hz, kMode90}, {45_Hz, kMode90}, + {30_Hz, kMode60}, {22.5_Hz, kMode90}, {20_Hz, kMode60}}; + } + }(); ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size()); for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { - EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].modePtr) - << "Expected fps " << expectedRefreshRates[i]->getFps().getIntValue() - << " Actual fps " << refreshRates[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) + << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" + << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" + << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, touchConsidered) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, touchConsidered) { + auto selector = createSelector(kModes_60_90, kModeId60); - auto [_, signals] = selector.getRankedRefreshRates({}, {}); + auto [_, signals] = selector.getRankedFrameRates({}, {}); EXPECT_FALSE(signals.touch); std::tie(std::ignore, signals) = selector.getRankedRefreshRatesAsPair({}, {.touch = true}); @@ -1251,8 +1353,8 @@ TEST_F(RefreshRateSelectorTest, touchConsidered) { EXPECT_FALSE(signals.touch); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitDefault) { - TestableRefreshRateSelector selector(kModes_60_90_72_120, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) { + auto selector = createSelector(kModes_60_90_72_120, kModeId60); std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -1284,57 +1386,57 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitDefault) { ss << "ExplicitDefault " << desired; lr.name = ss.str(); - EXPECT_EQ(expected, selector.getBestRefreshRate(layers)->getFps()); + EXPECT_EQ(expected, selector.getBestFrameRateMode(layers)->getFps()); } } -TEST_F(RefreshRateSelectorTest, - getBestRefreshRate_ExplicitExactOrMultiple_WithFractionalRefreshRates) { +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_ExplicitExactOrMultiple_WithFractionalRefreshRates) { std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; // Test that 23.976 will choose 24 if 23.976 is not supported { - TestableRefreshRateSelector selector(makeModes(kMode24, kMode25, kMode30, kMode30Frac, - kMode60, kMode60Frac), - kModeId60); + auto selector = createSelector(makeModes(kMode24, kMode25, kMode30, kMode30Frac, kMode60, + kMode60Frac), + kModeId60); lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.desiredRefreshRate = 23.976_Hz; lr.name = "ExplicitExactOrMultiple 23.976 Hz"; - EXPECT_EQ(kModeId24, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId24, selector.getBestFrameRateMode(layers)->getId()); } // Test that 24 will choose 23.976 if 24 is not supported { - TestableRefreshRateSelector selector(makeModes(kMode24Frac, kMode25, kMode30, kMode30Frac, - kMode60, kMode60Frac), - kModeId60); + auto selector = createSelector(makeModes(kMode24Frac, kMode25, kMode30, kMode30Frac, + kMode60, kMode60Frac), + kModeId60); lr.desiredRefreshRate = 24_Hz; lr.name = "ExplicitExactOrMultiple 24 Hz"; - EXPECT_EQ(kModeId24Frac, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId24Frac, selector.getBestFrameRateMode(layers)->getId()); } // Test that 29.97 will prefer 59.94 over 60 and 30 { - TestableRefreshRateSelector selector(makeModes(kMode24, kMode24Frac, kMode25, kMode30, - kMode60, kMode60Frac), - kModeId60); + auto selector = createSelector(makeModes(kMode24, kMode24Frac, kMode25, kMode30, kMode60, + kMode60Frac), + kModeId60); lr.desiredRefreshRate = 29.97_Hz; lr.name = "ExplicitExactOrMultiple 29.97 Hz"; - EXPECT_EQ(kModeId60Frac, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60Frac, selector.getBestFrameRateMode(layers)->getId()); } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExact_WithFractionalRefreshRates) { +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExact_WithFractionalRefreshRates) { std::vector layers = {{.weight = 1.f}}; auto& lr = layers[0]; // Test that voting for supported refresh rate will select this refresh rate { - TestableRefreshRateSelector selector(kModes_24_25_30_50_60_Frac, kModeId60); + auto selector = createSelector(kModes_24_25_30_50_60_Frac, kModeId60); for (auto desired : {23.976_Hz, 24_Hz, 25_Hz, 29.97_Hz, 30_Hz, 50_Hz, 59.94_Hz, 60_Hz}) { lr.vote = LayerVoteType::ExplicitExact; @@ -1343,14 +1445,14 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExact_WithFractionalR ss << "ExplicitExact " << desired; lr.name = ss.str(); - EXPECT_EQ(lr.desiredRefreshRate, selector.getBestRefreshRate(layers)->getFps()); + EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getFps()); } } } -TEST_F(RefreshRateSelectorTest, - getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresTouchFlag) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId90); +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_withDisplayManagerRequestingSingleRate_ignoresTouchFlag) { + auto selector = createSelector(kModes_60_90, kModeId90); constexpr FpsRange k90 = {90_Hz, 90_Hz}; constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; @@ -1365,16 +1467,16 @@ TEST_F(RefreshRateSelectorTest, lr.name = "60Hz ExplicitDefault"; lr.focused = true; - const auto [mode, signals] = - selector.getRankedRefreshRates(layers, {.touch = true, .idle = true}); + const auto [rankedFrameRate, signals] = + selector.getRankedFrameRates(layers, {.touch = true, .idle = true}); - EXPECT_EQ(mode.begin()->modePtr, kMode60); + EXPECT_EQ(rankedFrameRate.begin()->frameRateMode.modePtr, kMode60); EXPECT_FALSE(signals.touch); } -TEST_F(RefreshRateSelectorTest, - getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresIdleFlag) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_withDisplayManagerRequestingSingleRate_ignoresIdleFlag) { + auto selector = createSelector(kModes_60_90, kModeId60); constexpr FpsRange k60 = {60_Hz, 60_Hz}; constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; @@ -1389,11 +1491,11 @@ TEST_F(RefreshRateSelectorTest, lr.desiredRefreshRate = 90_Hz; lr.name = "90Hz ExplicitDefault"; lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers, {.idle = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.idle = true})); } -TEST_F(RefreshRateSelectorTest, testDisplayModeOrdering) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 1.f}, @@ -1426,15 +1528,31 @@ TEST_F(RefreshRateSelectorTest, testDisplayModeOrdering) { lr5.name = "30Hz"; lr5.focused = true; - std::array expectedRanking = {kMode120, kMode90, kMode72, kMode60, kMode30}; - auto actualRanking = selector.getRankedRefreshRates(layers, {}).ranking; + auto expectedRanking = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{120_Hz, kMode120}, + {90_Hz, kMode90}, + {72_Hz, kMode72}, + {60_Hz, kMode60}, + {30_Hz, kMode30}}; + case Config::FrameRateOverride::Enabled: + return {{120_Hz, kMode120}, {90_Hz, kMode90}, {72_Hz, kMode72}, {60_Hz, kMode60}, + {45_Hz, kMode90}, {40_Hz, kMode120}, {36_Hz, kMode72}, {30_Hz, kMode30}}; + } + }(); + auto actualRanking = selector.getRankedFrameRates(layers, {}).ranking; ASSERT_EQ(expectedRanking.size(), actualRanking.size()); for (size_t i = 0; i < expectedRanking.size(); ++i) { - EXPECT_EQ(expectedRanking[i], actualRanking[i].modePtr) - << "Expected fps " << expectedRanking[i]->getFps().getIntValue() << " Actual fps " - << actualRanking[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) + << "Expected " << expectedRanking[i].fps.getIntValue() << " (" + << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" + << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } lr1.vote = LayerVoteType::Max; @@ -1452,15 +1570,31 @@ TEST_F(RefreshRateSelectorTest, testDisplayModeOrdering) { lr5.desiredRefreshRate = 120_Hz; lr5.name = "120Hz"; - expectedRanking = {kMode120, kMode90, kMode72, kMode60, kMode30}; - actualRanking = selector.getRankedRefreshRates(layers, {}).ranking; + expectedRanking = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{120_Hz, kMode120}, + {90_Hz, kMode90}, + {72_Hz, kMode72}, + {60_Hz, kMode60}, + {30_Hz, kMode30}}; + case Config::FrameRateOverride::Enabled: + return {{120_Hz, kMode120}, {90_Hz, kMode90}, {72_Hz, kMode72}, {60_Hz, kMode60}, + {45_Hz, kMode90}, {40_Hz, kMode120}, {36_Hz, kMode72}, {30_Hz, kMode30}}; + } + }(); + actualRanking = selector.getRankedFrameRates(layers, {}).ranking; ASSERT_EQ(expectedRanking.size(), actualRanking.size()); for (size_t i = 0; i < expectedRanking.size(); ++i) { - EXPECT_EQ(expectedRanking[i], actualRanking[i].modePtr) - << "Expected fps " << expectedRanking[i]->getFps().getIntValue() << " Actual fps " - << actualRanking[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) + << "Expected " << expectedRanking[i].fps.getIntValue() << " (" + << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" + << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } lr1.vote = LayerVoteType::Heuristic; @@ -1476,15 +1610,31 @@ TEST_F(RefreshRateSelectorTest, testDisplayModeOrdering) { lr5.desiredRefreshRate = 72_Hz; lr5.name = "72Hz"; - expectedRanking = {kMode30, kMode60, kMode90, kMode120, kMode72}; - actualRanking = selector.getRankedRefreshRates(layers, {}).ranking; + expectedRanking = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{30_Hz, kMode30}, + {60_Hz, kMode60}, + {90_Hz, kMode90}, + {120_Hz, kMode120}, + {72_Hz, kMode72}}; + case Config::FrameRateOverride::Enabled: + return {{30_Hz, kMode30}, {60_Hz, kMode60}, {90_Hz, kMode90}, {120_Hz, kMode120}, + {45_Hz, kMode90}, {40_Hz, kMode120}, {72_Hz, kMode72}, {36_Hz, kMode72}}; + } + }(); + actualRanking = selector.getRankedFrameRates(layers, {}).ranking; ASSERT_EQ(expectedRanking.size(), actualRanking.size()); for (size_t i = 0; i < expectedRanking.size(); ++i) { - EXPECT_EQ(expectedRanking[i], actualRanking[i].modePtr) - << "Expected fps " << expectedRanking[i]->getFps().getIntValue() << " Actual fps " - << actualRanking[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) + << "Expected " << expectedRanking[i].fps.getIntValue() << " (" + << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" + << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } lr1.desiredRefreshRate = 120_Hz; @@ -1503,21 +1653,37 @@ TEST_F(RefreshRateSelectorTest, testDisplayModeOrdering) { lr5.desiredRefreshRate = 120_Hz; lr5.name = "120Hz-2"; - expectedRanking = {kMode90, kMode60, kMode120, kMode72, kMode30}; - actualRanking = selector.getRankedRefreshRates(layers, {}).ranking; + expectedRanking = []() -> std::vector { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{90_Hz, kMode90}, + {60_Hz, kMode60}, + {120_Hz, kMode120}, + {72_Hz, kMode72}, + {30_Hz, kMode30}}; + case Config::FrameRateOverride::Enabled: + return {{90_Hz, kMode90}, {60_Hz, kMode60}, {120_Hz, kMode120}, {72_Hz, kMode72}, + {45_Hz, kMode90}, {40_Hz, kMode120}, {36_Hz, kMode72}, {30_Hz, kMode30}}; + } + }(); + actualRanking = selector.getRankedFrameRates(layers, {}).ranking; ASSERT_EQ(expectedRanking.size(), actualRanking.size()); for (size_t i = 0; i < expectedRanking.size(); ++i) { - EXPECT_EQ(expectedRanking[i], actualRanking[i].modePtr) - << "Expected fps " << expectedRanking[i]->getFps().getIntValue() << " Actual fps " - << actualRanking[i].modePtr->getFps().getIntValue(); + EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) + << "Expected " << expectedRanking[i].fps.getIntValue() << " (" + << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" + << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; } } -TEST_F(RefreshRateSelectorTest, - getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitFocusedLayers) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId90); +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitFocusedLayers) { + auto selector = createSelector(kModes_60_90, kModeId90); constexpr FpsRange k90 = {90_Hz, 90_Hz}; constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; @@ -1525,8 +1691,8 @@ TEST_F(RefreshRateSelectorTest, EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {k90, k90}, {k60_90, k60_90}})); - const auto [ranking, signals] = selector.getRankedRefreshRates({}, {}); - EXPECT_EQ(ranking.front().modePtr, kMode90); + const auto [ranking, signals] = selector.getRankedFrameRates({}, {}); + EXPECT_EQ(ranking.front().frameRateMode.modePtr, kMode90); EXPECT_FALSE(signals.touch); std::vector layers = {{.weight = 1.f}}; @@ -1536,50 +1702,50 @@ TEST_F(RefreshRateSelectorTest, lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz ExplicitExactOrMultiple"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::ExplicitDefault; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz ExplicitDefault"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.focused = true; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Heuristic; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Max; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Max"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.vote = LayerVoteType::Min; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Min"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); } -TEST_F(RefreshRateSelectorTest, groupSwitchingNotAllowed) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingNotAllowed) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); // The default policy doesn't allow group switching. Verify that no // group switches are performed. @@ -1591,11 +1757,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingNotAllowed) { layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayer) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayer) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1609,11 +1775,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayer) { layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId90, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1628,11 +1794,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) { layer.seamlessness = Seamlessness::OnlySeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1649,11 +1815,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps layer.seamlessness = Seamlessness::OnlySeamless; layer.name = "60Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId90, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1673,11 +1839,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) { layer.name = "60Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1702,11 +1868,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed layers[1].name = "90Hz ExplicitDefault"; layers[1].focused = false; - EXPECT_EQ(kModeId90, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1735,11 +1901,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeam layers[1].vote = LayerVoteType::ExplicitDefault; layers[1].name = "90Hz ExplicitDefault"; - EXPECT_EQ(kModeId90, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId60); +TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) { + auto selector = createSelector(kModes_60_90_G1, kModeId60); RefreshRateSelector::DisplayManagerPolicy policy; policy.defaultMode = selector.getCurrentPolicy().defaultMode; @@ -1765,11 +1931,11 @@ TEST_F(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndS layers[1].vote = LayerVoteType::ExplicitDefault; layers[1].name = "90Hz ExplicitDefault"; - EXPECT_EQ(kModeId60, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) { - TestableRefreshRateSelector selector(kModes_30_60, kModeId60); +TEST_P(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) { + auto selector = createSelector(kModes_30_60, kModeId60); // Allow group switching. RefreshRateSelector::DisplayManagerPolicy policy; @@ -1785,14 +1951,14 @@ TEST_F(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) { layer.name = "60Hz ExplicitExactOrMultiple"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); selector.setActiveModeId(kModeId120); - EXPECT_EQ(kModeId120, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId120, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) { - TestableRefreshRateSelector selector(kModes_25_30_50_60, kModeId60); +TEST_P(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) { + auto selector = createSelector(kModes_25_30_50_60, kModeId60); // Allow group switching. RefreshRateSelector::DisplayManagerPolicy policy; @@ -1813,18 +1979,18 @@ TEST_F(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) { .weight = 1.f, .focused = true}}; - EXPECT_EQ(kModeId50, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId50, selector.getBestFrameRateMode(layers)->getId()); auto& seamedLayer = layers[0]; seamedLayer.desiredRefreshRate = 30_Hz; seamedLayer.name = "30Hz ExplicitDefault"; selector.setActiveModeId(kModeId30); - EXPECT_EQ(kModeId25, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId25, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) { - TestableRefreshRateSelector selector(kModes_60_90_G1, kModeId90); +TEST_P(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) { + auto selector = createSelector(kModes_60_90_G1, kModeId90); // Allow group switching. RefreshRateSelector::DisplayManagerPolicy policy; @@ -1835,11 +2001,11 @@ TEST_F(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) { std::vector layers = { {.name = "Min", .vote = LayerVoteType::Min, .weight = 1.f, .focused = true}}; - EXPECT_EQ(kModeId90, selector.getBestRefreshRate(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); } -TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { - TestableRefreshRateSelector selector(kModes_30_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { + auto selector = createSelector(kModes_30_60_90, kModeId60); std::vector layers = {{.weight = 1.f}}; layers[0].name = "Test layer"; @@ -1849,13 +2015,14 @@ TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { bool focused = true; }; - // Returns the mode selected by getBestRefreshRate for a single layer with the given arguments. + // Returns the mode selected by getBestFrameRateMode for a single layer with the given + // arguments. const auto getFrameRate = [&](LayerVoteType voteType, Fps fps, Args args = {}) -> DisplayModeId { layers[0].vote = voteType; layers[0].desiredRefreshRate = fps; layers[0].focused = args.focused; - return selector.getBestRefreshRate(layers, {.touch = args.touch})->getId(); + return selector.getBestFrameRateMode(layers, {.touch = args.touch})->getId(); }; constexpr FpsRange k30_60 = {30_Hz, 60_Hz}; @@ -1864,7 +2031,7 @@ TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {k30_60, k30_60}, {k30_90, k30_90}})); - EXPECT_EQ(kModeId60, selector.getBestRefreshRate()->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode()->getId()); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz)); EXPECT_EQ(kModeId30, getFrameRate(LayerVoteType::Min, 90_Hz)); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::Max, 90_Hz)); @@ -1897,22 +2064,23 @@ TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90_Hz)); } -TEST_F(RefreshRateSelectorTest, idle) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, idle) { + auto selector = createSelector(kModes_60_90, kModeId60); std::vector layers = {{.weight = 1.f}}; layers[0].name = "Test layer"; - const auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> DisplayModeId { + const auto getIdleDisplayModeId = [&](LayerVoteType voteType, + bool touchActive) -> DisplayModeId { layers[0].vote = voteType; layers[0].desiredRefreshRate = 90_Hz; const auto [ranking, signals] = - selector.getRankedRefreshRates(layers, {.touch = touchActive, .idle = true}); + selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); // Refresh rate will be chosen by either touch state or idle state. EXPECT_EQ(!touchActive, signals.idle); - return ranking.front().modePtr->getId(); + return ranking.front().frameRateMode.modePtr->getId(); }; EXPECT_EQ(SetPolicyResult::Changed, @@ -1921,38 +2089,38 @@ TEST_F(RefreshRateSelectorTest, idle) { // Idle should be lower priority than touch boost. { constexpr bool kTouchActive = true; - EXPECT_EQ(kModeId90, getIdleFrameRate(LayerVoteType::NoVote, kTouchActive)); - EXPECT_EQ(kModeId90, getIdleFrameRate(LayerVoteType::Min, kTouchActive)); - EXPECT_EQ(kModeId90, getIdleFrameRate(LayerVoteType::Max, kTouchActive)); - EXPECT_EQ(kModeId90, getIdleFrameRate(LayerVoteType::Heuristic, kTouchActive)); - EXPECT_EQ(kModeId90, getIdleFrameRate(LayerVoteType::ExplicitDefault, kTouchActive)); + EXPECT_EQ(kModeId90, getIdleDisplayModeId(LayerVoteType::NoVote, kTouchActive)); + EXPECT_EQ(kModeId90, getIdleDisplayModeId(LayerVoteType::Min, kTouchActive)); + EXPECT_EQ(kModeId90, getIdleDisplayModeId(LayerVoteType::Max, kTouchActive)); + EXPECT_EQ(kModeId90, getIdleDisplayModeId(LayerVoteType::Heuristic, kTouchActive)); + EXPECT_EQ(kModeId90, getIdleDisplayModeId(LayerVoteType::ExplicitDefault, kTouchActive)); EXPECT_EQ(kModeId90, - getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, kTouchActive)); + getIdleDisplayModeId(LayerVoteType::ExplicitExactOrMultiple, kTouchActive)); } // With no layers, idle should still be lower priority than touch boost. - EXPECT_EQ(kModeId90, selector.getBestRefreshRate({}, {.touch = true, .idle = true})->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId()); // Idle should be higher precedence than other layer frame rate considerations. selector.setActiveModeId(kModeId90); { constexpr bool kTouchActive = false; - EXPECT_EQ(kModeId60, getIdleFrameRate(LayerVoteType::NoVote, kTouchActive)); - EXPECT_EQ(kModeId60, getIdleFrameRate(LayerVoteType::Min, kTouchActive)); - EXPECT_EQ(kModeId60, getIdleFrameRate(LayerVoteType::Max, kTouchActive)); - EXPECT_EQ(kModeId60, getIdleFrameRate(LayerVoteType::Heuristic, kTouchActive)); - EXPECT_EQ(kModeId60, getIdleFrameRate(LayerVoteType::ExplicitDefault, kTouchActive)); + EXPECT_EQ(kModeId60, getIdleDisplayModeId(LayerVoteType::NoVote, kTouchActive)); + EXPECT_EQ(kModeId60, getIdleDisplayModeId(LayerVoteType::Min, kTouchActive)); + EXPECT_EQ(kModeId60, getIdleDisplayModeId(LayerVoteType::Max, kTouchActive)); + EXPECT_EQ(kModeId60, getIdleDisplayModeId(LayerVoteType::Heuristic, kTouchActive)); + EXPECT_EQ(kModeId60, getIdleDisplayModeId(LayerVoteType::ExplicitDefault, kTouchActive)); EXPECT_EQ(kModeId60, - getIdleFrameRate(LayerVoteType::ExplicitExactOrMultiple, kTouchActive)); + getIdleDisplayModeId(LayerVoteType::ExplicitExactOrMultiple, kTouchActive)); } // Idle should be applied rather than the active mode when there are no layers. - EXPECT_EQ(kModeId60, selector.getBestRefreshRate({}, {.idle = true})->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode({}, {.idle = true})->getId()); } -TEST_F(RefreshRateSelectorTest, findClosestKnownFrameRate) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, findClosestKnownFrameRate) { + auto selector = createSelector(kModes_60_90, kModeId60); for (float fps = 1.0f; fps <= 120.0f; fps += 0.1f) { const auto knownFrameRate = selector.findClosestKnownFrameRate(Fps::fromValue(fps)); @@ -1969,8 +2137,8 @@ TEST_F(RefreshRateSelectorTest, findClosestKnownFrameRate) { } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_KnownFrameRate) { - TestableRefreshRateSelector selector(kModes_60_90, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_KnownFrameRate) { + auto selector = createSelector(kModes_60_90, kModeId60); struct Expectation { Fps fps; @@ -1997,101 +2165,80 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_KnownFrameRate) { for (const auto& [fps, mode] : knownFrameRatesExpectations) { layer.desiredRefreshRate = fps; - EXPECT_EQ(mode, selector.getBestRefreshRate(layers)); + EXPECT_EQ(mode, selector.getBestFrameRateMode(layers)); } } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExact) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExact) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 0.5f}}; auto& explicitExactLayer = layers[0]; auto& explicitExactOrMultipleLayer = layers[1]; - explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; - explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; - explicitExactOrMultipleLayer.desiredRefreshRate = 60_Hz; - explicitExactLayer.vote = LayerVoteType::ExplicitExact; explicitExactLayer.name = "ExplicitExact"; explicitExactLayer.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode30, selector.getBestRefreshRate(layers, {.touch = true})); - - explicitExactOrMultipleLayer.desiredRefreshRate = 120_Hz; - explicitExactLayer.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); - - explicitExactLayer.desiredRefreshRate = 72_Hz; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); - - explicitExactLayer.desiredRefreshRate = 90_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); - - explicitExactLayer.desiredRefreshRate = 120_Hz; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); -} - -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60, - {.enableFrameRateOverride = - Config::FrameRateOverride::Enabled}); - - std::vector layers = {{.weight = 1.f}, {.weight = 0.5f}}; - auto& explicitExactLayer = layers[0]; - auto& explicitExactOrMultipleLayer = layers[1]; - explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; explicitExactOrMultipleLayer.desiredRefreshRate = 60_Hz; - explicitExactLayer.vote = LayerVoteType::ExplicitExact; - explicitExactLayer.name = "ExplicitExact"; - explicitExactLayer.desiredRefreshRate = 30_Hz; + if (GetParam() == Config::FrameRateOverride::Disabled) { + EXPECT_SCORED_FRAME_RATE(kMode30, 30_Hz, selector.getBestScoredFrameRate(layers)); + EXPECT_SCORED_FRAME_RATE(kMode30, 30_Hz, + selector.getBestScoredFrameRate(layers, {.touch = true})); - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers, {.touch = true})); + } else { + EXPECT_SCORED_FRAME_RATE(kMode60, 60_Hz, selector.getBestScoredFrameRate(layers)); + EXPECT_SCORED_FRAME_RATE(kMode120, 120_Hz, + selector.getBestScoredFrameRate(layers, {.touch = true})); + } explicitExactOrMultipleLayer.desiredRefreshRate = 120_Hz; explicitExactLayer.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + + if (GetParam() == Config::FrameRateOverride::Disabled) { + EXPECT_SCORED_FRAME_RATE(kMode60, 60_Hz, selector.getBestScoredFrameRate(layers)); + } else { + EXPECT_SCORED_FRAME_RATE(kMode120, 120_Hz, selector.getBestScoredFrameRate(layers)); + } explicitExactLayer.desiredRefreshRate = 72_Hz; - EXPECT_EQ(kMode72, selector.getBestRefreshRate(layers)); + EXPECT_SCORED_FRAME_RATE(kMode72, 72_Hz, selector.getBestScoredFrameRate(layers)); explicitExactLayer.desiredRefreshRate = 90_Hz; - EXPECT_EQ(kMode90, selector.getBestRefreshRate(layers)); + EXPECT_SCORED_FRAME_RATE(kMode90, 90_Hz, selector.getBestScoredFrameRate(layers)); explicitExactLayer.desiredRefreshRate = 120_Hz; - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers)); + EXPECT_SCORED_FRAME_RATE(kMode120, 120_Hz, selector.getBestScoredFrameRate(layers)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ReadsCache) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +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{}, GlobalSignals{.touch = true, .idle = true}); - const RefreshRateSelector::RankedRefreshRates result = {{RefreshRateSelector::ScoredRefreshRate{ - kMode90}}, - {.touch = true}}; + const RefreshRateSelector::RankedFrameRates result = {{RefreshRateSelector::ScoredFrameRate{ + {90_Hz, kMode90}}}, + GlobalSignals{.touch = true}}; selector.mutableGetRankedRefreshRatesCache() = {args, result}; - EXPECT_EQ(result, selector.getRankedRefreshRates(args.first, args.second)); + EXPECT_EQ(result, selector.getRankedFrameRates(args.first, args.second)); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_WritesCache) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_WritesCache) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId60); EXPECT_FALSE(selector.mutableGetRankedRefreshRatesCache()); std::vector layers = {{.weight = 1.f}, {.weight = 0.5f}}; RefreshRateSelector::GlobalSignals globalSignals{.touch = true, .idle = true}; - const auto result = selector.getRankedRefreshRates(layers, globalSignals); + const auto result = selector.getRankedFrameRates(layers, globalSignals); const auto& cache = selector.mutableGetRankedRefreshRatesCache(); ASSERT_TRUE(cache); @@ -2100,10 +2247,8 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_WritesCache) { EXPECT_EQ(cache->result, result); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactTouchBoost) { - TestableRefreshRateSelector selector(kModes_60_120, kModeId60, - {.enableFrameRateOverride = - Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExactTouchBoost) { + auto selector = createSelector(kModes_60_120, kModeId60); std::vector layers = {{.weight = 1.f}, {.weight = 0.5f}}; auto& explicitExactLayer = layers[0]; @@ -2117,19 +2262,21 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactTouchBoost) { explicitExactLayer.name = "ExplicitExact"; explicitExactLayer.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode120, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + if (GetParam() == Config::FrameRateOverride::Disabled) { + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true})); + } else { + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers, {.touch = true})); + } explicitExactOrMultipleLayer.vote = LayerVoteType::NoVote; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true})); } -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_FractionalRefreshRates_ExactAndDefault) { - TestableRefreshRateSelector selector(kModes_24_25_30_50_60_Frac, kModeId60, - {.enableFrameRateOverride = - Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_FractionalRefreshRates_ExactAndDefault) { + auto selector = createSelector(kModes_24_25_30_50_60_Frac, kModeId60); std::vector layers = {{.weight = 0.5f}, {.weight = 0.5f}}; auto& explicitDefaultLayer = layers[0]; @@ -2143,12 +2290,12 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_FractionalRefreshRates_ExactA explicitDefaultLayer.name = "ExplicitDefault"; explicitDefaultLayer.desiredRefreshRate = 59.94_Hz; - EXPECT_EQ(kMode60, selector.getBestRefreshRate(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); } // b/190578904 -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withCloseRefreshRates) { - constexpr int kMinRefreshRate = 10; +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withCloseRefreshRates) { + const int kMinRefreshRate = RefreshRateSelector::kMinSupportedFrameRate.getIntValue(); constexpr int kMaxRefreshRate = 240; DisplayModes displayModes; @@ -2159,14 +2306,13 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withCloseRefreshRates) { Fps::fromValue(static_cast(fps)))); } - const TestableRefreshRateSelector selector(std::move(displayModes), - DisplayModeId(kMinRefreshRate)); + const auto selector = createSelector(std::move(displayModes), DisplayModeId(kMinRefreshRate)); std::vector layers = {{.weight = 1.f}}; const auto testRefreshRate = [&](Fps fps, LayerVoteType vote) { layers[0].desiredRefreshRate = fps; layers[0].vote = vote; - EXPECT_EQ(fps.getIntValue(), selector.getBestRefreshRate(layers)->getFps().getIntValue()) + EXPECT_EQ(fps.getIntValue(), selector.getBestFrameRateMode(layers)->getFps().getIntValue()) << "Failed for " << ftl::enum_string(vote); }; @@ -2180,7 +2326,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withCloseRefreshRates) { } // b/190578904 -TEST_F(RefreshRateSelectorTest, getBestRefreshRate_conflictingVotes) { +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_conflictingVotes) { constexpr DisplayModeId kActiveModeId{0}; DisplayModes displayModes = makeModes(createDisplayMode(kActiveModeId, 43_Hz), createDisplayMode(DisplayModeId(1), 53_Hz), @@ -2188,7 +2334,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_conflictingVotes) { createDisplayMode(DisplayModeId(3), 60_Hz)); const RefreshRateSelector::GlobalSignals globalSignals = {.touch = false, .idle = false}; - const TestableRefreshRateSelector selector(std::move(displayModes), kActiveModeId); + const auto selector = createSelector(std::move(displayModes), kActiveModeId); const std::vector layers = { { @@ -2205,19 +2351,19 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_conflictingVotes) { }, }; - EXPECT_EQ(53_Hz, selector.getBestRefreshRate(layers, globalSignals)->getFps()); + EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getFps()); } -TEST_F(RefreshRateSelectorTest, modeComparison) { +TEST_P(RefreshRateSelectorTest, modeComparison) { EXPECT_LT(kMode60->getFps(), kMode90->getFps()); EXPECT_GE(kMode60->getFps(), kMode60->getFps()); EXPECT_GE(kMode90->getFps(), kMode90->getFps()); } -TEST_F(RefreshRateSelectorTest, testKernelIdleTimerAction) { +TEST_P(RefreshRateSelectorTest, testKernelIdleTimerAction) { using KernelIdleTimerAction = RefreshRateSelector::KernelIdleTimerAction; - TestableRefreshRateSelector selector(kModes_60_90, kModeId90); + auto selector = createSelector(kModes_60_90, kModeId90); EXPECT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction()); @@ -2234,10 +2380,10 @@ TEST_F(RefreshRateSelectorTest, testKernelIdleTimerAction) { EXPECT_EQ(KernelIdleTimerAction::TurnOff, selector.getIdleTimerAction()); } -TEST_F(RefreshRateSelectorTest, testKernelIdleTimerActionFor120Hz) { +TEST_P(RefreshRateSelectorTest, testKernelIdleTimerActionFor120Hz) { using KernelIdleTimerAction = RefreshRateSelector::KernelIdleTimerAction; - TestableRefreshRateSelector selector(kModes_60_120, kModeId120); + auto selector = createSelector(kModes_60_120, kModeId120); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 60_Hz}})); @@ -2256,8 +2402,8 @@ TEST_F(RefreshRateSelectorTest, testKernelIdleTimerActionFor120Hz) { EXPECT_EQ(KernelIdleTimerAction::TurnOff, selector.getIdleTimerAction()); } -TEST_F(RefreshRateSelectorTest, getFrameRateDivisor) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId30); +TEST_P(RefreshRateSelectorTest, getFrameRateDivisor) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId30); const auto frameRate = 30_Hz; Fps displayRefreshRate = selector.getActiveMode().getFps(); @@ -2289,7 +2435,7 @@ TEST_F(RefreshRateSelectorTest, getFrameRateDivisor) { EXPECT_EQ(0, RefreshRateSelector::getFrameRateDivisor(60_Hz, 59.94_Hz)); } -TEST_F(RefreshRateSelectorTest, isFractionalPairOrMultiple) { +TEST_P(RefreshRateSelectorTest, isFractionalPairOrMultiple) { EXPECT_TRUE(RefreshRateSelector::isFractionalPairOrMultiple(23.976_Hz, 24_Hz)); EXPECT_TRUE(RefreshRateSelector::isFractionalPairOrMultiple(24_Hz, 23.976_Hz)); @@ -2315,22 +2461,72 @@ TEST_F(RefreshRateSelectorTest, isFractionalPairOrMultiple) { EXPECT_FALSE(RefreshRateSelector::isFractionalPairOrMultiple(29.97_Hz, 59.94_Hz)); } -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_noLayers) { - RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_noLayers) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); EXPECT_TRUE(selector.getFrameRateOverrides({}, 120_Hz, {}).empty()); } -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_60on120) { - RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_NonExplicit) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); std::vector layers = {{.weight = 1.f}}; layers[0].name = "Test layer"; layers[0].ownerUid = 1234; layers[0].desiredRefreshRate = 60_Hz; + + layers[0].vote = LayerVoteType::NoVote; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); + + layers[0].vote = LayerVoteType::Min; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); + + layers[0].vote = LayerVoteType::Max; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); + + layers[0].vote = LayerVoteType::Heuristic; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); +} + +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_Disabled) { + if (GetParam() != Config::FrameRateOverride::Disabled) { + return; + } + + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); + + std::vector layers = {{.weight = 1.f}}; + layers[0].name = "Test layer"; + layers[0].ownerUid = 1234; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].vote = LayerVoteType::ExplicitDefault; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); + + layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); + + layers[0].vote = LayerVoteType::ExplicitExact; + EXPECT_TRUE(selector.getFrameRateOverrides(layers, 120_Hz, {}).empty()); +} + +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_60on120) { + if (GetParam() == Config::FrameRateOverride::Disabled) { + return; + } + + ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates || + GetParam() == Config::FrameRateOverride::AppOverride || + GetParam() == Config::FrameRateOverride::Enabled); + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); + + std::vector layers = {{.weight = 1.f}}; + layers[0].name = "Test layer"; + layers[0].ownerUid = 1234; + layers[0].desiredRefreshRate = 60_Hz; + + layers[0].vote = LayerVoteType::ExplicitDefault; auto frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); EXPECT_EQ(1u, frameRateOverrides.size()); ASSERT_EQ(1u, frameRateOverrides.count(1234)); @@ -2342,26 +2538,23 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_60on120) { ASSERT_EQ(1u, frameRateOverrides.count(1234)); EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); - layers[0].vote = LayerVoteType::NoVote; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); - - layers[0].vote = LayerVoteType::Min; + layers[0].vote = LayerVoteType::ExplicitExact; frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); +} - layers[0].vote = LayerVoteType::Max; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { + if (GetParam() == Config::FrameRateOverride::Disabled) { + return; + } - layers[0].vote = LayerVoteType::Heuristic; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); -} + ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates || + GetParam() == Config::FrameRateOverride::AppOverride || + GetParam() == Config::FrameRateOverride::Enabled); -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { - RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); std::vector layers = {{.ownerUid = 1234, .weight = 1.f}, {.ownerUid = 5678, .weight = 1.f}}; @@ -2392,9 +2585,16 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { EXPECT_TRUE(frameRateOverrides.empty()); } -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_touch) { - RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_touch) { + if (GetParam() == Config::FrameRateOverride::Disabled) { + return; + } + + ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates || + GetParam() == Config::FrameRateOverride::AppOverride || + GetParam() == Config::FrameRateOverride::Enabled); + + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); std::vector layers = {{.ownerUid = 1234, .weight = 1.f}}; layers[0].name = "Test layer"; @@ -2432,88 +2632,87 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_touch) { EXPECT_TRUE(frameRateOverrides.empty()); } -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_DivisorIsNotDisplayRefreshRate_Enabled) { - RefreshRateSelector selector(kModes_60_120, kModeId120, - {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_DivisorIsNotDisplayRefreshRate) { + if (GetParam() == Config::FrameRateOverride::Disabled) { + return; + } + + ASSERT_TRUE(GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates || + GetParam() == Config::FrameRateOverride::AppOverride || + GetParam() == Config::FrameRateOverride::Enabled); + + auto selector = createSelector(kModes_60_120, kModeId120); std::vector layers = {{.weight = 1.f}}; layers[0].name = "Test layer"; layers[0].ownerUid = 1234; layers[0].desiredRefreshRate = 30_Hz; - layers[0].vote = LayerVoteType::ExplicitDefault; + const auto expetedFps = + GetParam() == Config::FrameRateOverride::AppOverrideNativeRefreshRates ? 60_Hz : 30_Hz; + layers[0].vote = LayerVoteType::ExplicitDefault; auto frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); EXPECT_EQ(1u, frameRateOverrides.size()); ASSERT_EQ(1u, frameRateOverrides.count(1234)); - EXPECT_EQ(30_Hz, frameRateOverrides.at(1234)); + EXPECT_EQ(expetedFps, frameRateOverrides.at(1234)); layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); EXPECT_EQ(1u, frameRateOverrides.size()); ASSERT_EQ(1u, frameRateOverrides.count(1234)); - EXPECT_EQ(30_Hz, frameRateOverrides.at(1234)); - - layers[0].vote = LayerVoteType::NoVote; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); - - layers[0].vote = LayerVoteType::Min; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); - - layers[0].vote = LayerVoteType::Max; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); + EXPECT_EQ(expetedFps, frameRateOverrides.at(1234)); - layers[0].vote = LayerVoteType::Heuristic; + layers[0].vote = LayerVoteType::ExplicitExact; frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); -} - -TEST_F(RefreshRateSelectorTest, - getFrameRateOverrides_DivisorIsNotDisplayRefreshRate_EnabledForNativeRefreshRates) { - RefreshRateSelector selector(kModes_60_120, kModeId120, - {.enableFrameRateOverride = - Config::FrameRateOverride::EnabledForNativeRefreshRates}); - - std::vector layers = {{.weight = 1.f}}; - layers[0].name = "Test layer"; - layers[0].ownerUid = 1234; - layers[0].desiredRefreshRate = 30_Hz; - layers[0].vote = LayerVoteType::ExplicitDefault; - - auto frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); EXPECT_EQ(1u, frameRateOverrides.size()); ASSERT_EQ(1u, frameRateOverrides.count(1234)); - EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + EXPECT_EQ(expetedFps, frameRateOverrides.at(1234)); +} - layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_EQ(1u, frameRateOverrides.size()); - ASSERT_EQ(1u, frameRateOverrides.count(1234)); - EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); +TEST_P(RefreshRateSelectorTest, renderFrameRateInvalidPolicy) { + auto selector = createSelector(kModes_60_120, kModeId120); - layers[0].vote = LayerVoteType::NoVote; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); + // The render frame rate cannot be greater than the physical refresh rate + { + const FpsRange physical = {60_Hz, 60_Hz}; + const FpsRange render = {60_Hz, 120_Hz}; + EXPECT_EQ(SetPolicyResult::Invalid, + selector.setDisplayManagerPolicy( + {kModeId60, {physical, render}, {physical, render}})); + } +} - layers[0].vote = LayerVoteType::Min; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); +TEST_P(RefreshRateSelectorTest, renderFrameRateRestrictsPhysicalRefreshRate) { + auto selector = createSelector(kModes_60_120, kModeId120); - layers[0].vote = LayerVoteType::Max; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); + { + const FpsRange physical = {0_Hz, 120_Hz}; + const FpsRange render = {0_Hz, 60_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId60, {physical, render}, {physical, render}})); + const auto expectedMaxMode = + GetParam() == Config::FrameRateOverride::Enabled ? kMode120 : kMode60; + EXPECT_EQ(expectedMaxMode, selector.getMaxRefreshRateByPolicy()); + EXPECT_EQ(kMode60, selector.getMinRefreshRateByPolicy()); + } - layers[0].vote = LayerVoteType::Heuristic; - frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); - EXPECT_TRUE(frameRateOverrides.empty()); + { + const FpsRange physical = {0_Hz, 120_Hz}; + const FpsRange render = {120_Hz, 120_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId60, {physical, render}, {physical, render}})); + EXPECT_EQ(kMode120, selector.getMaxRefreshRateByPolicy()); + EXPECT_EQ(kMode120, selector.getMinRefreshRateByPolicy()); + } } -TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_InPolicy) { - TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = - Config::FrameRateOverride::Enabled}); +TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_InPolicy) { + if (GetParam() != Config::FrameRateOverride::Enabled) { + return; + } + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); std::vector layers = {{.weight = 1.f}}; { @@ -2566,5 +2765,153 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_InPolicy) { EXPECT_EQ(30_Hz, frameRateOverrides.at(1234)); } +TEST_P(RefreshRateSelectorTest, renderFrameRates) { + auto selector = createSelector(kModes_30_60_72_90_120, kModeId120); + + // [renderRate, refreshRate] + const auto expected = []() -> std::vector> { + switch (GetParam()) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::AppOverrideNativeRefreshRates: + case Config::FrameRateOverride::AppOverride: + return {{30_Hz, 30_Hz}, + {60_Hz, 60_Hz}, + {72_Hz, 72_Hz}, + {90_Hz, 90_Hz}, + {120_Hz, 120_Hz}}; + case Config::FrameRateOverride::Enabled: + return {{30_Hz, 30_Hz}, {36_Hz, 72_Hz}, {40_Hz, 120_Hz}, {45_Hz, 90_Hz}, + {60_Hz, 60_Hz}, {72_Hz, 72_Hz}, {90_Hz, 90_Hz}, {120_Hz, 120_Hz}}; + } + }(); + + const auto& primaryRefreshRates = selector.getPrimaryFrameRates(); + ASSERT_EQ(expected.size(), primaryRefreshRates.size()); + + for (size_t i = 0; i < expected.size(); i++) { + const auto [expectedRenderRate, expectedRefreshRate] = expected[i]; + EXPECT_EQ(expectedRenderRate, primaryRefreshRates[i].fps); + EXPECT_EQ(expectedRefreshRate, primaryRefreshRates[i].modePtr->getFps()); + } +} + +TEST_P(RefreshRateSelectorTest, refreshRateIsCappedWithRenderFrameRate) { + if (GetParam() != Config::FrameRateOverride::Enabled) { + return; + } + + auto selector = createSelector(kModes_60_120, kModeId60); + + constexpr FpsRange k0_120Hz = {0_Hz, 120_Hz}; + constexpr FpsRange k0_60Hz = {0_Hz, 60_Hz}; + + constexpr FpsRanges kAppRequest = {/*physical*/ k0_120Hz, + /*render*/ k0_120Hz}; + + EXPECT_SCORED_FRAME_RATE(kMode120, 120_Hz, selector.getBestScoredFrameRate()); + { + constexpr FpsRanges kPrimary = {/*physical*/ k0_120Hz, + /*render*/ k0_120Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy({/*defaultMode*/ kModeId60, + /*primaryRanges*/ + kPrimary, + /*appRequestRanges*/ + kAppRequest})); + } + EXPECT_SCORED_FRAME_RATE(kMode120, 120_Hz, selector.getBestScoredFrameRate()); + + { + constexpr FpsRanges kPrimary = {/*physical*/ k0_60Hz, + /*render*/ k0_60Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy({/*defaultMode*/ kModeId60, + /*primaryRanges*/ + kPrimary, + /*appRequestRanges*/ + kAppRequest})); + } + EXPECT_SCORED_FRAME_RATE(kMode60, 60_Hz, selector.getBestScoredFrameRate()); + + { + constexpr FpsRanges kPrimary = {/*physical*/ k0_120Hz, + /*render*/ k0_60Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy({/*defaultMode*/ kModeId60, + /*primaryRanges*/ + kPrimary, + /*appRequestRanges*/ + kAppRequest})); + } + EXPECT_SCORED_FRAME_RATE(kMode60, 60_Hz, selector.getBestScoredFrameRate()); +} + +TEST_P(RefreshRateSelectorTest, renderFrameRates_60_120) { + auto selector = createSelector(kModes_60_120, kModeId120); + + std::vector layers = {{.weight = 1.f}}; + auto& layer = layers[0]; + + const auto expectedRenderRate = + GetParam() == Config::FrameRateOverride::Enabled ? 30_Hz : 60_Hz; + + layer.name = "30Hz ExplicitDefault"; + layer.desiredRefreshRate = 30_Hz; + layer.vote = LayerVoteType::ExplicitDefault; + EXPECT_SCORED_FRAME_RATE(kMode60, expectedRenderRate, selector.getBestScoredFrameRate(layers)); + + layer.name = "30Hz Heuristic"; + layer.desiredRefreshRate = 30_Hz; + layer.vote = LayerVoteType::Heuristic; + EXPECT_SCORED_FRAME_RATE(kMode60, expectedRenderRate, selector.getBestScoredFrameRate(layers)); + + layer.name = "30Hz ExplicitExactOrMultiple"; + layer.desiredRefreshRate = 30_Hz; + layer.vote = LayerVoteType::ExplicitExactOrMultiple; + EXPECT_SCORED_FRAME_RATE(kMode60, expectedRenderRate, selector.getBestScoredFrameRate(layers)); +} + +TEST_P(RefreshRateSelectorTest, idleWhenLowestRefreshRateIsNotDivisor) { + auto selector = createSelector(kModes_35_60_90, kModeId60); + + std::vector layers = {{.weight = 1.f}}; + layers[0].name = "Test layer"; + + const auto getIdleDisplayModeId = [&](LayerVoteType voteType, + bool touchActive) -> DisplayModeId { + layers[0].vote = voteType; + layers[0].desiredRefreshRate = 90_Hz; + + const auto [ranking, signals] = + selector.getRankedFrameRates(layers, {.touch = touchActive, .idle = true}); + + // Refresh rate will be chosen by either touch state or idle state. + EXPECT_EQ(!touchActive, signals.idle); + return ranking.front().frameRateMode.modePtr->getId(); + }; + + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 90_Hz}})); + + // With no layers, idle should still be lower priority than touch boost. + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId()); + + // Idle should be higher precedence than other layer frame rate considerations. + selector.setActiveModeId(kModeId90); + { + constexpr bool kTouchActive = false; + EXPECT_EQ(kModeId35, getIdleDisplayModeId(LayerVoteType::NoVote, kTouchActive)); + EXPECT_EQ(kModeId35, getIdleDisplayModeId(LayerVoteType::Min, kTouchActive)); + EXPECT_EQ(kModeId35, getIdleDisplayModeId(LayerVoteType::Max, kTouchActive)); + EXPECT_EQ(kModeId35, getIdleDisplayModeId(LayerVoteType::Heuristic, kTouchActive)); + EXPECT_EQ(kModeId35, getIdleDisplayModeId(LayerVoteType::ExplicitDefault, kTouchActive)); + EXPECT_EQ(kModeId35, + getIdleDisplayModeId(LayerVoteType::ExplicitExactOrMultiple, kTouchActive)); + } + + // Idle should be applied rather than the active mode when there are no layers. + EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true})->getId()); +} + } // namespace } // namespace android::scheduler -- cgit v1.2.3-59-g8ed1b