diff options
author | 2021-01-07 17:56:08 -0800 | |
---|---|---|
committer | 2021-01-25 15:54:37 -0800 | |
commit | 35018763c0098ce802d51408f77b13633128041c (patch) | |
tree | 82bb49bd09e322e3887ed9219114f54a4d8facab | |
parent | 20dcde8e35b003a82e4c14d39c76f93a16ec6e9d (diff) |
SurfaceFlinger: handle high refresh rate deny list
Add visibility to SurfaceFlinger into the high refresh rate deny list
and let SurfaceFlinger handle it. Previously WM was setting the
preferredDisplayModeId on the denied app's window. The old way prevented
SurfaceFlinger to use the frame rate override feature as it didn't
know that a specific app is causing the refresh rate spec to be limited.
With this change, SurfaceFlinger will limit the display refresh rate based
on the high refresh rate deny list, and if possible, will use the frame
rate override feature to change the display rate to a multiple, allowing
other animations to be smooth while the denied app remains in the low
refresh rate.
Bug: 170502573
Test: SF unit tests
Change-Id: Idc8a5fe6bc12dbd949ad5e09ff50e339ffaeac36
-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 |