SF: introduce debug.sf.hwc.min.duration
debug.sf.hwc.min.duration can be set for specific devices to
indicate the shortest duration hwc will take to present a frame.
This value is used by SurfaceFlinger to calculate the
earlistPresentTime used for preventing an early present.
Bug: 190842189
Bug: 188854955
Test: SF unit tests
Test: run TouchLatency with debug.sf.hwc.min.duration set to a value
Change-Id: I8ffe92e5e6b355892c6bb073229f417fb0e9588c
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
index cb57aea..43e0297 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp
@@ -59,7 +59,7 @@
}
void VsyncConfiguration::dump(std::string& result) const {
- const auto [early, earlyGpu, late] = getCurrentConfigs();
+ const auto [early, earlyGpu, late, hwcMinWorkDuration] = getCurrentConfigs();
using base::StringAppendF;
StringAppendF(&result,
" app phase: %9" PRId64 " ns\t SF phase: %9" PRId64
@@ -70,7 +70,8 @@
" early app duration: %9lld ns\t early SF duration: %9lld ns\n"
" GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64
" ns\n"
- " GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n",
+ " GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n"
+ " HWC min duration: %9lld ns\n",
late.appOffset, late.sfOffset,
late.appWorkDuration.count(), late.sfWorkDuration.count(),
@@ -81,7 +82,9 @@
earlyGpu.appOffset, earlyGpu.sfOffset,
- earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count());
+ earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count(),
+
+ hwcMinWorkDuration.count());
}
PhaseOffsets::PhaseOffsets(Fps currentRefreshRate)
@@ -103,7 +106,8 @@
// offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW
// vsync.
getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
- .value_or(std::numeric_limits<nsecs_t>::max())) {}
+ .value_or(std::numeric_limits<nsecs_t>::max()),
+ getProperty("debug.sf.hwc.min.duration").value_or(0)) {}
PhaseOffsets::PhaseOffsets(Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
std::optional<nsecs_t> earlySfOffsetNs,
@@ -115,7 +119,7 @@
std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
- nsecs_t thresholdForNextVsync)
+ nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration)
: VsyncConfiguration(currentFps),
mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
@@ -129,7 +133,8 @@
mHighFpsEarlyGpuSfOffsetNs(highFpsEarlyGpuSfOffsetNs),
mHighFpsEarlyAppOffsetNs(highFpsEarlyAppOffsetNs),
mHighFpsEarlyGpuAppOffsetNs(highFpsEarlyGpuAppOffsetNs),
- mThresholdForNextVsync(thresholdForNextVsync) {}
+ mThresholdForNextVsync(thresholdForNextVsync),
+ mHwcMinWorkDuration(hwcMinWorkDuration) {}
PhaseOffsets::VsyncConfigSet PhaseOffsets::constructOffsets(nsecs_t vsyncDuration) const {
if (vsyncDuration < std::chrono::nanoseconds(15ms).count()) {
@@ -189,6 +194,7 @@
.sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
.appWorkDuration =
appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration)},
+ .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
};
}
@@ -234,6 +240,7 @@
.appWorkDuration =
appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration),
},
+ .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
};
}
@@ -342,6 +349,7 @@
.sfWorkDuration = sfDuration,
.appWorkDuration = appDuration,
},
+ .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
};
}
@@ -351,19 +359,22 @@
getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration),
- getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration)) {
+ getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration),
+ getProperty("debug.sf.hwc.min.duration").value_or(0)) {
validateSysprops();
}
WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
- nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration)
+ nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
+ nsecs_t hwcMinWorkDuration)
: VsyncConfiguration(currentRefreshRate),
mSfDuration(sfDuration),
mAppDuration(appDuration),
mSfEarlyDuration(sfEarlyDuration),
mAppEarlyDuration(appEarlyDuration),
mSfEarlyGpuDuration(sfEarlyGpuDuration),
- mAppEarlyGpuDuration(appEarlyGpuDuration) {}
+ mAppEarlyGpuDuration(appEarlyGpuDuration),
+ mHwcMinWorkDuration(hwcMinWorkDuration) {}
} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
index d9d206d..3e53b3f 100644
--- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h
+++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h
@@ -111,7 +111,8 @@
nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional<nsecs_t> highFpsEarlySfOffsetNs,
std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
- std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync);
+ std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync,
+ nsecs_t hwcMinWorkDuration);
private:
VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
@@ -134,6 +135,7 @@
const std::optional<nsecs_t> mHighFpsEarlyGpuAppOffsetNs;
const nsecs_t mThresholdForNextVsync;
+ const nsecs_t mHwcMinWorkDuration;
};
/*
@@ -148,7 +150,8 @@
protected:
// Used for unit tests
WorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration,
- nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration);
+ nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
+ nsecs_t hwcMinWorkDuration);
private:
VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
@@ -161,6 +164,8 @@
const nsecs_t mSfEarlyGpuDuration;
const nsecs_t mAppEarlyGpuDuration;
+
+ const nsecs_t mHwcMinWorkDuration;
};
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.h b/services/surfaceflinger/Scheduler/VsyncModulator.h
index fcde279..9410768 100644
--- a/services/surfaceflinger/Scheduler/VsyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VsyncModulator.h
@@ -69,9 +69,12 @@
VsyncConfig early; // Used for early transactions, and during refresh rate change.
VsyncConfig earlyGpu; // Used during GPU composition.
VsyncConfig late; // Default.
+ std::chrono::nanoseconds hwcMinWorkDuration; // Used for calculating the
+ // earliest present time
bool operator==(const VsyncConfigSet& other) const {
- return early == other.early && earlyGpu == other.earlyGpu && late == other.late;
+ return early == other.early && earlyGpu == other.earlyGpu && late == other.late &&
+ hwcMinWorkDuration == other.hwcMinWorkDuration;
}
bool operator!=(const VsyncConfigSet& other) const { return !(*this == other); }