Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -216,13 +216,21 @@ const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { std::lock_guard lock(mLock); if (!mRefreshRateSwitching) { return *mCurrentRefreshRate; } else { return *mAvailableRefreshRates.front(); } } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); if (!mRefreshRateSwitching) { return *mCurrentRefreshRate; } else { return *mAvailableRefreshRates.back(); } } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { std::lock_guard lock(mLock); Loading @@ -234,14 +242,18 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { mCurrentRefreshRate = &mRefreshRates.at(configId); } RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) { RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) : mRefreshRateSwitching(refreshRateSwitching) { init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( bool refreshRateSwitching, const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { HwcConfigIndexType currentConfigId) : mRefreshRateSwitching(refreshRateSwitching) { std::vector<InputConfig> inputConfigs; for (size_t configId = 0; configId < configs.size(); ++configId) { auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup()); Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.h +8 −2 Original line number Diff line number Diff line Loading @@ -94,6 +94,9 @@ public: // Returns true if config is allowed by the current policy. bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock); // Returns true if this device is doing refresh rate switching. This won't change at runtime. bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } // Describes the different options the layer voted for refresh rate enum class LayerVoteType { NoVote, // Doesn't care about the refresh rate Loading Loading @@ -164,9 +167,10 @@ public: nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(const std::vector<InputConfig>& configs, RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, RefreshRateConfigs(bool refreshRateSwitching, const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); private: Loading Loading @@ -204,6 +208,8 @@ private: const RefreshRate* mMinSupportedRefreshRate; const RefreshRate* mMaxSupportedRefreshRate; const bool mRefreshRateSwitching; mutable std::mutex mLock; }; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +20 −27 Original line number Diff line number Diff line Loading @@ -530,6 +530,8 @@ void Scheduler::dump(std::string& result) const { using base::StringAppendF; const char* const states[] = {"off", "on"}; const bool supported = mRefreshRateConfigs.refreshRateSwitchingSupported(); StringAppendF(&result, "+ Refresh rate switching: %s\n", states[supported]); StringAppendF(&result, "+ Content detection: %s\n", states[mLayerHistory != nullptr]); StringAppendF(&result, "+ Idle timer: %s\n", Loading Loading @@ -573,44 +575,35 @@ bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() { } HwcConfigIndexType Scheduler::calculateRefreshRateType() { // This block of the code checks whether any layers used the SetFrameRate API. If they have, // their request should be honored regardless of whether the device has refresh rate switching // turned off. if (layerHistoryHasClientSpecifiedFrameRate()) { if (!mUseContentDetectionV2) { return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements) .configId; } else { return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements) .configId; } if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { return mRefreshRateConfigs.getCurrentRefreshRate().configId; } // If the layer history doesn't have the frame rate specified, use the old path. NOTE: // if we remove the kernel idle timer, and use our internal idle timer, this code will have to // be refactored. if (!layerHistoryHasClientSpecifiedFrameRate()) { // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (mDisplayPowerTimer && (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset)) { if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // As long as touch is active we want to be in performance mode if (mTouchTimer && mFeatures.touch == TouchState::Active) { if (mFeatures.touch == TouchState::Active) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // If timer has expired as it means there is no new content on the screen if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) { if (mFeatures.idleTimer == TimerState::Expired) { return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } } if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps. // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { // TODO(b/148428554): Be careful to not always call this. return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } Loading services/surfaceflinger/SurfaceFlinger.cpp +27 −13 Original line number Diff line number Diff line Loading @@ -555,6 +555,12 @@ void SurfaceFlinger::bootFinished() readPersistentProperties(); mBootStage = BootStage::FINISHED; if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { // set the refresh rate according to the policy const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); Loading Loading @@ -2713,7 +2719,8 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { auto currentConfig = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(primaryDisplayId)); mRefreshRateConfigs = std::make_unique<scheduler::RefreshRateConfigs>(getHwComposer().getConfigs( std::make_unique<scheduler::RefreshRateConfigs>(refresh_rate_switching(false), getHwComposer().getConfigs( primaryDisplayId), currentConfig); mRefreshRateStats = Loading Loading @@ -5693,19 +5700,26 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDe mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, display->getActiveConfig(), vsyncPeriod); if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { auto configId = mScheduler->getPreferredConfigId(); auto preferredRefreshRate = configId ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig); : mRefreshRateConfigs->getMinRefreshRateByPolicy(); ALOGV("trying to switch to Scheduler preferred config %d (%s)", preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str()); if (isDisplayConfigAllowed(preferredRefreshRate.configId)) { ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value()); setDesiredActiveConfig({preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value()); setDesiredActiveConfig( {preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); } else { // Set the highest allowed config setDesiredActiveConfig({mRefreshRateConfigs->getMaxRefreshRateByPolicy().configId, Scheduler::ConfigEvent::Changed}); } } else { LOG_ALWAYS_FATAL("Desired config not allowed: %d", preferredRefreshRate.configId.value()); ALOGV("switching to config %d", defaultConfig.value()); setDesiredActiveConfig({defaultConfig, Scheduler::ConfigEvent::Changed}); } return NO_ERROR; Loading services/surfaceflinger/SurfaceFlingerProperties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -226,6 +226,14 @@ int64_t color_space_agnostic_dataspace(Dataspace defaultValue) { return static_cast<int64_t>(defaultValue); } bool refresh_rate_switching(bool defaultValue) { auto temp = SurfaceFlingerProperties::refresh_rate_switching(); if (temp.has_value()) { return *temp; } return defaultValue; } int32_t set_idle_timer_ms(int32_t defaultValue) { auto temp = SurfaceFlingerProperties::set_idle_timer_ms(); if (temp.has_value()) { Loading Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -216,13 +216,21 @@ const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { std::lock_guard lock(mLock); if (!mRefreshRateSwitching) { return *mCurrentRefreshRate; } else { return *mAvailableRefreshRates.front(); } } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); if (!mRefreshRateSwitching) { return *mCurrentRefreshRate; } else { return *mAvailableRefreshRates.back(); } } const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { std::lock_guard lock(mLock); Loading @@ -234,14 +242,18 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { mCurrentRefreshRate = &mRefreshRates.at(configId); } RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) { RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig) : mRefreshRateSwitching(refreshRateSwitching) { init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( bool refreshRateSwitching, const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId) { HwcConfigIndexType currentConfigId) : mRefreshRateSwitching(refreshRateSwitching) { std::vector<InputConfig> inputConfigs; for (size_t configId = 0; configId < configs.size(); ++configId) { auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup()); Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +8 −2 Original line number Diff line number Diff line Loading @@ -94,6 +94,9 @@ public: // Returns true if config is allowed by the current policy. bool isConfigAllowed(HwcConfigIndexType config) const EXCLUDES(mLock); // Returns true if this device is doing refresh rate switching. This won't change at runtime. bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } // Describes the different options the layer voted for refresh rate enum class LayerVoteType { NoVote, // Doesn't care about the refresh rate Loading Loading @@ -164,9 +167,10 @@ public: nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(const std::vector<InputConfig>& configs, RefreshRateConfigs(bool refreshRateSwitching, const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, RefreshRateConfigs(bool refreshRateSwitching, const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs, HwcConfigIndexType currentConfigId); private: Loading Loading @@ -204,6 +208,8 @@ private: const RefreshRate* mMinSupportedRefreshRate; const RefreshRate* mMaxSupportedRefreshRate; const bool mRefreshRateSwitching; mutable std::mutex mLock; }; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +20 −27 Original line number Diff line number Diff line Loading @@ -530,6 +530,8 @@ void Scheduler::dump(std::string& result) const { using base::StringAppendF; const char* const states[] = {"off", "on"}; const bool supported = mRefreshRateConfigs.refreshRateSwitchingSupported(); StringAppendF(&result, "+ Refresh rate switching: %s\n", states[supported]); StringAppendF(&result, "+ Content detection: %s\n", states[mLayerHistory != nullptr]); StringAppendF(&result, "+ Idle timer: %s\n", Loading Loading @@ -573,44 +575,35 @@ bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() { } HwcConfigIndexType Scheduler::calculateRefreshRateType() { // This block of the code checks whether any layers used the SetFrameRate API. If they have, // their request should be honored regardless of whether the device has refresh rate switching // turned off. if (layerHistoryHasClientSpecifiedFrameRate()) { if (!mUseContentDetectionV2) { return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements) .configId; } else { return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements) .configId; } if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { return mRefreshRateConfigs.getCurrentRefreshRate().configId; } // If the layer history doesn't have the frame rate specified, use the old path. NOTE: // if we remove the kernel idle timer, and use our internal idle timer, this code will have to // be refactored. if (!layerHistoryHasClientSpecifiedFrameRate()) { // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (mDisplayPowerTimer && (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset)) { if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // As long as touch is active we want to be in performance mode if (mTouchTimer && mFeatures.touch == TouchState::Active) { if (mFeatures.touch == TouchState::Active) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // If timer has expired as it means there is no new content on the screen if (mIdleTimer && mFeatures.idleTimer == TimerState::Expired) { if (mFeatures.idleTimer == TimerState::Expired) { return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } } if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps. // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { // TODO(b/148428554): Be careful to not always call this. return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } Loading
services/surfaceflinger/SurfaceFlinger.cpp +27 −13 Original line number Diff line number Diff line Loading @@ -555,6 +555,12 @@ void SurfaceFlinger::bootFinished() readPersistentProperties(); mBootStage = BootStage::FINISHED; if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { // set the refresh rate according to the policy const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); Loading Loading @@ -2713,7 +2719,8 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { auto currentConfig = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(primaryDisplayId)); mRefreshRateConfigs = std::make_unique<scheduler::RefreshRateConfigs>(getHwComposer().getConfigs( std::make_unique<scheduler::RefreshRateConfigs>(refresh_rate_switching(false), getHwComposer().getConfigs( primaryDisplayId), currentConfig); mRefreshRateStats = Loading Loading @@ -5693,19 +5700,26 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDe mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, display->getActiveConfig(), vsyncPeriod); if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { auto configId = mScheduler->getPreferredConfigId(); auto preferredRefreshRate = configId ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig); : mRefreshRateConfigs->getMinRefreshRateByPolicy(); ALOGV("trying to switch to Scheduler preferred config %d (%s)", preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str()); if (isDisplayConfigAllowed(preferredRefreshRate.configId)) { ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value()); setDesiredActiveConfig({preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); ALOGV("switching to Scheduler preferred config %d", preferredRefreshRate.configId.value()); setDesiredActiveConfig( {preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); } else { // Set the highest allowed config setDesiredActiveConfig({mRefreshRateConfigs->getMaxRefreshRateByPolicy().configId, Scheduler::ConfigEvent::Changed}); } } else { LOG_ALWAYS_FATAL("Desired config not allowed: %d", preferredRefreshRate.configId.value()); ALOGV("switching to config %d", defaultConfig.value()); setDesiredActiveConfig({defaultConfig, Scheduler::ConfigEvent::Changed}); } return NO_ERROR; Loading
services/surfaceflinger/SurfaceFlingerProperties.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -226,6 +226,14 @@ int64_t color_space_agnostic_dataspace(Dataspace defaultValue) { return static_cast<int64_t>(defaultValue); } bool refresh_rate_switching(bool defaultValue) { auto temp = SurfaceFlingerProperties::refresh_rate_switching(); if (temp.has_value()) { return *temp; } return defaultValue; } int32_t set_idle_timer_ms(int32_t defaultValue) { auto temp = SurfaceFlingerProperties::set_idle_timer_ms(); if (temp.has_value()) { Loading