Loading services/surfaceflinger/RefreshRateOverlay.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -233,8 +233,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { mCurrentFps = fps.getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), Loading @@ -258,8 +258,9 @@ void RefreshRateOverlay::onInvalidate() { void RefreshRateOverlay::reset() { mBufferCache.clear(); mLowFps = mFlinger.mRefreshRateConfigs->getMinRefreshRate().getFps().getIntValue(); mHighFps = mFlinger.mRefreshRateConfigs->getMaxRefreshRate().getFps().getIntValue(); const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange(); mLowFps = range.min.getIntValue(); mHighFps = range.max.getIntValue(); } } // namespace android Loading services/surfaceflinger/RefreshRateOverlay.h +2 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ #include <ui/Size.h> #include <utils/StrongPointer.h> #include "Scheduler/RefreshRateConfigs.h" #include "Fps.h" namespace android { Loading @@ -34,14 +34,12 @@ class IGraphicBufferProducer; class Layer; class SurfaceFlinger; using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger&, bool showSpinner); void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); void changeRefreshRate(const Fps&); void onInvalidate(); void reset(); Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +59 −39 Original line number Diff line number Diff line Loading @@ -39,6 +39,26 @@ std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, f toString(layer.seamlessness).c_str(), to_string(layer.desiredRefreshRate).c_str()); } std::vector<Fps> constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } } // namespace using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; Loading Loading @@ -154,8 +174,8 @@ struct RefreshRateScore { float score; }; const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, GlobalSignals* outSignalsConsidered) const { ATRACE_CALL(); ALOGV("getBestRefreshRate %zu layers", layers.size()); Loading Loading @@ -469,9 +489,20 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) return bestRefreshRate; } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { std::optional<Fps> RefreshRateConfigs::onKernelTimerChanged( std::optional<HwcConfigIndexType> desiredActiveConfigId, bool timerExpired) const { std::lock_guard lock(mLock); return getMinRefreshRateByPolicyLocked(); const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId) : *mCurrentRefreshRate; const auto& min = *mMinSupportedRefreshRate; if (current != min) { const auto& refreshRate = timerExpired ? min : current; return refreshRate.getFps(); } return {}; } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { Loading @@ -487,7 +518,7 @@ const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.front(); } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getMaxRefreshRateByPolicyLocked(); } Loading @@ -506,12 +537,12 @@ const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.back(); } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const { std::lock_guard lock(mLock); return *mCurrentRefreshRate; } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getCurrentRefreshRateByPolicyLocked(); } Loading @@ -533,16 +564,23 @@ RefreshRateConfigs::RefreshRateConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) : mKnownFrameRates(constructKnownFrameRates(configs)) { updateDisplayConfigs(configs, currentConfigId); } void RefreshRateConfigs::updateDisplayConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { std::lock_guard lock(mLock); LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentConfigId.value() < 0); LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); mRefreshRates.clear(); for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast<size_t>(configId.value())); const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod()); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, Fps::fromPeriodNsecs( config->getVsyncPeriod()), std::make_unique<RefreshRate>(configId, config, fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); Loading @@ -550,7 +588,7 @@ RefreshRateConfigs::RefreshRateConfigs( } std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentConfigId; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); Loading @@ -570,7 +608,7 @@ RefreshRateConfigs::RefreshRateConfigs( constructAvailableRefreshRates(); } bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const { // defaultConfig must be a valid config, and within the given refresh rate range. auto iter = mRefreshRates.find(policy.defaultConfig); if (iter == mRefreshRates.end()) { Loading @@ -588,7 +626,7 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { std::lock_guard lock(mLock); if (!isPolicyValid(policy)) { if (!isPolicyValidLocked(policy)) { ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str()); return BAD_VALUE; } Loading @@ -603,7 +641,7 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) { std::lock_guard lock(mLock); if (policy && !isPolicyValid(*policy)) { if (policy && !isPolicyValidLocked(*policy)) { return BAD_VALUE; } Policy previousPolicy = *getCurrentPolicyLocked(); Loading Loading @@ -639,14 +677,14 @@ bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const { return false; } void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::getSortedRefreshRateListLocked( const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate, std::vector<const RefreshRate*>* outRefreshRates) { outRefreshRates->clear(); outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { if (shouldAddRefreshRate(*refreshRate)) { ALOGV("getSortedRefreshRateList: config %d added to list policy", ALOGV("getSortedRefreshRateListLocked: config %d added to list policy", refreshRate->configId.value()); outRefreshRates->push_back(refreshRate.get()); } Loading @@ -672,8 +710,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, std::vector<const RefreshRate*>* outRefreshRates) { getSortedRefreshRateList( std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock) { getSortedRefreshRateListLocked( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { const auto& hwcConfig = refreshRate.hwcConfig; Loading Loading @@ -706,25 +745,6 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { &mAppRequestRefreshRates); } std::vector<Fps> RefreshRateConfigs::constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) { return *mKnownFrameRates.begin(); Loading @@ -744,7 +764,7 @@ Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const { std::lock_guard lock(mLock); const auto& deviceMin = getMinRefreshRate(); const auto& deviceMin = *mMinSupportedRefreshRate; const auto& minByPolicy = getMinRefreshRateByPolicyLocked(); const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked(); Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.h +54 −52 Original line number Diff line number Diff line Loading @@ -68,8 +68,6 @@ public: std::shared_ptr<const HWC2::Display::Config> config, Fps fps, ConstructorTag) : configId(configId), hwcConfig(config), fps(std::move(fps)) {} RefreshRate(const RefreshRate&) = delete; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } Loading Loading @@ -111,27 +109,26 @@ public: using AllRefreshRatesMapType = std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>; struct Policy { private: static constexpr int kAllowGroupSwitchingDefault = false; public: struct Range { struct FpsRange { Fps min{0.0f}; Fps max{std::numeric_limits<float>::max()}; bool operator==(const Range& other) const { bool operator==(const FpsRange& other) const { return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); } bool operator!=(const Range& other) const { return !(*this == other); } bool operator!=(const FpsRange& other) const { return !(*this == other); } std::string toString() const { return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str()); return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str()); } }; struct Policy { private: static constexpr int kAllowGroupSwitchingDefault = false; public: // The default config, used to ensure we only initiate display config switches within the // same config group as defaultConfigId's group. HwcConfigIndexType defaultConfig; Loading @@ -140,29 +137,29 @@ public: // The primary refresh rate range represents display manager's general guidance on the // display configs we'll consider when switching refresh rates. Unless we get an explicit // signal from an app, we should stay within this range. Range primaryRange; FpsRange primaryRange; // The app request refresh rate range allows us to consider more display configs 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. Range appRequestRange; FpsRange appRequestRange; Policy() = default; Policy(HwcConfigIndexType defaultConfig, const Range& range) Policy(HwcConfigIndexType defaultConfig, const FpsRange& range) : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {} Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& range) Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const FpsRange& range) : Policy(defaultConfig, allowGroupSwitching, range, range) {} Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange, const Range& appRequestRange) Policy(HwcConfigIndexType defaultConfig, const FpsRange& primaryRange, const FpsRange& appRequestRange) : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& primaryRange, const Range& appRequestRange) const FpsRange& primaryRange, const FpsRange& appRequestRange) : defaultConfig(defaultConfig), allowGroupSwitching(allowGroupSwitching), primaryRange(primaryRange), Loading Loading @@ -258,35 +255,35 @@ public: // globalSignals - global state of touch and idle // outSignalsConsidered - An output param that tells the caller whether the refresh rate was // chosen based on touch boost and/or idle timer. const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers, RefreshRate getBestRefreshRate(const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, GlobalSignals* outSignalsConsidered = nullptr) const EXCLUDES(mLock); // Returns the lowest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } // Returns the lowest refresh rate according to the current policy. May change at runtime. Only // uses the primary range, not the app request range. const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()}; } // Returns the highest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } std::optional<Fps> onKernelTimerChanged(std::optional<HwcConfigIndexType> desiredActiveConfigId, bool timerExpired) const EXCLUDES(mLock); // Returns the highest refresh rate according to the current policy. May change at runtime. Only // uses the primary range, not the app request range. const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); RefreshRate getMaxRefreshRateByPolicy() const EXCLUDES(mLock); // Returns the current refresh rate const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock); RefreshRate getCurrentRefreshRate() const EXCLUDES(mLock); // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by // the policy. const RefreshRate& getCurrentRefreshRateByPolicy() const; RefreshRate getCurrentRefreshRateByPolicy() const; // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at // Returns the refresh rate that corresponds to a HwcConfigIndexType. This may change at // runtime. const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed. RefreshRate getRefreshRateFromConfigId(HwcConfigIndexType configId) const EXCLUDES(mLock) { std::lock_guard lock(mLock); return *mRefreshRates.at(configId); }; Loading @@ -302,10 +299,17 @@ public: RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); void updateDisplayConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfig) EXCLUDES(mLock); // Returns whether switching configs (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only // differ in resolution. bool canSwitch() const { return mRefreshRates.size() > 1; } bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return mRefreshRates.size() > 1; } // Class to enumerate options around toggling the kernel timer on and off. We have an option // for no change to avoid extra calls to kernel. Loading Loading @@ -334,12 +338,10 @@ private: friend class RefreshRateConfigsTest; void constructAvailableRefreshRates() REQUIRES(mLock); static std::vector<Fps> constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs); void getSortedRefreshRateList( void getSortedRefreshRateListLocked( const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate, std::vector<const RefreshRate*>* outRefreshRates); std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock); // Returns the refresh rate with the highest score in the collection specified from begin // to end. If there are more than one with the same highest refresh rate, the first one is Loading @@ -364,7 +366,7 @@ private: const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValid(const Policy& policy); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Return the display refresh rate divider to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the Loading @@ -376,9 +378,9 @@ private: float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&, bool isSeamlessSwitch) const REQUIRES(mLock); // The list of refresh rates, indexed by display config ID. This must not change after this // The list of refresh rates, indexed by display config ID. This may change after this // object is initialized. AllRefreshRatesMapType mRefreshRates; AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod // (the first element is the lowest refresh rate). Loading @@ -398,9 +400,9 @@ private: std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. const RefreshRate* mMinSupportedRefreshRate; const RefreshRate* mMaxSupportedRefreshRate; // This may change at runtime. const RefreshRate* mMinSupportedRefreshRate GUARDED_BY(mLock); const RefreshRate* mMaxSupportedRefreshRate GUARDED_BY(mLock); mutable std::mutex mLock; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -612,7 +612,7 @@ void Scheduler::chooseRefreshRateForContent() { mFeatures.contentRequirements = summary; newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals); auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); Loading @@ -629,7 +629,7 @@ void Scheduler::chooseRefreshRateForContent() { } } if (frameRateChanged) { auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, consideredSignals.idle ? ConfigEvent::None : ConfigEvent::Changed); Loading Loading
services/surfaceflinger/RefreshRateOverlay.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -233,8 +233,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { mCurrentFps = fps.getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), Loading @@ -258,8 +258,9 @@ void RefreshRateOverlay::onInvalidate() { void RefreshRateOverlay::reset() { mBufferCache.clear(); mLowFps = mFlinger.mRefreshRateConfigs->getMinRefreshRate().getFps().getIntValue(); mHighFps = mFlinger.mRefreshRateConfigs->getMaxRefreshRate().getFps().getIntValue(); const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange(); mLowFps = range.min.getIntValue(); mHighFps = range.max.getIntValue(); } } // namespace android Loading
services/surfaceflinger/RefreshRateOverlay.h +2 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ #include <ui/Size.h> #include <utils/StrongPointer.h> #include "Scheduler/RefreshRateConfigs.h" #include "Fps.h" namespace android { Loading @@ -34,14 +34,12 @@ class IGraphicBufferProducer; class Layer; class SurfaceFlinger; using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger&, bool showSpinner); void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); void changeRefreshRate(const Fps&); void onInvalidate(); void reset(); Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +59 −39 Original line number Diff line number Diff line Loading @@ -39,6 +39,26 @@ std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, f toString(layer.seamlessness).c_str(), to_string(layer.desiredRefreshRate).c_str()); } std::vector<Fps> constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } } // namespace using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; Loading Loading @@ -154,8 +174,8 @@ struct RefreshRateScore { float score; }; const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, GlobalSignals* outSignalsConsidered) const { ATRACE_CALL(); ALOGV("getBestRefreshRate %zu layers", layers.size()); Loading Loading @@ -469,9 +489,20 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) return bestRefreshRate; } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { std::optional<Fps> RefreshRateConfigs::onKernelTimerChanged( std::optional<HwcConfigIndexType> desiredActiveConfigId, bool timerExpired) const { std::lock_guard lock(mLock); return getMinRefreshRateByPolicyLocked(); const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId) : *mCurrentRefreshRate; const auto& min = *mMinSupportedRefreshRate; if (current != min) { const auto& refreshRate = timerExpired ? min : current; return refreshRate.getFps(); } return {}; } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { Loading @@ -487,7 +518,7 @@ const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.front(); } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getMaxRefreshRateByPolicyLocked(); } Loading @@ -506,12 +537,12 @@ const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.back(); } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const { std::lock_guard lock(mLock); return *mCurrentRefreshRate; } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getCurrentRefreshRateByPolicyLocked(); } Loading @@ -533,16 +564,23 @@ RefreshRateConfigs::RefreshRateConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) : mKnownFrameRates(constructKnownFrameRates(configs)) { updateDisplayConfigs(configs, currentConfigId); } void RefreshRateConfigs::updateDisplayConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { std::lock_guard lock(mLock); LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentConfigId.value() < 0); LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); mRefreshRates.clear(); for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast<size_t>(configId.value())); const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod()); mRefreshRates.emplace(configId, std::make_unique<RefreshRate>(configId, config, Fps::fromPeriodNsecs( config->getVsyncPeriod()), std::make_unique<RefreshRate>(configId, config, fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); Loading @@ -550,7 +588,7 @@ RefreshRateConfigs::RefreshRateConfigs( } std::vector<const RefreshRate*> sortedConfigs; getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentConfigId; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); Loading @@ -570,7 +608,7 @@ RefreshRateConfigs::RefreshRateConfigs( constructAvailableRefreshRates(); } bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const { // defaultConfig must be a valid config, and within the given refresh rate range. auto iter = mRefreshRates.find(policy.defaultConfig); if (iter == mRefreshRates.end()) { Loading @@ -588,7 +626,7 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { std::lock_guard lock(mLock); if (!isPolicyValid(policy)) { if (!isPolicyValidLocked(policy)) { ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str()); return BAD_VALUE; } Loading @@ -603,7 +641,7 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { status_t RefreshRateConfigs::setOverridePolicy(const std::optional<Policy>& policy) { std::lock_guard lock(mLock); if (policy && !isPolicyValid(*policy)) { if (policy && !isPolicyValidLocked(*policy)) { return BAD_VALUE; } Policy previousPolicy = *getCurrentPolicyLocked(); Loading Loading @@ -639,14 +677,14 @@ bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const { return false; } void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::getSortedRefreshRateListLocked( const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate, std::vector<const RefreshRate*>* outRefreshRates) { outRefreshRates->clear(); outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { if (shouldAddRefreshRate(*refreshRate)) { ALOGV("getSortedRefreshRateList: config %d added to list policy", ALOGV("getSortedRefreshRateListLocked: config %d added to list policy", refreshRate->configId.value()); outRefreshRates->push_back(refreshRate.get()); } Loading @@ -672,8 +710,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, std::vector<const RefreshRate*>* outRefreshRates) { getSortedRefreshRateList( std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock) { getSortedRefreshRateListLocked( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { const auto& hwcConfig = refreshRate.hwcConfig; Loading Loading @@ -706,25 +745,6 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { &mAppRequestRefreshRates); } std::vector<Fps> RefreshRateConfigs::constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) { std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) { return *mKnownFrameRates.begin(); Loading @@ -744,7 +764,7 @@ Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const { std::lock_guard lock(mLock); const auto& deviceMin = getMinRefreshRate(); const auto& deviceMin = *mMinSupportedRefreshRate; const auto& minByPolicy = getMinRefreshRateByPolicyLocked(); const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked(); Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +54 −52 Original line number Diff line number Diff line Loading @@ -68,8 +68,6 @@ public: std::shared_ptr<const HWC2::Display::Config> config, Fps fps, ConstructorTag) : configId(configId), hwcConfig(config), fps(std::move(fps)) {} RefreshRate(const RefreshRate&) = delete; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } Loading Loading @@ -111,27 +109,26 @@ public: using AllRefreshRatesMapType = std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>; struct Policy { private: static constexpr int kAllowGroupSwitchingDefault = false; public: struct Range { struct FpsRange { Fps min{0.0f}; Fps max{std::numeric_limits<float>::max()}; bool operator==(const Range& other) const { bool operator==(const FpsRange& other) const { return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); } bool operator!=(const Range& other) const { return !(*this == other); } bool operator!=(const FpsRange& other) const { return !(*this == other); } std::string toString() const { return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str()); return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str()); } }; struct Policy { private: static constexpr int kAllowGroupSwitchingDefault = false; public: // The default config, used to ensure we only initiate display config switches within the // same config group as defaultConfigId's group. HwcConfigIndexType defaultConfig; Loading @@ -140,29 +137,29 @@ public: // The primary refresh rate range represents display manager's general guidance on the // display configs we'll consider when switching refresh rates. Unless we get an explicit // signal from an app, we should stay within this range. Range primaryRange; FpsRange primaryRange; // The app request refresh rate range allows us to consider more display configs 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. Range appRequestRange; FpsRange appRequestRange; Policy() = default; Policy(HwcConfigIndexType defaultConfig, const Range& range) Policy(HwcConfigIndexType defaultConfig, const FpsRange& range) : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {} Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& range) Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const FpsRange& range) : Policy(defaultConfig, allowGroupSwitching, range, range) {} Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange, const Range& appRequestRange) Policy(HwcConfigIndexType defaultConfig, const FpsRange& primaryRange, const FpsRange& appRequestRange) : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& primaryRange, const Range& appRequestRange) const FpsRange& primaryRange, const FpsRange& appRequestRange) : defaultConfig(defaultConfig), allowGroupSwitching(allowGroupSwitching), primaryRange(primaryRange), Loading Loading @@ -258,35 +255,35 @@ public: // globalSignals - global state of touch and idle // outSignalsConsidered - An output param that tells the caller whether the refresh rate was // chosen based on touch boost and/or idle timer. const RefreshRate& getBestRefreshRate(const std::vector<LayerRequirement>& layers, RefreshRate getBestRefreshRate(const std::vector<LayerRequirement>& layers, const GlobalSignals& globalSignals, GlobalSignals* outSignalsConsidered = nullptr) const EXCLUDES(mLock); // Returns the lowest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } // Returns the lowest refresh rate according to the current policy. May change at runtime. Only // uses the primary range, not the app request range. const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()}; } // Returns the highest refresh rate supported by the device. This won't change at runtime. const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } std::optional<Fps> onKernelTimerChanged(std::optional<HwcConfigIndexType> desiredActiveConfigId, bool timerExpired) const EXCLUDES(mLock); // Returns the highest refresh rate according to the current policy. May change at runtime. Only // uses the primary range, not the app request range. const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); RefreshRate getMaxRefreshRateByPolicy() const EXCLUDES(mLock); // Returns the current refresh rate const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock); RefreshRate getCurrentRefreshRate() const EXCLUDES(mLock); // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by // the policy. const RefreshRate& getCurrentRefreshRateByPolicy() const; RefreshRate getCurrentRefreshRateByPolicy() const; // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at // Returns the refresh rate that corresponds to a HwcConfigIndexType. This may change at // runtime. const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed. RefreshRate getRefreshRateFromConfigId(HwcConfigIndexType configId) const EXCLUDES(mLock) { std::lock_guard lock(mLock); return *mRefreshRates.at(configId); }; Loading @@ -302,10 +299,17 @@ public: RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); void updateDisplayConfigs( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfig) EXCLUDES(mLock); // Returns whether switching configs (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only // differ in resolution. bool canSwitch() const { return mRefreshRates.size() > 1; } bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); return mRefreshRates.size() > 1; } // Class to enumerate options around toggling the kernel timer on and off. We have an option // for no change to avoid extra calls to kernel. Loading Loading @@ -334,12 +338,10 @@ private: friend class RefreshRateConfigsTest; void constructAvailableRefreshRates() REQUIRES(mLock); static std::vector<Fps> constructKnownFrameRates( const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs); void getSortedRefreshRateList( void getSortedRefreshRateListLocked( const std::function<bool(const RefreshRate&)>& shouldAddRefreshRate, std::vector<const RefreshRate*>* outRefreshRates); std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock); // Returns the refresh rate with the highest score in the collection specified from begin // to end. If there are more than one with the same highest refresh rate, the first one is Loading @@ -364,7 +366,7 @@ private: const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValid(const Policy& policy); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Return the display refresh rate divider to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the Loading @@ -376,9 +378,9 @@ private: float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&, bool isSeamlessSwitch) const REQUIRES(mLock); // The list of refresh rates, indexed by display config ID. This must not change after this // The list of refresh rates, indexed by display config ID. This may change after this // object is initialized. AllRefreshRatesMapType mRefreshRates; AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod // (the first element is the lowest refresh rate). Loading @@ -398,9 +400,9 @@ private: std::optional<Policy> mOverridePolicy GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. const RefreshRate* mMinSupportedRefreshRate; const RefreshRate* mMaxSupportedRefreshRate; // This may change at runtime. const RefreshRate* mMinSupportedRefreshRate GUARDED_BY(mLock); const RefreshRate* mMaxSupportedRefreshRate GUARDED_BY(mLock); mutable std::mutex mLock; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -612,7 +612,7 @@ void Scheduler::chooseRefreshRateForContent() { mFeatures.contentRequirements = summary; newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals); auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); Loading @@ -629,7 +629,7 @@ void Scheduler::chooseRefreshRateForContent() { } } if (frameRateChanged) { auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, consideredSignals.idle ? ConfigEvent::None : ConfigEvent::Changed); Loading