diff options
author | 2025-03-20 12:47:43 -0700 | |
---|---|---|
committer | 2025-03-20 12:47:43 -0700 | |
commit | b1e7d3cfe6c857e94400094bbf7421de50e432aa (patch) | |
tree | 7d0a9c395767fab7a6789eba1109ef584c929a76 | |
parent | de365a6c1bfd64d2e9ef9da49e30f3565ecaf599 (diff) | |
parent | 70d21c0b993a26ea6dffa6afc002beab3efd0d95 (diff) |
Merge "[SF] Backdoor to update the WorkDuration" into main
6 files changed, 128 insertions, 22 deletions
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index c9d3b31061..16266c6b00 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -124,7 +124,10 @@ void Scheduler::setPacesetterDisplay(PhysicalDisplayId pacesetterId) { // Cancel the pending refresh rate change, if any, before updating the phase configuration. mVsyncModulator->cancelRefreshRateChange(); - mVsyncConfiguration->reset(); + { + std::scoped_lock lock{mVsyncConfigLock}; + mVsyncConfiguration->reset(); + } updatePhaseConfiguration(pacesetterId, pacesetterSelectorPtr()->getActiveMode().fps); } @@ -211,7 +214,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, .vsyncId = vsyncId, .expectedVsyncTime = expectedVsyncTime, .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration, - .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration, + .hwcMinWorkDuration = getCurrentVsyncConfigs().hwcMinWorkDuration, .debugPresentTimeDelay = debugPresentDelay}; ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked(); @@ -516,12 +519,26 @@ void Scheduler::updatePhaseConfiguration(PhysicalDisplayId displayId, Fps refres if (!isPacesetter) return; mRefreshRateStats->setRefreshRate(refreshRate); - mVsyncConfiguration->setRefreshRateFps(refreshRate); - setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()), - refreshRate.getPeriod()); + const auto currentConfigs = [=, this] { + std::scoped_lock lock{mVsyncConfigLock}; + mVsyncConfiguration->setRefreshRateFps(refreshRate); + return mVsyncConfiguration->getCurrentConfigs(); + }(); + setVsyncConfig(mVsyncModulator->setVsyncConfigSet(currentConfigs), refreshRate.getPeriod()); } #pragma clang diagnostic pop +void Scheduler::reloadPhaseConfiguration(Fps refreshRate, Duration minSfDuration, + Duration maxSfDuration, Duration appDuration) { + const auto currentConfigs = [=, this] { + std::scoped_lock lock{mVsyncConfigLock}; + mVsyncConfiguration = std::make_unique<impl::WorkDuration>(refreshRate, minSfDuration, + maxSfDuration, appDuration); + return mVsyncConfiguration->getCurrentConfigs(); + }(); + setVsyncConfig(mVsyncModulator->setVsyncConfigSet(currentConfigs), refreshRate.getPeriod()); +} + void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powerMode) { mRefreshRateStats->setPowerMode(powerMode); } @@ -896,8 +913,11 @@ void Scheduler::dump(utils::Dumper& dumper) const { mFrameRateOverrideMappings.dump(dumper); dumper.eol(); - mVsyncConfiguration->dump(dumper.out()); - dumper.eol(); + { + std::scoped_lock lock{mVsyncConfigLock}; + mVsyncConfiguration->dump(dumper.out()); + dumper.eol(); + } mRefreshRateStats->dump(dumper.out()); dumper.eol(); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 61469c1b46..694856e9ce 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -53,6 +53,7 @@ #include "RefreshRateSelector.h" #include "SmallAreaDetectionAllowMappings.h" #include "Utils/Dumper.h" +#include "VsyncConfiguration.h" #include "VsyncModulator.h" #include <FrontEnd/LayerHierarchy.h> @@ -95,7 +96,7 @@ public: // TODO: b/241285191 - Remove this API by promoting pacesetter in onScreen{Acquired,Released}. void setPacesetterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) - EXCLUDES(mDisplayLock); + EXCLUDES(mDisplayLock, mVsyncConfigLock); using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>; @@ -188,9 +189,19 @@ public: } } - void updatePhaseConfiguration(PhysicalDisplayId, Fps); + void updatePhaseConfiguration(PhysicalDisplayId, Fps) EXCLUDES(mVsyncConfigLock); + void reloadPhaseConfiguration(Fps, Duration minSfDuration, Duration maxSfDuration, + Duration appDuration) EXCLUDES(mVsyncConfigLock); - const VsyncConfiguration& getVsyncConfiguration() const { return *mVsyncConfiguration; } + VsyncConfigSet getCurrentVsyncConfigs() const EXCLUDES(mVsyncConfigLock) { + std::scoped_lock lock{mVsyncConfigLock}; + return mVsyncConfiguration->getCurrentConfigs(); + } + + VsyncConfigSet getVsyncConfigsForRefreshRate(Fps refreshRate) const EXCLUDES(mVsyncConfigLock) { + std::scoped_lock lock{mVsyncConfigLock}; + return mVsyncConfiguration->getConfigsForRefreshRate(refreshRate); + } // Sets the render rate for the scheduler to run at. void setRenderRate(PhysicalDisplayId, Fps, bool applyImmediately); @@ -266,7 +277,7 @@ public: bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const; - void dump(utils::Dumper&) const; + void dump(utils::Dumper&) const EXCLUDES(mVsyncConfigLock); void dump(Cycle, std::string&) const; void dumpVsync(std::string&) const EXCLUDES(mDisplayLock); @@ -348,7 +359,7 @@ private: // impl::MessageQueue overrides: void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override - REQUIRES(kMainThreadContext, mDisplayLock); + REQUIRES(kMainThreadContext, mDisplayLock) EXCLUDES(mVsyncConfigLock); // Used to skip event dispatch before EventThread creation during boot. // TODO: b/241285191 - Reorder Scheduler initialization to avoid this. @@ -476,8 +487,9 @@ private: const FeatureFlags mFeatures; + mutable std::mutex mVsyncConfigLock; // Stores phase offsets configured per refresh rate. - const std::unique_ptr<VsyncConfiguration> mVsyncConfiguration; + std::unique_ptr<VsyncConfiguration> mVsyncConfiguration GUARDED_BY(mVsyncConfigLock); // Shifts the VSYNC phase during certain transactions and refresh rate changes. const sp<VsyncModulator> mVsyncModulator; diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp index 6ae10f3d31..8cbb17c06e 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp @@ -362,6 +362,17 @@ WorkDuration::WorkDuration(Fps currentRefreshRate) validateSysprops(); } +WorkDuration::WorkDuration(Fps currentRefreshRate, Duration minSfDuration, Duration maxSfDuration, + Duration appDuration) + : WorkDuration(currentRefreshRate, + /*sfDuration*/ minSfDuration.ns(), + /*appDuration*/ appDuration.ns(), + /*sfEarlyDuration*/ maxSfDuration.ns(), + /*appEarlyDuration*/ appDuration.ns(), + /*sfEarlyGpuDuration*/ maxSfDuration.ns(), + /*appEarlyGpuDuration*/ appDuration.ns(), + /*hwcMinWorkDuration*/ 0) {} + WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration, diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h index b6cb373b7e..3d8ae3e5d4 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h @@ -144,6 +144,8 @@ private: class WorkDuration : public VsyncConfiguration { public: explicit WorkDuration(Fps currentRefreshRate); + WorkDuration(Fps currentRefreshRate, Duration minSfDuration, Duration maxSfDuration, + Duration appDuration); protected: // Used for unit tests diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6b40c98d0a..9a0b87deca 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1226,8 +1226,8 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info outMode.peakRefreshRate = peakFps.getValue(); outMode.vsyncRate = mode->getVsyncRate().getValue(); - const auto vsyncConfigSet = mScheduler->getVsyncConfiguration().getConfigsForRefreshRate( - Fps::fromValue(outMode.peakRefreshRate)); + const auto vsyncConfigSet = + mScheduler->getVsyncConfigsForRefreshRate(Fps::fromValue(outMode.peakRefreshRate)); outMode.appVsyncOffset = vsyncConfigSet.late.appOffset; outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset; outMode.group = mode->getGroup(); @@ -3326,8 +3326,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, const auto schedule = mScheduler->getVsyncSchedule(); const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime); const Fps renderRate = pacesetterDisplay->refreshRateSelector().getActiveMode().fps; - const nsecs_t vsyncPhase = - mScheduler->getVsyncConfiguration().getCurrentConfigs().late.sfOffset; + const nsecs_t vsyncPhase = mScheduler->getCurrentVsyncConfigs().late.sfOffset; const CompositorTiming compositorTiming(vsyncDeadline.ns(), renderRate.getPeriodNsecs(), vsyncPhase, presentLatency.ns()); @@ -4657,7 +4656,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { /*applyImmediately*/ true); } - const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs(); + const auto configs = mScheduler->getCurrentVsyncConfigs(); mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(), /* workDuration */ configs.late.appWorkDuration, @@ -6647,9 +6646,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { code == IBinder::SYSPROPS_TRANSACTION) { return OK; } - // Numbers from 1000 to 1045 are currently used for backdoors. The code + // Numbers from 1000 to 1047 are currently used for backdoors. The code // in onTransact verifies that the user is root, and has access to use SF. - if (code >= 1000 && code <= 1046) { + if (code >= 1000 && code <= 1047) { ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code); return OK; } @@ -7192,6 +7191,34 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r mScheduler->setDebugPresentDelay(TimePoint::fromNs(ms2ns(jankDelayMs))); return NO_ERROR; } + // Update WorkDuration + // parameters: + // - (required) i64 minSfNs, used as the late.sf WorkDuration. + // - (required) i64 maxSfNs, used as the early.sf and earlyGl.sf WorkDuration. + // - (required) i64 appDurationNs, used as the late.app, early.app and earlyGl.app + // WorkDuration. + // Usage: + // adb shell service call SurfaceFlinger 1047 i64 12333333 i64 16666666 i64 16666666 + case 1047: { + if (!property_get_bool("debug.sf.use_phase_offsets_as_durations", false)) { + ALOGE("Not supported when work duration is not enabled"); + return INVALID_OPERATION; + } + int64_t minSfNs = 0; + int64_t maxSfNs = 0; + int64_t appDurationNs = 0; + if (data.readInt64(&minSfNs) != NO_ERROR || data.readInt64(&maxSfNs) != NO_ERROR || + data.readInt64(&appDurationNs) != NO_ERROR) { + return BAD_VALUE; + } + mScheduler->reloadPhaseConfiguration(mDisplayModeController + .getActiveMode(mActiveDisplayId) + .fps, + Duration::fromNs(minSfNs), + Duration::fromNs(maxSfNs), + Duration::fromNs(appDurationNs)); + return NO_ERROR; + } } } return err; @@ -8376,8 +8403,7 @@ uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t ui } int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const { - const auto vsyncConfig = - mScheduler->getVsyncConfiguration().getConfigsForRefreshRate(refreshRate).late; + const auto vsyncConfig = mScheduler->getVsyncConfigsForRefreshRate(refreshRate).late; const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration; return calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } diff --git a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp index 21ee071f1b..3589553be0 100644 --- a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp +++ b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp @@ -22,6 +22,8 @@ #include <chrono> #include <thread> +#include <scheduler/Time.h> + #include "Scheduler/VsyncConfiguration.h" using namespace testing; @@ -39,6 +41,10 @@ public: : impl::WorkDuration(currentFps, sfDuration, appDuration, sfEarlyDuration, appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration, hwcMinWorkDuration) {} + + TestableWorkDuration(Fps currentFps, Duration minSfDuration, Duration maxSfDuration, + Duration appDuration) + : impl::WorkDuration(currentFps, minSfDuration, maxSfDuration, appDuration) {} }; class WorkDurationTest : public testing::Test { @@ -168,6 +174,35 @@ TEST_F(WorkDurationTest, minHwcWorkDuration) { EXPECT_EQ(mWorkDuration.getCurrentConfigs().hwcMinWorkDuration, 1234ns); } +TEST_F(WorkDurationTest, workDurationIsARange) { + const Duration minSfDuration = Duration::fromNs(10'500'000); + const Duration maxSfDuration = Duration::fromNs(20'500'000); + const Duration appDuration = Duration::fromNs(16'000'000); + const TestableWorkDuration workDuration{60_Hz, minSfDuration, maxSfDuration, appDuration}; + + auto currentOffsets = workDuration.getCurrentConfigs(); + auto offsets = workDuration.getConfigsForRefreshRate(60_Hz); + + EXPECT_EQ(currentOffsets, offsets); + EXPECT_EQ(offsets.late.sfOffset, 6'166'667); + EXPECT_EQ(offsets.late.appOffset, 6'833'334); + + EXPECT_EQ(offsets.late.sfWorkDuration, 10'500'000ns); + EXPECT_EQ(offsets.late.appWorkDuration, 16'000'000ns); + + EXPECT_EQ(offsets.early.sfOffset, -3'833'333); + EXPECT_EQ(offsets.early.appOffset, 13'500'001); + + EXPECT_EQ(offsets.early.sfWorkDuration, 20'500'000ns); + EXPECT_EQ(offsets.early.appWorkDuration, 16'000'000ns); + + EXPECT_EQ(offsets.earlyGpu.sfOffset, -3'833'333); + EXPECT_EQ(offsets.earlyGpu.appOffset, 13'500'001); + + EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 20'500'000ns); + EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 16'000'000ns); +} + class TestablePhaseOffsets : public impl::PhaseOffsets { public: TestablePhaseOffsets(nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, |