Skip to content

Commit b1e7d3c

Browse files
RamIndaniAndroid (Google) Code Review
authored andcommitted
Merge "[SF] Backdoor to update the WorkDuration" into main
2 parents de365a6 + 70d21c0 commit b1e7d3c

File tree

6 files changed

+128
-22
lines changed

6 files changed

+128
-22
lines changed

services/surfaceflinger/Scheduler/Scheduler.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ void Scheduler::setPacesetterDisplay(PhysicalDisplayId pacesetterId) {
124124
// Cancel the pending refresh rate change, if any, before updating the phase configuration.
125125
mVsyncModulator->cancelRefreshRateChange();
126126

127-
mVsyncConfiguration->reset();
127+
{
128+
std::scoped_lock lock{mVsyncConfigLock};
129+
mVsyncConfiguration->reset();
130+
}
128131
updatePhaseConfiguration(pacesetterId, pacesetterSelectorPtr()->getActiveMode().fps);
129132
}
130133

@@ -211,7 +214,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
211214
.vsyncId = vsyncId,
212215
.expectedVsyncTime = expectedVsyncTime,
213216
.sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
214-
.hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration,
217+
.hwcMinWorkDuration = getCurrentVsyncConfigs().hwcMinWorkDuration,
215218
.debugPresentTimeDelay = debugPresentDelay};
216219

217220
ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked();
@@ -516,12 +519,26 @@ void Scheduler::updatePhaseConfiguration(PhysicalDisplayId displayId, Fps refres
516519
if (!isPacesetter) return;
517520

518521
mRefreshRateStats->setRefreshRate(refreshRate);
519-
mVsyncConfiguration->setRefreshRateFps(refreshRate);
520-
setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()),
521-
refreshRate.getPeriod());
522+
const auto currentConfigs = [=, this] {
523+
std::scoped_lock lock{mVsyncConfigLock};
524+
mVsyncConfiguration->setRefreshRateFps(refreshRate);
525+
return mVsyncConfiguration->getCurrentConfigs();
526+
}();
527+
setVsyncConfig(mVsyncModulator->setVsyncConfigSet(currentConfigs), refreshRate.getPeriod());
522528
}
523529
#pragma clang diagnostic pop
524530

531+
void Scheduler::reloadPhaseConfiguration(Fps refreshRate, Duration minSfDuration,
532+
Duration maxSfDuration, Duration appDuration) {
533+
const auto currentConfigs = [=, this] {
534+
std::scoped_lock lock{mVsyncConfigLock};
535+
mVsyncConfiguration = std::make_unique<impl::WorkDuration>(refreshRate, minSfDuration,
536+
maxSfDuration, appDuration);
537+
return mVsyncConfiguration->getCurrentConfigs();
538+
}();
539+
setVsyncConfig(mVsyncModulator->setVsyncConfigSet(currentConfigs), refreshRate.getPeriod());
540+
}
541+
525542
void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powerMode) {
526543
mRefreshRateStats->setPowerMode(powerMode);
527544
}
@@ -896,8 +913,11 @@ void Scheduler::dump(utils::Dumper& dumper) const {
896913
mFrameRateOverrideMappings.dump(dumper);
897914
dumper.eol();
898915

899-
mVsyncConfiguration->dump(dumper.out());
900-
dumper.eol();
916+
{
917+
std::scoped_lock lock{mVsyncConfigLock};
918+
mVsyncConfiguration->dump(dumper.out());
919+
dumper.eol();
920+
}
901921

902922
mRefreshRateStats->dump(dumper.out());
903923
dumper.eol();

services/surfaceflinger/Scheduler/Scheduler.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "RefreshRateSelector.h"
5454
#include "SmallAreaDetectionAllowMappings.h"
5555
#include "Utils/Dumper.h"
56+
#include "VsyncConfiguration.h"
5657
#include "VsyncModulator.h"
5758

5859
#include <FrontEnd/LayerHierarchy.h>
@@ -95,7 +96,7 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
9596

9697
// TODO: b/241285191 - Remove this API by promoting pacesetter in onScreen{Acquired,Released}.
9798
void setPacesetterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext)
98-
EXCLUDES(mDisplayLock);
99+
EXCLUDES(mDisplayLock, mVsyncConfigLock);
99100

