Skip to content

Commit 70d21c0

Browse files
committed
[SF] Backdoor to update the WorkDuration
Test: atest libsurfaceflinger_unittest Test: Verified with a trace that work duration updates after backdoor call. BUG: 398872242 Flag: EXEMPT Backdoor implementation. Change-Id: Icea9bebbb3366df09643dbe40fd7c986461262b8
1 parent 1641606 commit 70d21c0

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
@@ -1230,8 +1230,8 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info
12301230
outMode.peakRefreshRate = peakFps.getValue();
12311231
outMode.vsyncRate = mode->getVsyncRate().getValue();
12321232

1233-
const auto vsyncConfigSet = mScheduler->getVsyncConfiguration().getConfigsForRefreshRate(
1234-
Fps::fromValue(outMode.peakRefreshRate));
1233+
const auto vsyncConfigSet =
1234+
mScheduler->getVsyncConfigsForRefreshRate(Fps::fromValue(outMode.peakRefreshRate));
12351235
outMode.appVsyncOffset = vsyncConfigSet.late.appOffset;
12361236
outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
12371237
outMode.group = mode->getGroup();
@@ -3331,8 +3331,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId,
33313331
const auto schedule = mScheduler->getVsyncSchedule();
33323332
const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime);
33333333
const Fps renderRate = pacesetterDisplay->refreshRateSelector().getActiveMode().fps;
3334-
const nsecs_t vsyncPhase =
3335-
mScheduler->getVsyncConfiguration().getCurrentConfigs().late.sfOffset;
3334+
const nsecs_t vsyncPhase = mScheduler->getCurrentVsyncConfigs().late.sfOffset;
33363335

33373336
const CompositorTiming compositorTiming(vsyncDeadline.ns(), renderRate.getPeriodNsecs(),
33383337
vsyncPhase, presentLatency.ns());
@@ -4664,7 +4663,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
46644663
/*applyImmediately*/ true);
46654664
}
46664665

4667-
const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs();
4666+
const auto configs = mScheduler->getCurrentVsyncConfigs();
46684667

46694668
mScheduler->createEventThread(scheduler::Cycle::Render, mFrameTimeline->getTokenManager(),
46704669
/* workDuration */ configs.late.appWorkDuration,
@@ -6655,9 +6654,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
66556654
code == IBinder::SYSPROPS_TRANSACTION) {
66566655
return OK;
66576656
}
6658-
// Numbers from 1000 to 1045 are currently used for backdoors. The code
6657+
// Numbers from 1000 to 1047 are currently used for backdoors. The code
66596658
// in onTransact verifies that the user is root, and has access to use SF.
6660-
if (code >= 1000 && code <= 1046) {
6659+
if (code >= 1000 && code <= 1047) {
66616660
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
66626661
return OK;
66636662
}
@@ -7199,6 +7198,34 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
71997198
mScheduler->setDebugPresentDelay(TimePoint::fromNs(ms2ns(jankDelayMs)));
72007199
return NO_ERROR;
72017200
}
7201+
// Update WorkDuration
7202+
// parameters:
7203+
// - (required) i64 minSfNs, used as the late.sf WorkDuration.
7204+
// - (required) i64 maxSfNs, used as the early.sf and earlyGl.sf WorkDuration.
7205+
// - (required) i64 appDurationNs, used as the late.app, early.app and earlyGl.app
7206+
// WorkDuration.
7207+
// Usage:
7208+
// adb shell service call SurfaceFlinger 1047 i64 12333333 i64 16666666 i64 16666666
7209+
case 1047: {
7210+
if (!property_get_bool("debug.sf.use_phase_offsets_as_durations", false)) {
7211+
ALOGE("Not supported when work duration is not enabled");
7212+
return INVALID_OPERATION;
7213+
}
7214+
int64_t minSfNs = 0;
7215+
int64_t maxSfNs = 0;
7216+
int64_t appDurationNs = 0;
7217+
if (data.readInt64(&minSfNs) != NO_ERROR || data.readInt64(&maxSfNs) != NO_ERROR ||
7218+
data.readInt64(&appDurationNs) != NO_ERROR) {
7219+
return BAD_VALUE;
7220+
}
7221+
mScheduler->reloadPhaseConfiguration(mDisplayModeController
7222+
.getActiveMode(mActiveDisplayId)
7223+
.fps,
7224+
Duration::fromNs(minSfNs),
7225+
Duration::fromNs(maxSfNs),
7226+
Duration::fromNs(appDurationNs));
7227+
return NO_ERROR;
7228+
}
72027229
}
72037230
}
72047231
return err;
@@ -8385,8 +8412,7 @@ uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t ui
83858412
}
83868413

83878414
int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const {
8388-
const auto vsyncConfig =
8389-
mScheduler->getVsyncConfiguration().getConfigsForRefreshRate(refreshRate).late;
8415+
const auto vsyncConfig = mScheduler->getVsyncConfigsForRefreshRate(refreshRate).late;
83908416
const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration;
83918417
return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
83928418
}

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)