diff options
23 files changed, 573 insertions, 351 deletions
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9c2ce0f242..9e175ec42e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2375,42 +2375,22 @@ status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display, return NAME_NOT_FOUND; } -status_t SurfaceComposerClient::setDesiredDisplayModeSpecs( - const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, - float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +status_t SurfaceComposerClient::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs& specs) { binder::Status status = - ComposerServiceAIDL::getComposerService() - ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching, - primaryRefreshRateMin, primaryRefreshRateMax, - appRequestRefreshRateMin, - appRequestRefreshRateMax); + ComposerServiceAIDL::getComposerService()->setDesiredDisplayModeSpecs(displayToken, + specs); return statusTFromBinderStatus(status); } status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, - ui::DisplayModeId* outDefaultMode, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { - if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || - !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { + gui::DisplayModeSpecs* outSpecs) { + if (!outSpecs) { return BAD_VALUE; } - gui::DisplayModeSpecs specs; binder::Status status = ComposerServiceAIDL::getComposerService()->getDesiredDisplayModeSpecs(displayToken, - &specs); - if (status.isOk()) { - *outDefaultMode = specs.defaultMode; - *outAllowGroupSwitching = specs.allowGroupSwitching; - *outPrimaryRefreshRateMin = specs.primaryRefreshRateMin; - *outPrimaryRefreshRateMax = specs.primaryRefreshRateMax; - *outAppRequestRefreshRateMin = specs.appRequestRefreshRateMin; - *outAppRequestRefreshRateMax = specs.appRequestRefreshRateMax; - } + outSpecs); return statusTFromBinderStatus(status); } diff --git a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl index fb4fcdf8e8..af138c7539 100644 --- a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl +++ b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl @@ -18,10 +18,58 @@ package android.gui; /** @hide */ parcelable DisplayModeSpecs { + /** + * Defines the refresh rates ranges that should be used by SF. + */ + parcelable RefreshRateRanges { + /** + * Defines a range of refresh rates. + */ + parcelable RefreshRateRange { + float min; + float max; + } + + /** + * The range of refresh rates that the display should run at. + */ + RefreshRateRange physical; + + /** + * The range of refresh rates that apps should render at. + */ + RefreshRateRange render; + } + + /** + * Base mode ID. This is what system defaults to for all other settings, or + * if the refresh rate range is not available. + */ int defaultMode; + + /** + * If true this will allow switching between modes in different display configuration + * groups. This way the user may see visual interruptions when the display mode changes. + */ + boolean allowGroupSwitching; - float primaryRefreshRateMin; - float primaryRefreshRateMax; - float appRequestRefreshRateMin; - float appRequestRefreshRateMax; + + /** + * The primary physical and render refresh rate ranges represent DisplayManager's general + * guidance on the display modes SurfaceFlinger will consider when switching refresh + * rates and scheduling the frame rate. Unless SurfaceFlinger has a specific reason to do + * otherwise, it will stay within this range. + */ + RefreshRateRanges primaryRanges; + + /** + * The app request physical and render refresh rate ranges allow SurfaceFlinger to consider + * more display modes when switching refresh rates. Although SurfaceFlinger will + * generally stay within the primary range, specific considerations, such as layer frame + * rate settings specified via the setFrameRate() API, may cause SurfaceFlinger to go + * outside the primary range. SurfaceFlinger never goes outside the app request range. + * The app request range will be greater than or equal to the primary refresh rate range, + * never smaller. + */ + RefreshRateRanges appRequestRanges; } diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index 92d9e7799c..40410fb59e 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -327,25 +327,9 @@ interface ISurfaceComposer { /** * Sets the refresh rate boundaries for the display. * - * The primary refresh rate range represents display manager's general guidance on the display - * modes we'll consider when switching refresh rates. Unless we get an explicit signal from an - * app, we should stay within this range. - * - * The app request refresh rate range allows us to consider more display modes when switching - * refresh rates. Although we should generally stay within the primary range, specific - * considerations, such as layer frame rate settings specified via the setFrameRate() api, may - * cause us to go outside the primary range. We never go outside the app request range. The app - * request range will be greater than or equal to the primary refresh rate range, never smaller. - * - * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider - * switching between. Only modes with a mode group and resolution matching defaultMode - * will be considered for switching. The defaultMode corresponds to an ID of mode in the list - * of supported modes returned from getDynamicDisplayInfo(). - */ - void setDesiredDisplayModeSpecs( - IBinder displayToken, int defaultMode, - boolean allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, - float appRequestRefreshRateMin, float appRequestRefreshRateMax); + * @see DisplayModeSpecs.aidl for details. + */ + void setDesiredDisplayModeSpecs(IBinder displayToken, in DisplayModeSpecs specs); DisplayModeSpecs getDesiredDisplayModeSpecs(IBinder displayToken); diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h index 202517067f..9d1ee8f65b 100644 --- a/libs/gui/fuzzer/libgui_fuzzer_utils.h +++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h @@ -127,9 +127,7 @@ public: MOCK_METHOD(binder::Status, removeTunnelModeEnabledListener, (const sp<gui::ITunnelModeEnabledListener>&), (override)); MOCK_METHOD(binder::Status, setDesiredDisplayModeSpecs, - (const sp<IBinder>&, int32_t, bool, float, float, float, - float appRequestRefreshRateMax), - (override)); + (const sp<IBinder>&, const gui::DisplayModeSpecs&), (override)); MOCK_METHOD(binder::Status, getDesiredDisplayModeSpecs, (const sp<IBinder>&, gui::DisplayModeSpecs*), (override)); MOCK_METHOD(binder::Status, getDisplayBrightnessSupport, (const sp<IBinder>&, bool*), diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp index eecbe0fe21..57720dd513 100644 --- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp +++ b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp @@ -123,10 +123,37 @@ private: sp<SurfaceControl> makeSurfaceControl(); BlurRegion getBlurRegion(); void fuzzOnPullAtom(); + gui::DisplayModeSpecs getDisplayModeSpecs(); FuzzedDataProvider mFdp; }; +gui::DisplayModeSpecs SurfaceComposerClientFuzzer::getDisplayModeSpecs() { + const auto getRefreshRateRange = [&] { + gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange range; + range.min = mFdp.ConsumeFloatingPoint<float>(); + range.max = mFdp.ConsumeFloatingPoint<float>(); + return range; + }; + + const auto getRefreshRateRanges = [&] { + gui::DisplayModeSpecs::RefreshRateRanges ranges; + ranges.physical = getRefreshRateRange(); + ranges.render = getRefreshRateRange(); + return ranges; + }; + + String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str()); + sp<IBinder> displayToken = + SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/); + gui::DisplayModeSpecs specs; + specs.defaultMode = mFdp.ConsumeIntegral<int32_t>(); + specs.allowGroupSwitching = mFdp.ConsumeBool(); + specs.primaryRanges = getRefreshRateRanges(); + specs.appRequestRanges = getRefreshRateRanges(); + return specs; +} + BlurRegion SurfaceComposerClientFuzzer::getBlurRegion() { int32_t left = mFdp.ConsumeIntegral<int32_t>(); int32_t right = mFdp.ConsumeIntegral<int32_t>(); @@ -247,12 +274,7 @@ void SurfaceComposerClientFuzzer::invokeSurfaceComposerClient() { String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str()); sp<IBinder> displayToken = SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/); - SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, mFdp.ConsumeIntegral<int32_t>(), - mFdp.ConsumeBool() /*allowGroupSwitching*/, - mFdp.ConsumeFloatingPoint<float>(), - mFdp.ConsumeFloatingPoint<float>(), - mFdp.ConsumeFloatingPoint<float>(), - mFdp.ConsumeFloatingPoint<float>()); + SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, getDisplayModeSpecs()); ui::ColorMode colorMode = mFdp.PickValueInArray(kColormodes); SurfaceComposerClient::setActiveColorMode(displayToken, colorMode); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index c450e85857..2038f1477a 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -159,18 +159,11 @@ public: static status_t getActiveDisplayMode(const sp<IBinder>& display, ui::DisplayMode*); // Sets the refresh rate boundaries for the display. - static status_t setDesiredDisplayModeSpecs( - const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, - bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, - float appRequestRefreshRateMin, float appRequestRefreshRateMax); + static status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs&); // Gets the refresh rate boundaries for the display. static status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, - ui::DisplayModeId* outDefaultMode, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax); + gui::DisplayModeSpecs*); // Get the coordinates of the display's native color primaries static status_t getDisplayNativePrimaries(const sp<IBinder>& display, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 346b686466..67c669ddb7 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -920,16 +920,12 @@ public: } binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, - int32_t /*defaultMode*/, bool /*allowGroupSwitching*/, - float /*primaryRefreshRateMin*/, - float /*primaryRefreshRateMax*/, - float /*appRequestRefreshRateMin*/, - float /*appRequestRefreshRateMax*/) override { + const gui::DisplayModeSpecs&) override { return binder::Status::ok(); } binder::Status getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, - gui::DisplayModeSpecs* /*outSpecs*/) override { + gui::DisplayModeSpecs*) override { return binder::Status::ok(); } diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index 40af6ee575..c913891b62 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -30,6 +30,7 @@ #include <ftl/enum.h> #include <ftl/fake_guard.h> #include <ftl/match.h> +#include <ftl/unit.h> #include <utils/Trace.h> #include "../SurfaceFlingerProperties.h" @@ -105,7 +106,7 @@ std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes, Fi return sortedModes; } -bool canModesSupportFrameRateOverride(const std::vector<DisplayModeIterator>& sortedModes) { +bool shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator>& sortedModes) { for (const auto it1 : sortedModes) { const auto& mode1 = it1->second; for (const auto it2 : sortedModes) { @@ -164,9 +165,10 @@ struct RefreshRateSelector::RefreshRateScoreComparator { std::string RefreshRateSelector::Policy::toString() const { return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s" - ", primaryRange=%s, appRequestRange=%s}", + ", primaryRanges=%s, appRequestRanges=%s}", defaultMode.value(), allowGroupSwitching ? "true" : "false", - to_string(primaryRange).c_str(), to_string(appRequestRange).c_str()); + to_string(primaryRanges).c_str(), + to_string(appRequestRanges).c_str()); } std::pair<nsecs_t, nsecs_t> RefreshRateSelector::getDisplayFrames(nsecs_t layerPeriod, @@ -263,7 +265,7 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay if (layer.vote == LayerVoteType::ExplicitExact) { const int divisor = getFrameRateDivisor(refreshRate, layer.desiredRefreshRate); - if (mSupportsFrameRateOverrideByContent) { + if (supportsFrameRateOverrideByContent()) { // 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. @@ -381,7 +383,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq // move out the of range if layers explicitly request a different refresh // rate. const bool primaryRangeIsSingleRate = - isApproxEqual(policy->primaryRange.min, policy->primaryRange.max); + isApproxEqual(policy->primaryRanges.physical.min, policy->primaryRanges.physical.max); if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) { ALOGV("Idle"); @@ -450,7 +452,7 @@ auto RefreshRateSelector::getRankedRefreshRatesLocked(const std::vector<LayerReq continue; } - const bool inPrimaryRange = policy->primaryRange.includes(mode->getFps()); + const bool inPrimaryRange = policy->primaryRanges.physical.includes(mode->getFps()); if ((primaryRangeIsSingleRate || !inPrimaryRange) && !(layer.focused && (layer.vote == LayerVoteType::ExplicitDefault || @@ -578,7 +580,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 (mSupportsFrameRateOverrideByContent) { + if (supportsFrameRateOverrideByContent()) { // Enable touch boost if there are other layers besides exact return explicitExact + noVoteLayers != layers.size(); } else { @@ -647,23 +649,43 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme GlobalSignals globalSignals) const -> UidToFrameRateOverride { ATRACE_CALL(); - ALOGV("%s: %zu layers", __func__, layers.size()); std::lock_guard lock(mLock); - std::vector<RefreshRateScore> scores; - scores.reserve(mDisplayModes.size()); - - for (auto it = mDisplayModes.begin(); it != mDisplayModes.end(); ++it) { - scores.emplace_back(RefreshRateScore{it, 0.0f}); + // 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); + } } - std::sort(scores.begin(), scores.end(), [](const auto& lhs, const auto& rhs) { - const auto& mode1 = lhs.modeIt->second; - const auto& mode2 = rhs.modeIt->second; - return isStrictlyLess(mode1->getFps(), mode2->getFps()); - }); + 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); + + using fps_approx_ops::operator/; + const unsigned numMultiples = displayRefreshRate / minFrameRate; + + std::vector<std::pair<Fps, float>> scoredFrameRates; + scoredFrameRates.reserve(numMultiples); + + for (unsigned n = numMultiples; n > 0; n--) { + const Fps divisor = displayRefreshRate / n; + if (mConfig.enableFrameRateOverride == + Config::FrameRateOverride::EnabledForNativeRefreshRates && + !supportedDisplayRefreshRates.contains(divisor)) { + continue; + } + + if (policyPtr->appRequestRanges.render.includes(divisor)) { + ALOGV("%s: adding %s as a potential frame rate", __func__, to_string(divisor).c_str()); + scoredFrameRates.emplace_back(divisor, 0); + } + } const auto layersByUid = groupLayersByUid(layers); UidToFrameRateOverride frameRateOverrides; @@ -679,7 +701,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme continue; } - for (auto& [_, score, _1] : scores) { + for (auto& [_, score] : scoredFrameRates) { score = 0; } @@ -691,36 +713,33 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault && layer->vote != LayerVoteType::ExplicitExactOrMultiple && layer->vote != LayerVoteType::ExplicitExact); - for (auto& [modeIt, score, _] : scores) { + for (auto& [fps, score] : scoredFrameRates) { constexpr bool isSeamlessSwitch = true; - const auto layerScore = calculateLayerScoreLocked(*layer, modeIt->second->getFps(), - isSeamlessSwitch); + const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch); score += layer->weight * layerScore; } } - // We just care about the refresh rates which are a divisor of the - // display refresh rate - const auto it = std::remove_if(scores.begin(), scores.end(), [&](RefreshRateScore score) { - const auto& [id, mode] = *score.modeIt; - return getFrameRateDivisor(displayRefreshRate, mode->getFps()) == 0; - }); - scores.erase(it, scores.end()); - // If we never scored any layers, we don't have a preferred frame rate - if (std::all_of(scores.begin(), scores.end(), - [](RefreshRateScore score) { return score.overallScore == 0; })) { + if (std::all_of(scoredFrameRates.begin(), scoredFrameRates.end(), + [](const auto& scoredFrameRate) { + const auto [_, score] = scoredFrameRate; + return score == 0; + })) { continue; } // Now that we scored all the refresh rates we need to pick the lowest refresh rate // that got the highest score. - const DisplayModePtr& bestRefreshRate = - std::min_element(scores.begin(), scores.end(), - RefreshRateScoreComparator{.refreshRateOrder = - RefreshRateOrder::Ascending}) - ->modeIt->second; - frameRateOverrides.emplace(uid, bestRefreshRate->getFps()); + const auto [overrideFps, _] = + *std::max_element(scoredFrameRates.begin(), scoredFrameRates.end(), + [](const auto& lhsPair, const auto& rhsPair) { + const float lhs = lhsPair.second; + const float rhs = rhsPair.second; + return lhs < rhs && !ScoredRefreshRate::scoresEqual(lhs, rhs); + }); + ALOGV("%s: overriding to %s for uid=%d", __func__, to_string(overrideFps).c_str(), uid); + frameRateOverrides.emplace(uid, overrideFps); } return frameRateOverrides; @@ -893,8 +912,17 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a mDisplayManagerPolicy = {}; mDisplayManagerPolicy.defaultMode = activeModeId; - mSupportsFrameRateOverrideByContent = - mConfig.enableFrameRateOverride && canModesSupportFrameRateOverride(sortedModes); + mFrameRateOverrideConfig = [&] { + switch (mConfig.enableFrameRateOverride) { + case Config::FrameRateOverride::Disabled: + case Config::FrameRateOverride::Enabled: + return mConfig.enableFrameRateOverride; + case Config::FrameRateOverride::EnabledForNativeRefreshRates: + return shouldEnableFrameRateOverride(sortedModes) + ? Config::FrameRateOverride::EnabledForNativeRefreshRates + : Config::FrameRateOverride::Disabled; + } + }(); constructAvailableRefreshRates(); } @@ -902,7 +930,7 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const { // defaultMode must be a valid mode, and within the given refresh rate range. if (const auto mode = mDisplayModes.get(policy.defaultMode)) { - if (!policy.primaryRange.includes(mode->get()->getFps())) { + if (!policy.primaryRanges.physical.includes(mode->get()->getFps())) { ALOGE("Default mode is not in the primary range."); return false; } @@ -912,8 +940,8 @@ bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const { } using namespace fps_approx_ops; - return policy.appRequestRange.min <= policy.primaryRange.min && - policy.appRequestRange.max >= policy.primaryRange.max; + return policy.appRequestRanges.physical.min <= policy.primaryRanges.physical.min && + policy.appRequestRanges.physical.max >= policy.primaryRanges.physical.max; } auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyResult { @@ -1026,8 +1054,8 @@ void RefreshRateSelector::constructAvailableRefreshRates() { return modes; }; - mPrimaryRefreshRates = filterRefreshRates(policy->primaryRange, "primary"); - mAppRequestRefreshRates = filterRefreshRates(policy->appRequestRange, "app request"); + mPrimaryRefreshRates = filterRefreshRates(policy->primaryRanges.physical, "primary"); + mAppRequestRefreshRates = filterRefreshRates(policy->appRequestRanges.physical, "app request"); } Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const { @@ -1067,7 +1095,7 @@ auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction { if (minByPolicy == maxByPolicy) { // Turn on the timer when the min of the primary range is below the device min. if (const Policy* currentPolicy = getCurrentPolicyLocked(); - isApproxLess(currentPolicy->primaryRange.min, deviceMinFps)) { + isApproxLess(currentPolicy->primaryRanges.physical.min, deviceMinFps)) { return KernelIdleTimerAction::TurnOn; } return KernelIdleTimerAction::TurnOff; @@ -1127,7 +1155,7 @@ void RefreshRateSelector::dump(utils::Dumper& dumper) const { dumper.dump("overridePolicy"sv, currentPolicy.toString()); } - dumper.dump("supportsFrameRateOverrideByContent"sv, mSupportsFrameRateOverrideByContent); + dumper.dump("frameRateOverrideConfig"sv, *ftl::enum_name(mFrameRateOverrideConfig)); std::string idleTimer; if (mIdleTimer) { diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index bff16d3010..abbd30465a 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -67,40 +67,31 @@ public: DisplayModeId defaultMode; // Whether or not we switch mode groups to get the best frame rate. bool allowGroupSwitching = kAllowGroupSwitchingDefault; - // The primary refresh rate range represents display manager's general guidance on the - // display modes we'll consider when switching refresh rates. Unless we get an explicit - // signal from an app, we should stay within this range. - FpsRange primaryRange; - // The app request refresh rate range allows us to consider more display modes when - // switching refresh rates. Although we should generally stay within the primary range, - // specific considerations, such as layer frame rate settings specified via the - // setFrameRate() api, may cause us to go outside the primary range. We never go outside the - // app request range. The app request range will be greater than or equal to the primary - // refresh rate range, never smaller. - FpsRange appRequestRange; + // The primary refresh rate ranges. @see DisplayModeSpecs.aidl for details. + // TODO(b/257072060): use the render range when selecting SF render rate + // or the app override frame rate + FpsRanges primaryRanges; + // The app request refresh rate ranges. @see DisplayModeSpecs.aidl for details. + FpsRanges appRequestRanges; Policy() = default; - Policy(DisplayModeId defaultMode, FpsRange range) - : Policy(defaultMode, kAllowGroupSwitchingDefault, range, range) {} + Policy(DisplayModeId defaultMode, FpsRange range, + bool allowGroupSwitching = kAllowGroupSwitchingDefault) + : Policy(defaultMode, FpsRanges{range, range}, FpsRanges{range, range}, + allowGroupSwitching) {} - Policy(DisplayModeId defaultMode, bool allowGroupSwitching, FpsRange range) - : Policy(defaultMode, allowGroupSwitching, range, range) {} - - Policy(DisplayModeId defaultMode, FpsRange primaryRange, FpsRange appRequestRange) - : Policy(defaultMode, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} - - Policy(DisplayModeId defaultMode, bool allowGroupSwitching, FpsRange primaryRange, - FpsRange appRequestRange) + Policy(DisplayModeId defaultMode, FpsRanges primaryRanges, FpsRanges appRequestRanges, + bool allowGroupSwitching = kAllowGroupSwitchingDefault) : defaultMode(defaultMode), allowGroupSwitching(allowGroupSwitching), - primaryRange(primaryRange), - appRequestRange(appRequestRange) {} + primaryRanges(primaryRanges), + appRequestRanges(appRequestRanges) {} bool operator==(const Policy& other) const { using namespace fps_approx_ops; - return defaultMode == other.defaultMode && primaryRange == other.primaryRange && - appRequestRange == other.appRequestRange && + return defaultMode == other.defaultMode && primaryRanges == other.primaryRanges && + appRequestRanges == other.appRequestRanges && allowGroupSwitching == other.allowGroupSwitching; } @@ -260,7 +251,20 @@ public: // Configuration flags. struct Config { - bool enableFrameRateOverride = false; + enum class FrameRateOverride { + // Do not override the frame rate for an app + Disabled, + + // Override the frame rate for an app to a value which is also + // a display refresh rate + EnabledForNativeRefreshRates, + + // Override the frame rate for an app to any value + Enabled, + + ftl_last = Enabled + }; + FrameRateOverride enableFrameRateOverride = FrameRateOverride::Disabled; // Specifies the upper refresh rate threshold (inclusive) for layer vote types of multiple // or heuristic, such that refresh rates higher than this value will not be voted for. 0 if @@ -275,11 +279,12 @@ public: std::optional<KernelIdleTimerController> kernelIdleTimerController; }; - RefreshRateSelector(DisplayModes, DisplayModeId activeModeId, - Config config = {.enableFrameRateOverride = false, - .frameRateMultipleThreshold = 0, - .idleTimerTimeout = 0ms, - .kernelIdleTimerController = {}}); + RefreshRateSelector( + DisplayModes, DisplayModeId activeModeId, + Config config = {.enableFrameRateOverride = Config::FrameRateOverride::Disabled, + .frameRateMultipleThreshold = 0, + .idleTimerTimeout = 0ms, + .kernelIdleTimerController = {}}); RefreshRateSelector(const RefreshRateSelector&) = delete; RefreshRateSelector& operator=(const RefreshRateSelector&) = delete; @@ -302,7 +307,9 @@ public: // refresh rates. KernelIdleTimerAction getIdleTimerAction() const; - bool supportsFrameRateOverrideByContent() const { return mSupportsFrameRateOverrideByContent; } + bool supportsFrameRateOverrideByContent() const { + return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled; + } // 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 @@ -455,7 +462,7 @@ private: const std::vector<Fps> mKnownFrameRates; const Config mConfig; - bool mSupportsFrameRateOverrideByContent; + Config::FrameRateOverride mFrameRateOverrideConfig; struct GetRankedRefreshRatesCache { std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments; diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h index bd4f40989d..31b1d6901c 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h @@ -68,6 +68,15 @@ struct FpsRange { bool includes(Fps) const; }; +struct FpsRanges { + // The range of refresh rates that refers to the display mode setting. + FpsRange physical; + + // the range of frame rates that refers to the render rate, which is + // the rate that frames are swapped. + FpsRange render; +}; + static_assert(std::is_trivially_copyable_v<Fps>); constexpr Fps operator""_Hz(unsigned long long frequency) { @@ -127,8 +136,24 @@ inline bool operator!=(FpsRange lhs, FpsRange rhs) { return !(lhs == rhs); } +inline bool operator==(const FpsRanges& lhs, const FpsRanges& rhs) { + return lhs.physical == rhs.physical && lhs.render == rhs.render; +} + +inline bool operator!=(const FpsRanges& lhs, const FpsRanges& rhs) { + return !(lhs == rhs); +} + +inline unsigned operator/(Fps lhs, Fps rhs) { + return static_cast<unsigned>(std::ceil(lhs.getValue() / rhs.getValue())); +} + } // namespace fps_approx_ops +constexpr Fps operator/(Fps fps, unsigned divisor) { + return Fps::fromPeriodNsecs(fps.getPeriodNsecs() * static_cast<nsecs_t>(divisor)); +} + inline bool FpsRange::includes(Fps fps) const { using fps_approx_ops::operator<=; return min <= fps && fps <= max; @@ -151,4 +176,10 @@ inline std::string to_string(FpsRange range) { return base::StringPrintf("[%s, %s]", to_string(min).c_str(), to_string(max).c_str()); } +inline std::string to_string(FpsRanges ranges) { + const auto& [physical, render] = ranges; + return base::StringPrintf("{physical=%s, render=%s}", to_string(physical).c_str(), + to_string(render).c_str()); +} + } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 53066024d0..22a7ab0e17 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1132,8 +1132,8 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke display->refreshRateSelector().getCurrentPolicy().allowGroupSwitching; const scheduler::RefreshRateSelector::DisplayManagerPolicy policy{modeId, - allowGroupSwitching, - {fps, fps}}; + {fps, fps}, + allowGroupSwitching}; return setDesiredDisplayModeSpecsInternal(display, policy); }); @@ -2777,8 +2777,21 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const auto [kernelIdleTimerController, idleTimerTimeoutMs] = getKernelIdleTimerProperties(compositionDisplay->getId()); + const auto enableFrameRateOverride = [&] { + using Config = scheduler::RefreshRateSelector::Config; + if (!sysprop::enable_frame_rate_override(false)) { + return Config::FrameRateOverride::Disabled; + } + + if (sysprop::frame_rate_override_for_native_rates(true)) { + return Config::FrameRateOverride::EnabledForNativeRefreshRates; + } + + return Config::FrameRateOverride::Enabled; + }(); + scheduler::RefreshRateSelector::Config config = - {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false), + {.enableFrameRateOverride = enableFrameRateOverride, .frameRateMultipleThreshold = base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0), .idleTimerTimeout = idleTimerTimeoutMs, @@ -6649,10 +6662,33 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( return NO_ERROR; } -status_t SurfaceFlinger::setDesiredDisplayModeSpecs( - const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, - float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +namespace { +FpsRange translate(const gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange& aidlRange) { + return FpsRange{Fps::fromValue(aidlRange.min), Fps::fromValue(aidlRange.max)}; +} + +FpsRanges translate(const gui::DisplayModeSpecs::RefreshRateRanges& aidlRanges) { + return FpsRanges{translate(aidlRanges.physical), translate(aidlRanges.render)}; +} + +gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange translate(const FpsRange& range) { + gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange aidlRange; + aidlRange.min = range.min.getValue(); + aidlRange.max = range.max.getValue(); + return aidlRange; +} + +gui::DisplayModeSpecs::RefreshRateRanges translate(const FpsRanges& ranges) { + gui::DisplayModeSpecs::RefreshRateRanges aidlRanges; + aidlRanges.physical = translate(ranges.physical); + aidlRanges.render = translate(ranges.render); + return aidlRanges; +} + +} // namespace + +status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs& specs) { ATRACE_CALL(); if (!displayToken) { @@ -6670,12 +6706,8 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs( return INVALID_OPERATION; } else { using Policy = scheduler::RefreshRateSelector::DisplayManagerPolicy; - const Policy policy{DisplayModeId(defaultMode), - allowGroupSwitching, - {Fps::fromValue(primaryRefreshRateMin), - Fps::fromValue(primaryRefreshRateMax)}, - {Fps::fromValue(appRequestRefreshRateMin), - Fps::fromValue(appRequestRefreshRateMax)}}; + const Policy policy{DisplayModeId(specs.defaultMode), translate(specs.primaryRanges), + translate(specs.appRequestRanges), specs.allowGroupSwitching}; return setDesiredDisplayModeSpecsInternal(display, policy); } @@ -6685,16 +6717,10 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs( } status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, - ui::DisplayModeId* outDefaultMode, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { + gui::DisplayModeSpecs* outSpecs) { ATRACE_CALL(); - if (!displayToken || !outDefaultMode || !outPrimaryRefreshRateMin || - !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { + if (!displayToken || !outSpecs) { return BAD_VALUE; } @@ -6710,12 +6736,10 @@ status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp<IBinder>& displayTo scheduler::RefreshRateSelector::Policy policy = display->refreshRateSelector().getDisplayManagerPolicy(); - *outDefaultMode = policy.defaultMode.value(); - *outAllowGroupSwitching = policy.allowGroupSwitching; - *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); - *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); - *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue(); - *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue(); + outSpecs->defaultMode = policy.defaultMode.value(); + outSpecs->allowGroupSwitching = policy.allowGroupSwitching; + outSpecs->primaryRanges = translate(policy.primaryRanges); + outSpecs->appRequestRanges = translate(policy.appRequestRanges); return NO_ERROR; } @@ -7606,18 +7630,11 @@ binder::Status SurfaceComposerAIDL::removeTunnelModeEnabledListener( return binderStatusFromStatusT(status); } -binder::Status SurfaceComposerAIDL::setDesiredDisplayModeSpecs( - const sp<IBinder>& displayToken, int32_t defaultMode, bool allowGroupSwitching, - float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +binder::Status SurfaceComposerAIDL::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs& specs) { status_t status = checkAccessPermission(); if (status == OK) { - status = mFlinger->setDesiredDisplayModeSpecs(displayToken, - static_cast<ui::DisplayModeId>(defaultMode), - allowGroupSwitching, primaryRefreshRateMin, - primaryRefreshRateMax, - appRequestRefreshRateMin, - appRequestRefreshRateMax); + status = mFlinger->setDesiredDisplayModeSpecs(displayToken, specs); } return binderStatusFromStatusT(status); } @@ -7633,25 +7650,7 @@ binder::Status SurfaceComposerAIDL::getDesiredDisplayModeSpecs(const sp<IBinder> return binderStatusFromStatusT(status); } - ui::DisplayModeId displayModeId; - bool allowGroupSwitching; - float primaryRefreshRateMin; - float primaryRefreshRateMax; - float appRequestRefreshRateMin; - float appRequestRefreshRateMax; - status = mFlinger->getDesiredDisplayModeSpecs(displayToken, &displayModeId, - &allowGroupSwitching, &primaryRefreshRateMin, - &primaryRefreshRateMax, &appRequestRefreshRateMin, - &appRequestRefreshRateMax); - if (status == NO_ERROR) { - outSpecs->defaultMode = displayModeId; - outSpecs->allowGroupSwitching = allowGroupSwitching; - outSpecs->primaryRefreshRateMin = primaryRefreshRateMin; - outSpecs->primaryRefreshRateMax = primaryRefreshRateMax; - outSpecs->appRequestRefreshRateMin = appRequestRefreshRateMin; - outSpecs->appRequestRefreshRateMax = appRequestRefreshRateMax; - } - + status = mFlinger->getDesiredDisplayModeSpecs(displayToken, outSpecs); return binderStatusFromStatusT(status); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d2907626e0..c07e19ca6c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -551,17 +551,8 @@ private: status_t addTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& listener); status_t removeTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& listener); status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, - ui::DisplayModeId displayModeId, bool allowGroupSwitching, - float primaryRefreshRateMin, float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax); - status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, - ui::DisplayModeId* outDefaultMode, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax); + const gui::DisplayModeSpecs&); + status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, gui::DisplayModeSpecs*); status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const; status_t setDisplayBrightness(const sp<IBinder>& displayToken, const gui::DisplayBrightness& brightness); @@ -1451,11 +1442,8 @@ public: const sp<gui::ITunnelModeEnabledListener>& listener) override; binder::Status removeTunnelModeEnabledListener( const sp<gui::ITunnelModeEnabledListener>& listener) override; - binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, int32_t defaultMode, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) override; + binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs&) override; binder::Status getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, gui::DisplayModeSpecs* outSpecs) override; binder::Status getDisplayBrightnessSupport(const sp<IBinder>& displayToken, diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp index 20fa091730..c8c71dfad1 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.cpp +++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp @@ -367,6 +367,10 @@ bool enable_frame_rate_override(bool defaultValue) { return SurfaceFlingerProperties::enable_frame_rate_override().value_or(defaultValue); } +bool frame_rate_override_for_native_rates(bool defaultValue) { + return SurfaceFlingerProperties::frame_rate_override_for_native_rates().value_or(defaultValue); +} + bool enable_layer_caching(bool defaultValue) { return SurfaceFlingerProperties::enable_layer_caching().value_or(defaultValue); } diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h index 080feee686..5e316cfa0e 100644 --- a/services/surfaceflinger/SurfaceFlingerProperties.h +++ b/services/surfaceflinger/SurfaceFlingerProperties.h @@ -96,6 +96,8 @@ bool update_device_product_info_on_hotplug_reconnect(bool defaultValue); bool enable_frame_rate_override(bool defaultValue); +bool frame_rate_override_for_native_rates(bool defaultValue); + bool enable_layer_caching(bool defaultValue); bool enable_sdr_dimming(bool defaultValue); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 94de6e5274..9ba9b90b82 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -505,16 +505,8 @@ public: } void getDesiredDisplayModeSpecs(sp<IBinder> &display) { - ui::DisplayModeId outDefaultMode; - bool outAllowGroupSwitching; - float outPrimaryRefreshRateMin; - float outPrimaryRefreshRateMax; - float outAppRequestRefreshRateMin; - float outAppRequestRefreshRateMax; - mFlinger->getDesiredDisplayModeSpecs(display, &outDefaultMode, &outAllowGroupSwitching, - &outPrimaryRefreshRateMin, &outPrimaryRefreshRateMax, - &outAppRequestRefreshRateMin, - &outAppRequestRefreshRateMax); + gui::DisplayModeSpecs _; + mFlinger->getDesiredDisplayModeSpecs(display, &_); } void setVsyncConfig(FuzzedDataProvider *fdp) { diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index bcbe21a483..28da81ff50 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -445,6 +445,18 @@ prop { prop_name: "ro.surface_flinger.enable_frame_rate_override" } +# Limits the frame rate override feature (enable_frame_rate_override) to override the refresh rate +# to native display refresh rates only. Before introducing this flag, native display refresh rates +# was the default behvaiour. With this flag we can control which behaviour we want explicitly. +# This flag is intoruduced as a fail-safe machanism and planned to be defaulted to false. +prop { + api_name: "frame_rate_override_for_native_rates" + type: Boolean + scope: Public + access: Readonly + prop_name: "ro.surface_flinger.frame_rate_override_for_native_rates" +} + # Enables Layer Caching prop { api_name: "enable_layer_caching" diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt index 348a462038..0dfb80e5df 100644 --- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt @@ -61,6 +61,10 @@ props { prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays" } prop { + api_name: "frame_rate_override_for_native_rates" + prop_name: "ro.surface_flinger.frame_rate_override_for_native_rates" + } + prop { api_name: "has_HDR_display" prop_name: "ro.surface_flinger.has_HDR_display" } diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 4f04934d34..16768441f0 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -207,23 +207,12 @@ TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) { TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) { const auto display = getFirstDisplayToken(); - ui::DisplayModeId defaultMode; - bool allowGroupSwitching; - float primaryFpsMin; - float primaryFpsMax; - float appRequestFpsMin; - float appRequestFpsMax; - status_t res = - SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &defaultMode, - &allowGroupSwitching, &primaryFpsMin, - &primaryFpsMax, &appRequestFpsMin, - &appRequestFpsMax); + gui::DisplayModeSpecs specs; + status_t res = SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &specs); ASSERT_EQ(res, NO_ERROR); + gui::DisplayModeSpecs setSpecs; std::function<status_t()> condition = [=]() { - return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, defaultMode, - allowGroupSwitching, primaryFpsMin, - primaryFpsMax, appRequestFpsMin, - appRequestFpsMax); + return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, specs); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 02c934e576..10dae4636e 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -39,37 +39,19 @@ namespace android { */ class RefreshRateRangeTest : public ::testing::Test { private: - ui::DisplayModeId initialDefaultMode; - bool initialAllowGroupSwitching; - float initialPrimaryMin; - float initialPrimaryMax; - float initialAppRequestMin; - float initialAppRequestMax; + gui::DisplayModeSpecs mSpecs; protected: void SetUp() override { const auto ids = SurfaceComposerClient::getPhysicalDisplayIds(); ASSERT_FALSE(ids.empty()); mDisplayToken = SurfaceComposerClient::getPhysicalDisplayToken(ids.front()); - status_t res = - SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, - &initialDefaultMode, - &initialAllowGroupSwitching, - &initialPrimaryMin, - &initialPrimaryMax, - &initialAppRequestMin, - &initialAppRequestMax); + status_t res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &mSpecs); ASSERT_EQ(res, NO_ERROR); } void TearDown() override { - status_t res = - SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, initialDefaultMode, - initialAllowGroupSwitching, - initialPrimaryMin, - initialPrimaryMax, - initialAppRequestMin, - initialAppRequestMax); + status_t res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, mSpecs); ASSERT_EQ(res, NO_ERROR); } @@ -85,61 +67,39 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { ASSERT_EQ(res, NO_ERROR); ASSERT_GT(modes.size(), 0); + gui::DisplayModeSpecs setSpecs; + setSpecs.allowGroupSwitching = false; for (size_t i = 0; i < modes.size(); i++) { - res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, modes[i].id, false, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate, - modes[i].refreshRate); + setSpecs.defaultMode = modes[i].id; + setSpecs.primaryRanges.physical.min = modes[i].refreshRate; + setSpecs.primaryRanges.physical.max = modes[i].refreshRate; + setSpecs.primaryRanges.render = setSpecs.primaryRanges.physical; + setSpecs.appRequestRanges = setSpecs.primaryRanges; + res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, setSpecs); ASSERT_EQ(res, NO_ERROR); - ui::DisplayModeId defaultConfig; - bool allowGroupSwitching; - float primaryRefreshRateMin; - float primaryRefreshRateMax; - float appRequestRefreshRateMin; - float appRequestRefreshRateMax; - res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig, - &allowGroupSwitching, - &primaryRefreshRateMin, - &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + gui::DisplayModeSpecs getSpecs; + res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &getSpecs); ASSERT_EQ(res, NO_ERROR); - ASSERT_EQ(defaultConfig, i); - ASSERT_EQ(allowGroupSwitching, false); - ASSERT_EQ(primaryRefreshRateMin, modes[i].refreshRate); - ASSERT_EQ(primaryRefreshRateMax, modes[i].refreshRate); - ASSERT_EQ(appRequestRefreshRateMin, modes[i].refreshRate); - ASSERT_EQ(appRequestRefreshRateMax, modes[i].refreshRate); + ASSERT_EQ(setSpecs, getSpecs); } } void RefreshRateRangeTest::testSetAllowGroupSwitching(bool allowGroupSwitching) { - status_t res = - SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, 0, allowGroupSwitching, - 0.f, 90.f, 0.f, 90.f); + gui::DisplayModeSpecs setSpecs; + setSpecs.defaultMode = 0; + setSpecs.allowGroupSwitching = allowGroupSwitching; + setSpecs.primaryRanges.physical.min = 0; + setSpecs.primaryRanges.physical.max = 90; + setSpecs.primaryRanges.render = setSpecs.primaryRanges.physical; + setSpecs.appRequestRanges = setSpecs.primaryRanges; + + status_t res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, setSpecs); ASSERT_EQ(res, NO_ERROR); - ui::DisplayModeId defaultConfig; - bool newAllowGroupSwitching; - float primaryRefreshRateMin; - float primaryRefreshRateMax; - float appRequestRefreshRateMin; - float appRequestRefreshRateMax; - - res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig, - &newAllowGroupSwitching, - &primaryRefreshRateMin, - &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + gui::DisplayModeSpecs getSpecs; + res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &getSpecs); ASSERT_EQ(res, NO_ERROR); - ASSERT_EQ(defaultConfig, 0); - ASSERT_EQ(newAllowGroupSwitching, allowGroupSwitching); - ASSERT_EQ(primaryRefreshRateMin, 0.f); - ASSERT_EQ(primaryRefreshRateMax, 90.f); - ASSERT_EQ(appRequestRefreshRateMin, 0.f); - ASSERT_EQ(appRequestRefreshRateMax, 90.f); + ASSERT_EQ(setSpecs, getSpecs); } TEST_F(RefreshRateRangeTest, setAllowGroupSwitching) { diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index e7ae53c01a..cedb7eb6ee 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -37,6 +37,7 @@ namespace android::scheduler { namespace hal = android::hardware::graphics::composer::hal; +using Config = RefreshRateSelector::Config; using LayerRequirement = RefreshRateSelector::LayerRequirement; using LayerVoteType = RefreshRateSelector::LayerVoteType; using SetPolicyResult = RefreshRateSelector::SetPolicyResult; @@ -357,7 +358,7 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_noLayers) { constexpr bool kAllowGroupSwitching = true; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy( - {kModeId90, kAllowGroupSwitching, {0_Hz, 90_Hz}})); + {kModeId90, {0_Hz, 90_Hz}, kAllowGroupSwitching})); EXPECT_EQ(kMode90_G1, selector.getBestRefreshRate()); } } @@ -1105,7 +1106,7 @@ TEST_F(RefreshRateSelectorTest, getMinRefreshRatesByPolicyOutsideTheGroup) { TestableRefreshRateSelector selector(kModes_30_60_90, kModeId72); EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}, {30_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}})); const auto refreshRates = selector.rankRefreshRates(/*anchorGroupOpt*/ std::nullopt, RefreshRateOrder::Ascending); @@ -1126,7 +1127,7 @@ TEST_F(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { TestableRefreshRateSelector selector(kModes_30_60_90, kModeId72); EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}, {30_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}})); const auto refreshRates = selector.rankRefreshRates(/*anchorGroupOpt*/ std::nullopt, RefreshRateOrder::Descending); @@ -1351,8 +1352,10 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresTouchFlag) { TestableRefreshRateSelector selector(kModes_60_90, kModeId90); + constexpr FpsRange k90 = {90_Hz, 90_Hz}; + constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}, {60_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId90, {k90, k90}, {k60_90, k60_90}})); std::vector<LayerRequirement> layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -1373,8 +1376,11 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresIdleFlag) { TestableRefreshRateSelector selector(kModes_60_90, kModeId60); + constexpr FpsRange k60 = {60_Hz, 60_Hz}; + constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}, {60_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {k60, k60}, {k60_90, k60_90}})); std::vector<LayerRequirement> layers = {{.weight = 1.f}}; auto& lr = layers[0]; @@ -1513,8 +1519,11 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitFocusedLayers) { TestableRefreshRateSelector selector(kModes_60_90, kModeId90); + constexpr FpsRange k90 = {90_Hz, 90_Hz}; + constexpr FpsRange k60_90 = {60_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}, {60_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId90, {k90, k90}, {k60_90, k60_90}})); const auto [ranking, signals] = selector.getRankedRefreshRates({}, {}); EXPECT_EQ(ranking.front().modePtr, kMode90); @@ -1849,8 +1858,11 @@ TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { return selector.getBestRefreshRate(layers, {.touch = args.touch})->getId(); }; + constexpr FpsRange k30_60 = {30_Hz, 60_Hz}; + constexpr FpsRange k30_90 = {30_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {30_Hz, 60_Hz}, {30_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {k30_60, k30_60}, {k30_90, k30_90}})); EXPECT_EQ(kModeId60, selector.getBestRefreshRate()->getId()); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz)); @@ -1875,7 +1887,7 @@ TEST_F(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90_Hz, {.touch = true})); EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}, {60_Hz, 60_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}})); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz)); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::Min, 90_Hz)); @@ -1904,7 +1916,7 @@ TEST_F(RefreshRateSelectorTest, idle) { }; EXPECT_EQ(SetPolicyResult::Changed, - selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 90_Hz}, {60_Hz, 90_Hz}})); + selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 90_Hz}})); // Idle should be lower priority than touch boost. { @@ -2023,7 +2035,8 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExact) { TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) { TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId60, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = + Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; auto& explicitExactLayer = layers[0]; @@ -2089,7 +2102,8 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_WritesCache) { TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactTouchBoost) { TestableRefreshRateSelector selector(kModes_60_120, kModeId60, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = + Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}}; auto& explicitExactLayer = layers[0]; @@ -2114,7 +2128,8 @@ TEST_F(RefreshRateSelectorTest, getBestRefreshRate_ExplicitExactTouchBoost) { TEST_F(RefreshRateSelectorTest, getBestRefreshRate_FractionalRefreshRates_ExactAndDefault) { TestableRefreshRateSelector selector(kModes_24_25_30_50_60_Frac, kModeId60, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = + Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.weight = 0.5f}, {.weight = 0.5f}}; auto& explicitDefaultLayer = layers[0]; @@ -2308,7 +2323,7 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_noLayers) { TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_60on120) { RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.weight = 1.f}}; layers[0].name = "Test layer"; @@ -2346,7 +2361,7 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_60on120) { TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f}, {.ownerUid = 5678, .weight = 1.f}}; @@ -2379,7 +2394,7 @@ TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_twoUids) { TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_touch) { RefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, - {.enableFrameRateOverride = true}); + {.enableFrameRateOverride = Config::FrameRateOverride::Enabled}); std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f}}; layers[0].name = "Test layer"; @@ -2417,5 +2432,139 @@ 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}); + + 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(30_Hz, 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()); + + layers[0].vote = LayerVoteType::Heuristic; + 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)); + + 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)); + + 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()); + + layers[0].vote = LayerVoteType::Heuristic; + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_TRUE(frameRateOverrides.empty()); +} + +TEST_F(RefreshRateSelectorTest, getFrameRateOverrides_InPolicy) { + TestableRefreshRateSelector selector(kModes_30_60_72_90_120, kModeId120, + {.enableFrameRateOverride = + Config::FrameRateOverride::Enabled}); + + std::vector<LayerRequirement> layers = {{.weight = 1.f}}; + { + const FpsRange physical = {120_Hz, 120_Hz}; + const FpsRange render = {60_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {physical, render}, {physical, render}})); + } + + layers[0].name = "30Hz"; + 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()); + EXPECT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(60_Hz, frameRateOverrides.at(1234)); + + { + const FpsRange physical = {120_Hz, 120_Hz}; + const FpsRange render = {30_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {physical, render}, {physical, render}})); + } + + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + EXPECT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(30_Hz, frameRateOverrides.at(1234)); + + { + const FpsRange physical = {120_Hz, 120_Hz}; + const FpsRange render = {30_Hz, 30_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {physical, render}, {physical, render}})); + } + + layers[0].name = "60Hz"; + layers[0].ownerUid = 1234; + layers[0].desiredRefreshRate = 60_Hz; + layers[0].vote = LayerVoteType::ExplicitDefault; + + frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + EXPECT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(30_Hz, frameRateOverrides.at(1234)); +} + } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp index 4c25463e6e..05d0ebf773 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "mock/MockDisplayModeSpecs.h" #include "mock/MockEventThread.h" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -119,8 +120,9 @@ TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRe mFlinger.onActiveDisplayChanged(mDisplay); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(), - false, 0.f, 120.f, 0.f, 120.f); + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90.value(), false, 0, + 120)); ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value()); ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90); @@ -157,8 +159,9 @@ TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithoutRefres mFlinger.onActiveDisplayChanged(mDisplay); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(), - true, 0.f, 120.f, 0.f, 120.f); + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90.value(), true, 0, + 120)); ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value()); ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90); @@ -191,8 +194,9 @@ TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) { mFlinger.onActiveDisplayChanged(mDisplay); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90.value(), - false, 0.f, 120.f, 0.f, 120.f); + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90.value(), false, 0, + 120)); const VsyncPeriodChangeTimeline timeline{.refreshRequired = true}; EXPECT_CALL(*mComposer, @@ -202,8 +206,9 @@ TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) { mFlinger.commit(); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId120.value(), - false, 0.f, 180.f, 0.f, 180.f); + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId120.value(), false, 0, + 180)); ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value()); ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId120); @@ -232,8 +237,9 @@ TEST_F(DisplayModeSwitchingTest, changeResolution_OnActiveDisplay_WithoutRefresh mFlinger.onActiveDisplayChanged(mDisplay); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), kModeId90_4K.value(), - false, 0.f, 120.f, 0.f, 120.f); + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90_4K.value(), false, 0, + 120)); ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value()); ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90_4K); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 35c037c051..46eca69c6a 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -455,14 +455,9 @@ public: return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } - auto setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { - return mFlinger->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching, - primaryRefreshRateMin, primaryRefreshRateMax, - appRequestRefreshRateMin, - appRequestRefreshRateMax); + auto setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, + const gui::DisplayModeSpecs& specs) { + return mFlinger->setDesiredDisplayModeSpecs(displayToken, specs); } void onActiveDisplayChanged(const sp<DisplayDevice>& activeDisplay) { diff --git a/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h b/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h new file mode 100644 index 0000000000..a71e82cc75 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h @@ -0,0 +1,35 @@ +/* + * 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 <android/gui/DisplayModeSpecs.h> + +namespace android::mock { + +inline gui::DisplayModeSpecs createDisplayModeSpecs(int32_t defaultMode, bool allowGroupSwitching, + float minFps, float maxFps) { + gui::DisplayModeSpecs specs; + specs.defaultMode = defaultMode; + specs.allowGroupSwitching = allowGroupSwitching; + specs.primaryRanges.physical.min = minFps; + specs.primaryRanges.physical.max = maxFps; + specs.primaryRanges.render = specs.primaryRanges.physical; + specs.appRequestRanges = specs.primaryRanges; + return specs; +} + +} // namespace android::mock |