100101
using RefreshRateSelectorPtr = std::shared_ptr<RefreshRateSelector>;
101102

@@ -188,9 +189,19 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
188189
}
189190
}
190191

191-
void updatePhaseConfiguration(PhysicalDisplayId, Fps);
192+
void updatePhaseConfiguration(PhysicalDisplayId, Fps) EXCLUDES(mVsyncConfigLock);
193+
void reloadPhaseConfiguration(Fps, Duration minSfDuration, Duration maxSfDuration,
194+
Duration appDuration) EXCLUDES(mVsyncConfigLock);
192195

193-
const VsyncConfiguration& getVsyncConfiguration() const { return *mVsyncConfiguration; }
196+
VsyncConfigSet getCurrentVsyncConfigs() const EXCLUDES(mVsyncConfigLock) {
197+
std::scoped_lock lock{mVsyncConfigLock};
198+
return mVsyncConfiguration->getCurrentConfigs();
199+
}
200+
201+
VsyncConfigSet getVsyncConfigsForRefreshRate(Fps refreshRate) const EXCLUDES(mVsyncConfigLock) {
202+
std::scoped_lock lock{mVsyncConfigLock};
203+
return mVsyncConfiguration->getConfigsForRefreshRate(refreshRate);
204+
}
194205

195206
// Sets the render rate for the scheduler to run at.
196207
void setRenderRate(PhysicalDisplayId, Fps, bool applyImmediately);
@@ -266,7 +277,7 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
266277

267278
bool isVsyncInPhase(TimePoint expectedVsyncTime, Fps frameRate) const;
268279

269-
void dump(utils::Dumper&) const;
280+
void dump(utils::Dumper&) const EXCLUDES(mVsyncConfigLock);
270281
void dump(Cycle, std::string&) const;
271282
void dumpVsync(std::string&) const EXCLUDES(mDisplayLock);
272283

@@ -348,7 +359,7 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
348359

349360
// impl::MessageQueue overrides:
350361
void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override
351-
REQUIRES(kMainThreadContext, mDisplayLock);
362+
REQUIRES(kMainThreadContext, mDisplayLock) EXCLUDES(mVsyncConfigLock);
352363

353364
// Used to skip event dispatch before EventThread creation during boot.
354365
// TODO: b/241285191 - Reorder Scheduler initialization to avoid this.
@@ -476,8 +487,9 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
476487

477488
const FeatureFlags mFeatures;
478489

490+
mutable std::mutex mVsyncConfigLock;
479491
// Stores phase offsets configured per refresh rate.
480-
const std::unique_ptr<VsyncConfiguration> mVsyncConfiguration;
492+
std::unique_ptr<VsyncConfiguration> mVsyncConfiguration GUARDED_BY(mVsyncConfigLock);
481493

482494
// Shifts the VSYNC phase during certain transactions and refresh rate changes.
483495
const sp<VsyncModulator> mVsyncModulator;

services/surfaceflinger/Scheduler/VsyncConfiguration.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,17 @@ WorkDuration::WorkDuration(Fps currentRefreshRate)
362362
validateSysprops();
363363
}
364364

365+
WorkDuration::WorkDuration(Fps currentRefreshRate, Duration minSfDuration, Duration maxSfDuration,
366+
Duration appDuration)
367+
: WorkDuration(currentRefreshRate,
368+
/*sfDuration*/ minSfDuration.ns(),
369+
/*appDuration*/ appDuration.ns(),
370+
/*sfEarlyDuration*/ maxSfDuration.ns(),
371+
/*appEarlyDuration*/ appDuration.ns(),
372+
/*sfEarlyGpuDuration*/ maxSfDuration.ns(),
373+
/*appEarlyGpuDuration*/ appDuration.ns(),
374+
/*hwcMinWorkDuration*/ 0) {}
375+
365376
WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
366377
nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
367378
nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,

