diff options
9 files changed, 1278 insertions, 710 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8a3e784746..d53f0b167c 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 <chrono> #include <cmath> #include <deque> +#include <map> #include <android-base/properties.h> #include <android-base/stringprintf.h> @@ -31,6 +32,7 @@ #include <ftl/fake_guard.h> #include <ftl/match.h> #include <ftl/unit.h> +#include <scheduler/FrameRateMode.h> #include <utils/Trace.h> #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<Fps> constructKnownFrameRates(const DisplayModes& modes) { return knownFrameRates; } -// The Filter is a `bool(const DisplayMode&)` predicate. -template <typename Filter> -std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes, Filter&& filter) { +std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes) { std::vector<DisplayModeIterator> 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<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes, Fi return sortedModes; } +std::pair<unsigned, unsigned> 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<DisplayModeIterator>& 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<bool(const DisplayMode&)>&& filterModes, const FpsRange& renderRange) const + -> std::vector<FrameRateMode> { + 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<Key, DisplayModeIterator, KeyLess> 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<FrameRateMode> 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<int>(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<LayerRequirement>& layers, - GlobalSignals signals) const -> RankedRefreshRates { +auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement>& 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<LayerRequirement>& layers, - GlobalSignals signals) const - -> RankedRefreshRates { +auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& 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<LayerReq // selected a refresh rate to see if we should apply touch boost. if (signals.touch && !hasExplicitVoteLayers) { ALOGV("Touch Boost"); - return {rankRefreshRates(anchorGroup, RefreshRateOrder::Descending), + return {rankFrameRates(anchorGroup, RefreshRateOrder::Descending), GlobalSignals{.touch = true}}; } @@ -387,27 +486,27 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) { ALOGV("Idle"); - return {rankRefreshRates(activeMode.getGroup(), RefreshRateOrder::Ascending), + return {rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending), GlobalSignals{.idle = true}}; } if (layers.empty() || noVoteLayers == layers.size()) { ALOGV("No layers with votes"); - return {rankRefreshRates(anchorGroup, RefreshRateOrder::Descending), kNoSignals}; + return {rankFrameRates(anchorGroup, RefreshRateOrder::Descending), kNoSignals}; } // Only if all layers want Min we should return Min if (noVoteLayers + minVoteLayers == layers.size()) { ALOGV("All layers Min"); - return {rankRefreshRates(activeMode.getGroup(), RefreshRateOrder::Ascending), kNoSignals}; + return {rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending), kNoSignals}; } // Find the best refresh rate based on score std::vector<RefreshRateScore> 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::vector<LayerReq const auto weight = layer.weight; - for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { - const auto& [id, mode] = *modeIt; - const bool isSeamlessSwitch = mode->getGroup() == 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::vector<LayerReq !layer.focused) { ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed." " 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; } @@ -445,14 +544,14 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq // mode group otherwise. In second case, if the current mode group is different // from the default, this means a layer with seamlessness=SeamedAndSeamless has just // disappeared. - const bool isInPolicyForDefault = mode->getGroup() == 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::vector<LayerReq continue; } - const float layerScore = - calculateLayerScoreLocked(layer, mode->getFps(), 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::vector<LayerReq Fps::fromValue(mConfig.frameRateMultipleThreshold / 2); if (fixedSourceLayer && layerBelowThreshold) { const bool modeAboveThreshold = - mode->getFps() >= 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<LayerReq const auto maxScoreIt = std::max_element(scores.begin(), scores.end(), [](RefreshRateScore max, RefreshRateScore current) { - const auto& [modeIt, overallScore, _] = current; - return overallScore > 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::vector<LayerReq std::sort(scores.begin(), scores.end(), RefreshRateScoreComparator{.refreshRateOrder = refreshRateOrder}); - RefreshRateRanking ranking; + FrameRateRanking ranking; ranking.reserve(scores.size()); std::transform(scores.begin(), scores.end(), back_inserter(ranking), [](const RefreshRateScore& score) { - return ScoredRefreshRate{score.modeIt->second, 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::vector<LayerReq // range instead of picking a random score from the app range. if (noLayerScore) { ALOGV("Layers not scored"); - return {rankRefreshRates(anchorGroup, RefreshRateOrder::Descending), kNoSignals}; + return {rankFrameRates(anchorGroup, RefreshRateOrder::Descending), kNoSignals}; } else { return {ranking, kNoSignals}; } @@ -580,7 +679,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq // vote we should not change it if we get a touch event. Only apply touch boost if it will // actually increase the refresh rate over the normal selection. const bool touchBoostForExplicitExact = [&] { - if (supportsFrameRateOverrideByContent()) { + if (supportsAppFrameRateOverrideByContent()) { // Enable touch boost if there are other layers besides exact return explicitExact + noVoteLayers != layers.size(); } else { @@ -589,12 +688,11 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq } }(); - const auto touchRefreshRates = rankRefreshRates(anchorGroup, RefreshRateOrder::Descending); - + const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending); using fps_approx_ops::operator<; if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact && - scores.front().modeIt->second->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<LayerReq // current config if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) { const auto preferredDisplayMode = activeMode.getId(); - return {rankRefreshRates(anchorGroup, RefreshRateOrder::Ascending, preferredDisplayMode), + return {rankFrameRates(anchorGroup, RefreshRateOrder::Ascending, preferredDisplayMode), kNoSignals}; } @@ -649,20 +747,13 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme GlobalSignals globalSignals) const -> 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<Fps, ftl::Unit, kStaticCapacity, FpsApproxEqual> 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<LayerRequireme for (unsigned n = numMultiples; n > 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<LayerRequireme [](const auto& lhsPair, const auto& rhsPair) { const float lhs = lhsPair.second; const float rhs = rhsPair.second; - return lhs < rhs && !ScoredRefreshRate::scoresEqual(lhs, rhs); + return lhs < rhs && !ScoredFrameRate::scoresEqual(lhs, rhs); }); ALOGV("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid); frameRateOverrides.emplace(uid, overrideFps); @@ -765,10 +856,9 @@ std::optional<Fps> 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<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder, - std::optional<DisplayModeId> preferredDisplayModeOpt) const -> RefreshRateRanking { - std::deque<ScoredRefreshRate> ranking; - - const auto rankRefreshRate = [&](DisplayModeIterator it) REQUIRES(mLock) { - const auto& mode = it->second; - if (anchorGroupOpt && mode->getGroup() != anchorGroupOpt) { +auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt, + RefreshRateOrder refreshRateOrder, + std::optional<DisplayModeId> preferredDisplayModeOpt) const + -> FrameRateRanking { + const char* const whence = __func__; + std::deque<ScoredFrameRate> 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<float>::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<int> 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 <ftl/concat.h> #include <ftl/optional.h> +#include <ftl/unit.h> #include <gui/DisplayEventReceiver.h> #include <scheduler/Fps.h> +#include <scheduler/FrameRateMode.h> #include <scheduler/Seamlessness.h> #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<ScoredRefreshRate>; + using FrameRateRanking = std::vector<ScoredFrameRate>; - 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<LayerRequirement>&, - GlobalSignals) const EXCLUDES(mLock); + RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, 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<LayerRequirement>&, - GlobalSignals) const REQUIRES(mLock); + RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& 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<int> anchorGroupOpt, RefreshRateOrder, - std::optional<DisplayModeId> preferredDisplayModeOpt = - std::nullopt) const REQUIRES(mLock); + FrameRateRanking rankFrameRates( + std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder, + std::optional<DisplayModeId> 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<FrameRateMode> createFrameRateModes( + std::function<bool(const DisplayMode&)>&& 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<Fps, ftl::Unit, 8, FpsApproxEqual> 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<DisplayModeIterator> mPrimaryRefreshRates GUARDED_BY(mLock); - std::vector<DisplayModeIterator> mAppRequestRefreshRates GUARDED_BY(mLock); + std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock); + std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock); Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); @@ -466,11 +503,11 @@ private: const Config mConfig; Config::FrameRateOverride mFrameRateOverrideConfig; - struct GetRankedRefreshRatesCache { + struct GetRankedFrameRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; - RankedRefreshRates result; + RankedFrameRates result; }; - mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock); + mutable std::optional<GetRankedFrameRatesCache> 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<VSyncSource> Scheduler::makePrimaryDispSyncSource( std::optional<Fps> 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<FrameRateOverride> 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<RankedRefreshRates> 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<float>::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<Fps>); @@ -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 <scheduler/Fps.h> + +// TODO(b/241285191): Pull this to <ui/DisplayMode.h> +#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 9f26129748..032541c8bf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2793,7 +2793,11 @@ sp<DisplayDevice> 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<LayerRequirement> layers = {{.weight = mFdp.ConsumeFloatingPoint<float>()}}; - refreshRateSelector.getRankedRefreshRates(layers, globalSignals); + refreshRateSelector.getRankedFrameRates(layers, globalSignals); layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength); layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>(); 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 <log/log.h> #include <ui/Size.h> +#include <scheduler/FrameRateMode.h> #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<int> anchorGroupOpt, - RefreshRateOrder refreshRateOrder) const { + FrameRateRanking rankRefreshRates(std::optional<int> anchorGroupOpt, + RefreshRateOrder refreshRateOrder) const { std::lock_guard lock(mLock); - return RefreshRateSelector::rankRefreshRates(anchorGroupOpt, refreshRateOrder); + return RefreshRateSelector::rankFrameRates(anchorGroupOpt, refreshRateOrder); } const std::vector<Fps>& knownFrameRates() const { return mKnownFrameRates; } - using RefreshRateSelector::GetRankedRefreshRatesCache; - auto& mutableGetRankedRefreshRatesCache() { return mGetRankedRefreshRatesCache; } + using RefreshRateSelector::GetRankedFrameRatesCache; + auto& mutableGetRankedRefreshRatesCache() { return mGetRankedFrameRatesCache; } - auto getRankedRefreshRates(const std::vector<LayerRequirement>& layers, - GlobalSignals signals) const { - const auto result = RefreshRateSelector::getRankedRefreshRates(layers, signals); + auto getRankedFrameRates(const std::vector<LayerRequirement>& 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<LayerRequirement>& 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<LayerRequirement>& layers = {}, - GlobalSignals signals = {}) const { - return getRankedRefreshRates(layers, signals).ranking.front().modePtr; + DisplayModePtr getBestFrameRateMode(const std::vector<LayerRequirement>& layers = {}, + GlobalSignals signals = {}) const { + return getRankedFrameRates(layers, signals).ranking.front().frameRateMode.modePtr; + } + + ScoredFrameRate getBestScoredFrameRate(const std::vector<LayerRequirement>& 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<Config::FrameRateOverride> { 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<FrameRateMode> { + 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<FrameRateMode> { + 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<FrameRateMode> { + 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<FrameRateMode> { + 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<FrameRateMode> { + 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<LayerRequirement> 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<FrameRateMode> { + 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<FrameRateMode> { + 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<FrameRateMode> { + 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<FrameRateMode> { + 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<FrameRateMode> { + 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement>{}, 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<float>(fps)))); } - const TestableRefreshRateSelector selector(std::move(displayModes), - DisplayModeId(kMinRefreshRate)); + const auto selector = createSelector(std::move(displayModes), DisplayModeId(kMinRefreshRate)); std::vector<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<LayerRequirement> 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<std::pair<Fps, Fps>> { + 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<LayerRequirement> 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<LayerRequirement> 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 |