diff options
-rw-r--r-- | libs/gui/LayerState.cpp | 10 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 13 | ||||
-rw-r--r-- | libs/nativewindow/include/apex/window.h | 13 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 9 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerHistory.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp | 88 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateConfigs.h | 20 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.cpp | 10 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp | 176 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp | 15 |
13 files changed, 308 insertions, 62 deletions
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 63be3edf94..e5e10a0014 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "LayerState" +#include <apex/window.h> #include <inttypes.h> #include <binder/Parcel.h> @@ -620,7 +621,8 @@ status_t InputWindowCommands::read(const Parcel& input) { return NO_ERROR; } -bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) { +bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName, + bool privileged) { const char* functionName = inFunctionName != nullptr ? inFunctionName : "call"; int floatClassification = std::fpclassify(frameRate); if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { @@ -629,8 +631,10 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc } if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && - compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) { - ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility); + compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && + (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { + ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, + compatibility, privileged ? "yes" : "no"); return false; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4a372bba1e..78f655a71b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1518,7 +1518,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame mStatus = BAD_INDEX; return *this; } - if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate")) { + // Allow privileged values as well here, those will be ignored by SF if + // the caller is not privileged + if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate", + /*privileged=*/true)) { mStatus = BAD_VALUE; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 4a291aeb02..83a9d3356e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -309,11 +309,14 @@ static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) return compare_type(lhs.token, rhs.token); } -// Returns true if the frameRate and compatibility are valid values, false -// othwerise. If either of the params are invalid, an error log is printed, and -// functionName is added to the log to indicate which function call failed. -// functionName can be null. -bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName); +// Returns true if the frameRate is valid. +// +// @param frameRate the frame rate in Hz +// @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* +// @param functionName calling function or nullptr. Used for logging +// @param privileged whether caller has unscoped surfaceflinger access +bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName, + bool privileged = false); struct CaptureArgs { const static int32_t UNSET_UID = -1; diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h index 2d1354cdf1..0923438eec 100644 --- a/libs/nativewindow/include/apex/window.h +++ b/libs/nativewindow/include/apex/window.h @@ -39,6 +39,19 @@ enum ANativeWindowPerform { // clang-format on }; +/* + * Internal extension of compatibility value for ANativeWindow_setFrameRate. */ +enum ANativeWindow_FrameRateCompatibilityInternal { + /** + * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display + * to operate at the exact frame rate. + * + * This is used internally by the platform and should not be used by apps. + * @hide + */ + ANATIVEWINDOW_FRAME_RATE_EXACT = 100, +}; + /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 24d1b52a49..66ce3f1a44 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1441,11 +1441,14 @@ void Layer::updateTreeHasFrameRateVote() { layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; + const auto layerVotedWithExactCompatibility = + layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact; // We do not count layers that are ExactOrMultiple for the same reason // we are allowing touch boost for those layers. See // RefreshRateConfigs::getBestRefreshRate for more details. - if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) { + if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote || + layerVotedWithExactCompatibility) { layersWithVote++; } @@ -1662,6 +1665,8 @@ std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility co return "ExactOrMultiple"; case FrameRateCompatibility::NoVote: return "NoVote"; + case FrameRateCompatibility::Exact: + return "Exact"; } } @@ -2763,6 +2768,8 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::Default; case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: return FrameRateCompatibility::ExactOrMultiple; + case ANATIVEWINDOW_FRAME_RATE_EXACT: + return FrameRateCompatibility::Exact; default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f78b5f31e9..359340eb64 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -145,6 +145,8 @@ public: enum class FrameRateCompatibility { Default, // Layer didn't specify any specific handling strategy + Exact, // Layer needs the exact frame rate. + ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the // content properly. Any other value will result in a pull down. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 170933d9b3..7ef531df63 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -71,6 +71,7 @@ void trace(const wp<Layer>& weak, const LayerInfo& info, LayerHistory::LayerVote traceType(LayerHistory::LayerVoteType::Heuristic, fps); traceType(LayerHistory::LayerVoteType::ExplicitDefault, fps); traceType(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, fps); + traceType(LayerHistory::LayerVoteType::ExplicitExact, fps); traceType(LayerHistory::LayerVoteType::Min, 1); traceType(LayerHistory::LayerVoteType::Max, 1); @@ -172,6 +173,8 @@ void LayerHistory::partitionLayers(nsecs_t now) { return LayerVoteType::ExplicitExactOrMultiple; case Layer::FrameRateCompatibility::NoVote: return LayerVoteType::NoVote; + case Layer::FrameRateCompatibility::Exact: + return LayerVoteType::ExplicitExact; } }(); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 0f1e26750e..81ffe0f20e 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -83,6 +83,8 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { return "ExplicitDefault"; case LayerVoteType::ExplicitExactOrMultiple: return "ExplicitExactOrMultiple"; + case LayerVoteType::ExplicitExact: + return "ExplicitExact"; } } @@ -165,6 +167,18 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye return (1.0f / iter) * seamlessness; } + if (layer.vote == LayerVoteType::ExplicitExact) { + const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate); + if (mSupportsFrameRateOverride) { + // 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. + return divider > 0; + } + + return divider == 1; + } + return 0; } @@ -199,21 +213,34 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequir int maxVoteLayers = 0; int explicitDefaultVoteLayers = 0; int explicitExactOrMultipleVoteLayers = 0; + int explicitExact = 0; float maxExplicitWeight = 0; int seamedLayers = 0; for (const auto& layer : layers) { - if (layer.vote == LayerVoteType::NoVote) { - noVoteLayers++; - } else if (layer.vote == LayerVoteType::Min) { - minVoteLayers++; - } else if (layer.vote == LayerVoteType::Max) { - maxVoteLayers++; - } else if (layer.vote == LayerVoteType::ExplicitDefault) { - explicitDefaultVoteLayers++; - maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); - } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) { - explicitExactOrMultipleVoteLayers++; - maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); + switch (layer.vote) { + case LayerVoteType::NoVote: + noVoteLayers++; + break; + case LayerVoteType::Min: + minVoteLayers++; + break; + case LayerVoteType::Max: + maxVoteLayers++; + break; + case LayerVoteType::ExplicitDefault: + explicitDefaultVoteLayers++; + maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); + break; + case LayerVoteType::ExplicitExactOrMultiple: + explicitExactOrMultipleVoteLayers++; + maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); + break; + case LayerVoteType::ExplicitExact: + explicitExact++; + maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); + break; + case LayerVoteType::Heuristic: + break; } if (layer.seamlessness == Seamlessness::SeamedAndSeamless) { @@ -221,8 +248,8 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequir } } - const bool hasExplicitVoteLayers = - explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0; + const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 || + explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0; // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've // selected a refresh rate to see if we should apply touch boost. @@ -318,7 +345,9 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequir bool inPrimaryRange = scores[i].refreshRate->inPolicy(policy->primaryRange.min, policy->primaryRange.max); if ((primaryRangeIsSingleRate || !inPrimaryRange) && - !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) { + !(layer.focused && + (layer.vote == LayerVoteType::ExplicitDefault || + layer.vote == LayerVoteType::ExplicitExact))) { // Only focused layers with ExplicitDefault frame rate settings are allowed to score // refresh rates outside the primary range. continue; @@ -358,7 +387,8 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequir // actually increase the refresh rate over the normal selection. const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(); - if (globalSignals.touch && explicitDefaultVoteLayers == 0 && + bool touchBoostForExplicitExact = explicitExact == 0 || mSupportsFrameRateOverride; + if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact && bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) { setTouchConsidered(); ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str()); @@ -412,7 +442,7 @@ std::vector<RefreshRateScore> initializeScoresForAllRefreshRates( } RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides( - const std::vector<LayerRequirement>& layers, Fps displayFrameRate) const { + const std::vector<LayerRequirement>& layers, Fps displayFrameRate, bool touch) const { ATRACE_CALL(); if (!mSupportsFrameRateOverride) return {}; @@ -423,6 +453,17 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr groupLayersByUid(layers); UidToFrameRateOverride frameRateOverrides; for (const auto& [uid, layersWithSameUid] : layersByUid) { + // Layers with ExplicitExactOrMultiple expect touch boost + const bool hasExplicitExactOrMultiple = + std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(), + [](const auto& layer) { + return layer->vote == LayerVoteType::ExplicitExactOrMultiple; + }); + + if (touch && hasExplicitExactOrMultiple) { + continue; + } + for (auto& score : scores) { score.score = 0; } @@ -433,7 +474,8 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr } LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault && - layer->vote != LayerVoteType::ExplicitExactOrMultiple); + layer->vote != LayerVoteType::ExplicitExactOrMultiple && + layer->vote != LayerVoteType::ExplicitExact); for (RefreshRateScore& score : scores) { const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate, /*isSeamlessSwitch*/ true); @@ -559,8 +601,10 @@ void RefreshRateConfigs::setCurrentConfigId(DisplayModeId configId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } -RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId) - : mKnownFrameRates(constructKnownFrameRates(configs)) { +RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, + bool enableFrameRateOverride) + : mKnownFrameRates(constructKnownFrameRates(configs)), + mEnableFrameRateOverride(enableFrameRateOverride) { updateDisplayConfigs(configs, currentConfigId); } @@ -589,7 +633,7 @@ void RefreshRateConfigs::updateDisplayConfigs(const DisplayModes& configs, mMaxSupportedRefreshRate = sortedConfigs.back(); mSupportsFrameRateOverride = false; - if (android::sysprop::enable_frame_rate_override(true)) { + if (mEnableFrameRateOverride) { for (const auto& config1 : sortedConfigs) { for (const auto& config2 : sortedConfigs) { if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) { @@ -826,4 +870,4 @@ void RefreshRateConfigs::dump(std::string& result) const { } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index ef193ca787..36fbbad4d8 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -208,8 +208,11 @@ public: Heuristic, // Specific refresh rate that was calculated by platform using a heuristic ExplicitDefault, // Specific refresh rate that was provided by the app with Default // compatibility - ExplicitExactOrMultiple // Specific refresh rate that was provided by the app with - // ExactOrMultiple compatibility + ExplicitExactOrMultiple, // Specific refresh rate that was provided by the app with + // ExactOrMultiple compatibility + ExplicitExact, // Specific refresh rate that was provided by the app with + // Exact compatibility + }; // Captures the layer requirements for a refresh rate. This will be used to determine the @@ -295,7 +298,8 @@ public: // Returns a known frame rate that is the closest to frameRate Fps findClosestKnownFrameRate(Fps frameRate) const; - RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId); + RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, + bool enableFrameRateOverride = false); void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig) EXCLUDES(mLock); @@ -324,10 +328,15 @@ public: // Returns a divider for the current refresh rate int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock); - // Returns the frame rate override for each uid using UidToFrameRateOverride = std::map<uid_t, Fps>; + // Returns the frame rate override for each uid. + // + // @param layers list of visible layers + // @param displayFrameRate the display frame rate + // @param touch whether touch timer is active (i.e. user touched the screen recently) UidToFrameRateOverride getFrameRateOverrides(const std::vector<LayerRequirement>& layers, - Fps displayFrameRate) const EXCLUDES(mLock); + Fps displayFrameRate, bool touch) const + EXCLUDES(mLock); void dump(std::string& result) const EXCLUDES(mLock); @@ -407,6 +416,7 @@ private: // from based on the closest value. const std::vector<Fps> mKnownFrameRates; + const bool mEnableFrameRateOverride; bool mSupportsFrameRateOverride; }; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 588b83d774..d8612098ec 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -763,17 +763,11 @@ bool Scheduler::updateFrameRateOverrides( return false; } - if (consideredSignals.touch) { - std::lock_guard lock(mFrameRateOverridesMutex); - const bool changed = !mFrameRateOverridesByContent.empty(); - mFrameRateOverridesByContent.clear(); - return changed; - } - if (!consideredSignals.idle) { const auto frameRateOverrides = mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements, - displayRefreshRate); + displayRefreshRate, + consideredSignals.touch); std::lock_guard lock(mFrameRateOverridesMutex); if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(), frameRateOverrides.begin(), frameRateOverrides.end(), diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a51659681..c1fabf8322 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2920,7 +2920,9 @@ void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) { auto currentConfig = getHwComposer().getActiveMode(primaryDisplayId)->getId(); const auto modes = getHwComposer().getModes(primaryDisplayId); - mRefreshRateConfigs = std::make_unique<scheduler::RefreshRateConfigs>(modes, currentConfig); + mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(modes, currentConfig, + android::sysprop::enable_frame_rate_override(true)); const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig); mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(), @@ -3873,7 +3875,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eFrameRateChanged) { if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility, - "SurfaceFlinger::setClientStateLocked") && + "SurfaceFlinger::setClientStateLocked", privileged) && layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate), Layer::FrameRate::convertCompatibility( s.frameRateCompatibility), diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 0a747ab7e3..738ded18ac 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -1506,6 +1506,89 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { } } +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact) { + auto refreshRateConfigs = + std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 0.5f}}; + auto& explicitExactLayer = layers[0]; + auto& explicitExactOrMultipleLayer = layers[1]; + + explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; + explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60); + + explicitExactLayer.vote = LayerVoteType::ExplicitExact; + explicitExactLayer.name = "ExplicitExact"; + explicitExactLayer.desiredRefreshRate = Fps(30); + + EXPECT_EQ(mExpected30Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + EXPECT_EQ(mExpected30Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); + + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120); + explicitExactLayer.desiredRefreshRate = Fps(60); + EXPECT_EQ(mExpected60Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(72); + EXPECT_EQ(mExpected72Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(90); + EXPECT_EQ(mExpected90Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(120); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); +} + +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) { + auto refreshRateConfigs = + std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60, + /*enableFrameRateOverride=*/true); + + auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 0.5f}}; + auto& explicitExactLayer = layers[0]; + auto& explicitExactOrMultipleLayer = layers[1]; + + explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; + explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60); + + explicitExactLayer.vote = LayerVoteType::ExplicitExact; + explicitExactLayer.name = "ExplicitExact"; + explicitExactLayer.desiredRefreshRate = Fps(30); + + EXPECT_EQ(mExpected60Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); + + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120); + explicitExactLayer.desiredRefreshRate = Fps(60); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(72); + EXPECT_EQ(mExpected72Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(90); + EXPECT_EQ(mExpected90Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(120); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); +} + TEST_F(RefreshRateConfigsTest, testComparisonOperator) { EXPECT_TRUE(mExpected60Config < mExpected90Config); EXPECT_FALSE(mExpected60Config < mExpected60Config); @@ -1537,7 +1620,7 @@ TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) { EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction()); } -TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { +TEST_F(RefreshRateConfigsTest, getRefreshRateDivider) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/HWC_CONFIG_ID_30); @@ -1562,57 +1645,66 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f))); } -TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_noLayers) { +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/ HWC_CONFIG_ID_120); auto layers = std::vector<LayerRequirement>{}; - ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)).empty()); + ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false) + .empty()); } TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_60on120) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/ - HWC_CONFIG_ID_120); + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}}; layers[0].name = "Test layer"; layers[0].ownerUid = 1234; layers[0].desiredRefreshRate = Fps(60.0f); layers[0].vote = LayerVoteType::ExplicitDefault; - auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[0].vote = LayerVoteType::NoVote; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Min; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Max; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Heuristic; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); } -TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_twoUids) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/ - HWC_CONFIG_ID_120); + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); auto layers = std::vector<LayerRequirement>{ LayerRequirement{.ownerUid = 1234, .weight = 1.0f}, @@ -1626,7 +1718,8 @@ TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { layers[1].name = "Test layer 5678"; layers[1].desiredRefreshRate = Fps(30.0f); layers[1].vote = LayerVoteType::ExplicitDefault; - auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(2, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); @@ -1635,13 +1728,66 @@ TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { ASSERT_EQ(30.0f, frameRateOverrides.at(5678).getValue()); layers[1].vote = LayerVoteType::Heuristic; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[1].ownerUid = 1234; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_TRUE(frameRateOverrides.empty()); +} + +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) { + auto refreshRateConfigs = + std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/ + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); + + auto layers = std::vector<LayerRequirement>{ + LayerRequirement{.ownerUid = 1234, .weight = 1.0f}, + }; + + layers[0].name = "Test layer"; + layers[0].desiredRefreshRate = Fps(60.0f); + layers[0].vote = LayerVoteType::ExplicitDefault; + + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + layers[0].vote = LayerVoteType::ExplicitExact; + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); ASSERT_TRUE(frameRateOverrides.empty()); } diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index c8f4cb4c19..e060df2420 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -473,5 +473,20 @@ INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest, std::make_shared<EffectLayerFactory>()), PrintToStringParamName); +TEST_F(SetFrameRateTest, ValidateFrameRate) { + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "", /*privileged=*/true)); + + EXPECT_FALSE(ValidateFrameRate(-1, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_FALSE( + ValidateFrameRate(1.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_FALSE( + ValidateFrameRate(0.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + + EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "")); +} + } // namespace } // namespace android |