services/surfaceflinger/Scheduler/VsyncConfiguration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ class PhaseOffsets : public VsyncConfiguration {
144144
class WorkDuration : public VsyncConfiguration {
145145
public:
146146
explicit WorkDuration(Fps currentRefreshRate);
147+
WorkDuration(Fps currentRefreshRate, Duration minSfDuration, Duration maxSfDuration,
148+
Duration appDuration);
147149

148150
protected:
149151
// Used for unit tests

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,8 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info
12261226
outMode.peakRefreshRate = peakFps.getValue();
12271227
outMode.vsyncRate = mode->getVsyncRate().getValue();
12281228

1229-
const auto vsyncConfigSet = mScheduler->getVsyncConfiguration().getConfigsForRefreshRate(
1230-
Fps::fromValue(outMode.peakRefreshRate));
1229+
const auto vsyncConfigSet =
1230+
mScheduler->getVsyncConfigsForRefreshRate(Fps::fromValue(outMode.peakRefreshRate));
12311231
outMode.appVsyncOffset = vsyncConfigSet.late.appOffset;
12321232
outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
12331233
outMode.group = mode->getGroup();
@@ -3326,8 +3326,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId,
33263326
const auto schedule = mScheduler->getVsyncSchedule();
33273327
const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime);
33283328
const Fps renderRate = pacesetterDisplay->refreshRateSelector().getActiveMode().fps;
3329-
const nsecs_t vsyncPhase =
3330-
mScheduler->getVsyncConfiguration().getCurrentConfigs().late.sfOffset;
3329+
const nsecs_t vsyncPhase = mScheduler->getCurrentVsyncConfigs().late.sfOffset;
33313330

33323331
const CompositorTiming compositorTiming(vsyncDeadline.ns(), renderRate.getPeriodNsecs(),
33333332
vsyncPhase, presentLatency.ns());
@@ -4657,7 +4656,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
46574656
/*applyImmediately*/ true);
46584657
}
46594658

4660-
const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs();
4659+
const auto configs = mScheduler->getCurrentVsyncConfigs();
46614660

46624661
mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(),
46634662
/* workDuration */ configs.late.appWorkDuration,
@@ -6647,9 +6646,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
66476646
code == IBinder::SYSPROPS_TRANSACTION) {
66486647
return OK;
66496648
}
6650-
// Numbers from 1000 to 1045 are currently used for backdoors. The code
6649+
// Numbers from 1000 to 1047 are currently used for backdoors. The code
66516650
// in onTransact verifies that the user is root, and has access to use SF.
6652-
if (code >= 1000 && code <= 1046) {
6651+
if (code >= 1000 && code <= 1047) {
66536652
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
66546653
return OK;
66556654
}
@@ -7192,6 +7191,34 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
71927191
mScheduler->setDebugPresentDelay(TimePoint::fromNs(ms2ns(jankDelayMs)));
71937192
return NO_ERROR;
71947193
}
7194+
// Update WorkDuration
7195+
// parameters:
7196+
// - (required) i64 minSfNs, used as the late.sf WorkDuration.
7197+
// - (required) i64 maxSfNs, used as the early.sf and earlyGl.sf WorkDuration.
7198+
// - (required) i64 appDurationNs, used as the late.app, early.app and earlyGl.app
7199+
// WorkDuration.
7200+
// Usage:
7201+
// adb shell service call SurfaceFlinger 1047 i64 12333333 i64 16666666 i64 16666666
7202+
case 1047: {
7203+
if (!property_get_bool("debug.sf.use_phase_offsets_as_durations", false)) {
7204+
ALOGE("Not supported when work duration is not enabled");
7205+
return INVALID_OPERATION;
7206+
}
7207+
int64_t minSfNs = 0;
7208+
int64_t maxSfNs = 0;
7209+
int64_t appDurationNs = 0;
7210+
if (data.readInt64(&minSfNs) != NO_ERROR || data.readInt64(&maxSfNs) != NO_ERROR ||
7211+
data.readInt64(&appDurationNs) != NO_ERROR) {
7212+
return BAD_VALUE;
7213+
}
7214+
mScheduler->reloadPhaseConfiguration(mDisplayModeController
7215+
.getActiveMode(mActiveDisplayId)
7216+
.fps,
7217+
Duration::fromNs(minSfNs),
7218+
Duration::fromNs(maxSfNs),
7219+
Duration::fromNs(appDurationNs));
7220+
return NO_ERROR;
7221+
}
71957222
}
71967223
}
71977224
return err;
@@ -8376,8 +8403,7 @@ uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t ui
83768403
}
83778404

