diff options
7 files changed, 70 insertions, 9 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index b876ccdc7e..1765d2d8f7 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -107,6 +107,12 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( return *mAvailableRefreshRates.back(); } + // If there are not layers, there is not content detection, so return the current + // refresh rate. + if (layers.empty()) { + return getCurrentRefreshRateByPolicyLocked(); + } + int noVoteLayers = 0; int minVoteLayers = 0; int maxVoteLayers = 0; @@ -272,6 +278,10 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { std::lock_guard lock(mLock); + return getCurrentRefreshRateByPolicyLocked(); +} + +const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() const { if (std::find(mAvailableRefreshRates.begin(), mAvailableRefreshRates.end(), mCurrentRefreshRate) != mAvailableRefreshRates.end()) { return *mCurrentRefreshRate; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 0b5c73c9b7..c8aec86db3 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -199,6 +199,10 @@ private: // display refresh period. std::pair<nsecs_t, nsecs_t> getDisplayFrames(nsecs_t layerPeriod, nsecs_t displayPeriod) const; + // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by + // the policy. + const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock); + // The list of refresh rates, indexed by display config ID. This must not change after this // object is initialized. AllRefreshRatesMapType mRefreshRates; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index a0d63ba863..54442391ea 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -99,12 +99,14 @@ std::unique_ptr<DispSync> createDispSync() { Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, const scheduler::RefreshRateConfigs& refreshRateConfig, - ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2, + bool useContentDetection) : mPrimaryDispSync(createDispSync()), mEventControlThread(new impl::EventControlThread(std::move(function))), mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)), mSchedulerCallback(schedulerCallback), mRefreshRateConfigs(refreshRateConfig), + mUseContentDetection(useContentDetection), mUseContentDetectionV2(useContentDetectionV2) { using namespace sysprop; @@ -147,12 +149,14 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync, std::unique_ptr<EventControlThread> eventControlThread, const scheduler::RefreshRateConfigs& configs, - ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2, + bool useContentDetection) : mPrimaryDispSync(std::move(primaryDispSync)), mEventControlThread(std::move(eventControlThread)), mSupportKernelTimer(false), mSchedulerCallback(schedulerCallback), mRefreshRateConfigs(configs), + mUseContentDetection(useContentDetection), mUseContentDetectionV2(useContentDetectionV2) {} Scheduler::~Scheduler() { @@ -381,6 +385,17 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; + // If the content detection feature is off, all layers are registered at NoVote. We still + // keep the layer history, since we use it for other features (like Frame Rate API), so layers + // still need to be registered. + if (!mUseContentDetection) { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::NoVote); + return; + } + + // In V1 of content detection, all layers are registered as Heuristic (unless it's wallpaper). if (!mUseContentDetectionV2) { const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER @@ -391,6 +406,7 @@ void Scheduler::registerLayer(Layer* layer) { scheduler::LayerHistory::LayerVoteType::Heuristic); } else { if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { + // Running Wallpaper at Min is considered as part of content detection. mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, mRefreshRateConfigs.getMaxRefreshRate().fps, scheduler::LayerHistory::LayerVoteType::Min); @@ -539,8 +555,10 @@ void Scheduler::dump(std::string& result) const { StringAppendF(&result, "+ Idle timer: %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : states[0]); - StringAppendF(&result, "+ Touch timer: %s\n\n", + StringAppendF(&result, "+ Touch timer: %s\n", mTouchTimer ? mTouchTimer->dump().c_str() : states[0]); + StringAppendF(&result, "+ Use content detection: %s\n\n", + sysprop::use_content_detection_for_refresh_rate(false) ? "on" : "off"); } template <class T> diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 6ffda7878a..04cc96a5d1 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -64,7 +64,7 @@ public: Scheduler(impl::EventControlThread::SetVSyncEnabledFunction, const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, - bool useContentDetectionV2); + bool useContentDetectionV2, bool useContentDetection); virtual ~Scheduler(); @@ -160,7 +160,7 @@ private: // Used by tests to inject mocks. Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>, const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, - bool useContentDetectionV2); + bool useContentDetectionV2, bool useContentDetection); std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs); @@ -246,6 +246,9 @@ private: GUARDED_BY(mVsyncTimelineLock); static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; + // This variable indicates whether to use the content detection feature at all. + const bool mUseContentDetection; + // This variable indicates whether to use V2 version of the content detection. const bool mUseContentDetectionV2; }; diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index d49133d1fc..9a01d90664 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -33,6 +33,7 @@ #include "NativeWindowSurface.h" #include "StartPropertySetThread.h" #include "SurfaceFlingerDefaultFactory.h" +#include "SurfaceFlingerProperties.h" #include "SurfaceInterceptor.h" #include "DisplayHardware/ComposerHal.h" @@ -76,8 +77,8 @@ std::unique_ptr<Scheduler> DefaultFactory::createScheduler( SetVSyncEnabled setVSyncEnabled, const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& schedulerCallback) { return std::make_unique<Scheduler>(std::move(setVSyncEnabled), configs, schedulerCallback, - property_get_bool("debug.sf.use_content_detection_v2", - true)); + property_get_bool("debug.sf.use_content_detection_v2", true), + sysprop::use_content_detection_for_refresh_rate(false)); } std::unique_ptr<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor( diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 7e625135ae..e7e7f66c95 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -247,6 +247,31 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); } +TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_noLayers) { + std::vector<RefreshRateConfigs::InputConfig> configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/ + HWC_CONFIG_ID_72); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 72}; + + // If there are not layers, there is not content detection, so return the current + // refresh rate. + auto layers = std::vector<LayerRequirement>{}; + EXPECT_EQ(expected72Config, + refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ + false)); + + // Current refresh rate can always be changed. + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContentV2(layers, /*touchActive*/ + false)); +} + TEST_F(RefreshRateConfigsTest, getRefreshRateForContentV2_60_90) { std::vector<RefreshRateConfigs::InputConfig> configs{ {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index b0b51bdd8a..41b5d49bf8 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -29,7 +29,7 @@ namespace android { class TestableScheduler : public Scheduler, private ISchedulerCallback { public: TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) - : Scheduler([](bool) {}, configs, *this, useContentDetectionV2) { + : Scheduler([](bool) {}, configs, *this, useContentDetectionV2, true) { if (mUseContentDetectionV2) { mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(); } else { @@ -41,7 +41,7 @@ public: std::unique_ptr<EventControlThread> eventControlThread, const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this, - useContentDetectionV2) { + useContentDetectionV2, true) { if (mUseContentDetectionV2) { mLayerHistory = std::make_unique<scheduler::impl::LayerHistoryV2>(); } else { |