83788405
int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const {
8379-
const auto vsyncConfig =
8380-
mScheduler->getVsyncConfiguration().getConfigsForRefreshRate(refreshRate).late;
8406+
const auto vsyncConfig = mScheduler->getVsyncConfigsForRefreshRate(refreshRate).late;
83818407
const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration;
83828408
return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
83838409
}

services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <chrono>
2323
#include <thread>
2424

25+
#include <scheduler/Time.h>
26+
2527
#include "Scheduler/VsyncConfiguration.h"
2628

2729
using namespace testing;
@@ -39,6 +41,10 @@ class TestableWorkDuration : public impl::WorkDuration {
3941
: impl::WorkDuration(currentFps, sfDuration, appDuration, sfEarlyDuration,
4042
appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration,
4143
hwcMinWorkDuration) {}
44+
45+
TestableWorkDuration(Fps currentFps, Duration minSfDuration, Duration maxSfDuration,
46+
Duration appDuration)
47+
: impl::WorkDuration(currentFps, minSfDuration, maxSfDuration, appDuration) {}
4248
};
4349

4450
class WorkDurationTest : public testing::Test {
@@ -168,6 +174,35 @@ TEST_F(WorkDurationTest, minHwcWorkDuration) {
168174
EXPECT_EQ(mWorkDuration.getCurrentConfigs().hwcMinWorkDuration, 1234ns);
169175
}
170176

177+
TEST_F(WorkDurationTest, workDurationIsARange) {
178+
const Duration minSfDuration = Duration::fromNs(10'500'000);
179+
const Duration maxSfDuration = Duration::fromNs(20'500'000);
180+
const Duration appDuration = Duration::fromNs(16'000'000);
181+
const TestableWorkDuration workDuration{60_Hz, minSfDuration, maxSfDuration, appDuration};
182+
183+
auto currentOffsets = workDuration.getCurrentConfigs();
184+
auto offsets = workDuration.getConfigsForRefreshRate(60_Hz);
185+
186+
EXPECT_EQ(currentOffsets, offsets);
187+
EXPECT_EQ(offsets.late.sfOffset, 6'166'667);
188+
EXPECT_EQ(offsets.late.appOffset, 6'833'334);
189+
190+
EXPECT_EQ(offsets.late.sfWorkDuration, 10'500'000ns);
191+
EXPECT_EQ(offsets.late.appWorkDuration, 16'000'000ns);
192+
193+
EXPECT_EQ(offsets.early.sfOffset, -3'833'333);
194+
EXPECT_EQ(offsets.early.appOffset, 13'500'001);
195+
196+
EXPECT_EQ(offsets.early.sfWorkDuration, 20'500'000ns);
197+
EXPECT_EQ(offsets.early.appWorkDuration, 16'000'000ns);
198+
199+
EXPECT_EQ(offsets.earlyGpu.sfOffset, -3'833'333);
200+
EXPECT_EQ(offsets.earlyGpu.appOffset, 13'500'001);
201+
202+
EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 20'500'000ns);
203+
EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 16'000'000ns);
204+
}
205+
171206
class TestablePhaseOffsets : public impl::PhaseOffsets {
172207
public:
173208
TestablePhaseOffsets(nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,

0 commit comments

Comments
 (0)