SF: use peak refresh rate for HWC backpressure
The logic we have for selecting which fence to use to detect
backpressure replies on the assumption that continuously presents as
the rate of vsync. This is not true for VRR displays.
Bug: 296635687
Test: adb root && adb shell service call SurfaceFlinger 1045 f 0.9
Change-Id: Iaceb45741fd657b8c551f51b3c76a643df116da8
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index db247aa..d714848 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -62,5 +62,9 @@
"libgmock",
"libgtest",
"libscheduler",
+ "libsurfaceflingerflags_test",
+ ],
+ shared_libs: [
+ "server_configurable_flags",
],
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index acb7265..c13c330 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -108,6 +108,19 @@
return mRateMap.find(idealPeriod())->second.slope;
}
+Period VSyncPredictor::minFramePeriod() const {
+ if (!FlagManager::getInstance().vrr_config()) {
+ return Period::fromNs(currentPeriod());
+ }
+
+ std::lock_guard lock(mMutex);
+ const auto idealPeakRefreshPeriod = mDisplayModePtr->getPeakFps().getPeriodNsecs();
+ const auto numPeriods = static_cast<int>(std::round(static_cast<float>(idealPeakRefreshPeriod) /
+ static_cast<float>(idealPeriod())));
+ const auto slope = mRateMap.find(idealPeriod())->second.slope;
+ return Period::fromNs(slope * numPeriods);
+}
+
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
std::lock_guard lock(mMutex);
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index fbc1e16..6cb5a67 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -46,6 +46,7 @@
bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final EXCLUDES(mMutex);
nsecs_t currentPeriod() const final EXCLUDES(mMutex);
+ Period minFramePeriod() const final EXCLUDES(mMutex);
void resetModel() final EXCLUDES(mMutex);
/* Query if the model is in need of more samples to make a prediction.
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 2ae5c0b..aa18897 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -68,6 +68,11 @@
*/
virtual nsecs_t currentPeriod() const = 0;
+ /*
+ * The minimal period frames can be displayed.
+ */
+ virtual Period minFramePeriod() const = 0;
+
/* Inform the tracker that the samples it has are not accurate for prediction. */
virtual void resetModel() = 0;
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index 4a8aac6..ff1c9e9 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -81,6 +81,13 @@
return Period::fromNs(mTracker->currentPeriod());
}
+Period VsyncSchedule::minFramePeriod() const {
+ if (FlagManager::getInstance().vrr_config()) {
+ return mTracker->minFramePeriod();
+ }
+ return period();
+}
+
TimePoint VsyncSchedule::vsyncDeadlineAfter(TimePoint timePoint) const {
return TimePoint::fromNs(mTracker->nextAnticipatedVSyncTimeFrom(timePoint.ns()));
}
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 60c4105..722ea0b 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -64,6 +64,7 @@
// IVsyncSource overrides:
Period period() const override;
TimePoint vsyncDeadlineAfter(TimePoint) const override;
+ Period minFramePeriod() const override;
// Inform the schedule that the display mode changed the schedule needs to recalibrate
// itself to the new vsync period. The schedule will end the period transition internally.
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
index ae74205..70d4846 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
@@ -50,11 +50,11 @@
TimePoint expectedPresentTime() const { return mExpectedPresentTime; }
// The time of the VSYNC that preceded this frame. See `presentFenceForPastVsync` for details.
- TimePoint pastVsyncTime(Period vsyncPeriod) const;
+ TimePoint pastVsyncTime(Period minFramePeriod) const;
// Equivalent to `pastVsyncTime` unless running N VSYNCs ahead.
- TimePoint previousFrameVsyncTime(Period vsyncPeriod) const {
- return mExpectedPresentTime - vsyncPeriod;
+ TimePoint previousFrameVsyncTime(Period minFramePeriod) const {
+ return mExpectedPresentTime - minFramePeriod;
}
// The present fence for the frame that had targeted the most recent VSYNC before this frame.
@@ -62,14 +62,14 @@
// VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
// `presentFenceForPreviousFrame` if running N VSYNCs ahead, but the one that should have been
// signaled by now (unless that frame missed).
- const FenceTimePtr& presentFenceForPastVsync(Period vsyncPeriod) const;
+ const FenceTimePtr& presentFenceForPastVsync(Period minFramePeriod) const;
// Equivalent to `presentFenceForPastVsync` unless running N VSYNCs ahead.
const FenceTimePtr& presentFenceForPreviousFrame() const {
return mPresentFences.front().fenceTime;
}
- bool wouldPresentEarly(Period vsyncPeriod) const;
+ bool wouldPresentEarly(Period minFramePeriod) const;
bool isFramePending() const { return mFramePending; }
bool didMissFrame() const { return mFrameMissed; }
@@ -96,9 +96,9 @@
private:
template <int N>
- inline bool targetsVsyncsAhead(Period vsyncPeriod) const {
+ inline bool targetsVsyncsAhead(Period minFramePeriod) const {
static_assert(N > 1);
- return expectedFrameDuration() > (N - 1) * vsyncPeriod;
+ return expectedFrameDuration() > (N - 1) * minFramePeriod;
}
};
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h b/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h
index bb2de75..0154060 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/IVsyncSource.h
@@ -23,6 +23,7 @@
struct IVsyncSource {
virtual Period period() const = 0;
virtual TimePoint vsyncDeadlineAfter(TimePoint) const = 0;
+ virtual Period minFramePeriod() const = 0;
protected:
~IVsyncSource() = default;
diff --git a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
index 7a18654..e80372b 100644
--- a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
+++ b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
@@ -27,28 +27,28 @@
mHwcFrameMissed("PrevHwcFrameMissed " + displayLabel, false),
mGpuFrameMissed("PrevGpuFrameMissed " + displayLabel, false) {}
-TimePoint FrameTarget::pastVsyncTime(Period vsyncPeriod) const {
+TimePoint FrameTarget::pastVsyncTime(Period minFramePeriod) const {
// TODO(b/267315508): Generalize to N VSYNCs.
- const int shift = static_cast<int>(targetsVsyncsAhead<2>(vsyncPeriod));
- return mExpectedPresentTime - Period::fromNs(vsyncPeriod.ns() << shift);
+ const int shift = static_cast<int>(targetsVsyncsAhead<2>(minFramePeriod));
+ return mExpectedPresentTime - Period::fromNs(minFramePeriod.ns() << shift);
}
-const FenceTimePtr& FrameTarget::presentFenceForPastVsync(Period vsyncPeriod) const {
+const FenceTimePtr& FrameTarget::presentFenceForPastVsync(Period minFramePeriod) const {
// TODO(b/267315508): Generalize to N VSYNCs.
- const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(vsyncPeriod));
+ const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(minFramePeriod));
return mPresentFences[i].fenceTime;
}
-bool FrameTarget::wouldPresentEarly(Period vsyncPeriod) const {
+bool FrameTarget::wouldPresentEarly(Period minFramePeriod) const {
// TODO(b/241285475): Since this is called during `composite`, the calls to `targetsVsyncsAhead`
// should use `TimePoint::now()` in case of delays since `mFrameBeginTime`.
// TODO(b/267315508): Generalize to N VSYNCs.
- if (targetsVsyncsAhead<3>(vsyncPeriod)) {
+ if (targetsVsyncsAhead<3>(minFramePeriod)) {
return true;
}
- const auto fence = presentFenceForPastVsync(vsyncPeriod);
+ const auto fence = presentFenceForPastVsync(minFramePeriod);
return fence->isValid() && fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
}
@@ -68,6 +68,7 @@
mScheduledPresentTime = args.expectedVsyncTime;
const Period vsyncPeriod = vsyncSource.period();
+ const Period minFramePeriod = vsyncSource.minFramePeriod();
// Calculate the expected present time once and use the cached value throughout this frame to
// make sure all layers are seeing this same value.
@@ -85,7 +86,7 @@
ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)");
- const FenceTimePtr& pastPresentFence = presentFenceForPastVsync(vsyncPeriod);
+ const FenceTimePtr& pastPresentFence = presentFenceForPastVsync(minFramePeriod);
// In cases where the present fence is about to fire, give it a small grace period instead of
// giving up on the frame.
diff --git a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp b/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
index 1e038d1..c883385 100644
--- a/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
+++ b/services/surfaceflinger/Scheduler/tests/FrameTargeterTest.cpp
@@ -17,23 +17,29 @@
#include <ftl/optional.h>
#include <gtest/gtest.h>
+#include <common/test/FlagUtils.h>
#include <scheduler/Fps.h>
#include <scheduler/FrameTargeter.h>
#include <scheduler/IVsyncSource.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
+
using namespace std::chrono_literals;
namespace android::scheduler {
namespace {
struct VsyncSource final : IVsyncSource {
- VsyncSource(Period period, TimePoint deadline) : vsyncPeriod(period), vsyncDeadline(deadline) {}
+ VsyncSource(Period period, Period minFramePeriod, TimePoint deadline)
+ : vsyncPeriod(period), framePeriod(minFramePeriod), vsyncDeadline(deadline) {}
const Period vsyncPeriod;
+ const Period framePeriod;
const TimePoint vsyncDeadline;
Period period() const override { return vsyncPeriod; }
TimePoint vsyncDeadlineAfter(TimePoint) const override { return vsyncDeadline; }
+ Period minFramePeriod() const override { return framePeriod; }
};
} // namespace
@@ -44,10 +50,13 @@
struct Frame {
Frame(FrameTargeterTest* testPtr, VsyncId vsyncId, TimePoint& frameBeginTime,
- Duration frameDuration, Fps refreshRate,
+ Duration frameDuration, Fps refreshRate, Fps peakRefreshRate,
FrameTargeter::IsFencePendingFuncPtr isFencePendingFuncPtr = Frame::fenceSignaled,
const ftl::Optional<VsyncSource>& vsyncSourceOpt = std::nullopt)
- : testPtr(testPtr), frameBeginTime(frameBeginTime), period(refreshRate.getPeriod()) {
+ : testPtr(testPtr),
+ frameBeginTime(frameBeginTime),
+ period(refreshRate.getPeriod()),
+ minFramePeriod(peakRefreshRate.getPeriod()) {
const FrameTargeter::BeginFrameArgs args{.frameBeginTime = frameBeginTime,
.vsyncId = vsyncId,
.expectedVsyncTime =
@@ -58,7 +67,7 @@
vsyncSourceOpt
.or_else([&] {
return std::make_optional(
- VsyncSource(period,
+ VsyncSource(period, period,
args.expectedVsyncTime));
})
.value(),
@@ -88,6 +97,7 @@
TimePoint& frameBeginTime;
const Period period;
+ const Period minFramePeriod;
bool ended = false;
};
@@ -103,7 +113,7 @@
VsyncId vsyncId{42};
{
TimePoint frameBeginTime(989ms);
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, 60_Hz);
+ const Frame frame(this, vsyncId++, frameBeginTime, 10ms, 60_Hz, 60_Hz);
EXPECT_EQ(target().vsyncId(), VsyncId{42});
EXPECT_EQ(target().frameBeginTime(), TimePoint(989ms));
@@ -112,7 +122,7 @@
}
{
TimePoint frameBeginTime(1100ms);
- const Frame frame(this, vsyncId++, frameBeginTime, 11ms, 60_Hz);
+ const Frame frame(this, vsyncId++, frameBeginTime, 11ms, 60_Hz, 60_Hz);
EXPECT_EQ(target().vsyncId(), VsyncId{43});
EXPECT_EQ(target().frameBeginTime(), TimePoint(1100ms));
@@ -127,9 +137,10 @@
TimePoint frameBeginTime(777ms);
constexpr Fps kRefreshRate = 120_Hz;
- const VsyncSource vsyncSource(kRefreshRate.getPeriod(), frameBeginTime + 5ms);
+ const VsyncSource vsyncSource(kRefreshRate.getPeriod(), kRefreshRate.getPeriod(),
+ frameBeginTime + 5ms);
const Frame frame(this, VsyncId{123}, frameBeginTime, kFrameDuration, kRefreshRate,
- Frame::fenceSignaled, vsyncSource);
+ kRefreshRate, Frame::fenceSignaled, vsyncSource);
EXPECT_EQ(target().expectedPresentTime(), vsyncSource.vsyncDeadline + vsyncSource.vsyncPeriod);
}
@@ -142,7 +153,7 @@
constexpr Duration kFrameDuration = 13ms;
for (int n = 5; n-- > 0;) {
- Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
const auto fence = frame.end();
EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - kPeriod);
@@ -160,7 +171,31 @@
FenceTimePtr previousFence = FenceTime::NO_FENCE;
for (int n = 5; n-- > 0;) {
- Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
+ const auto fence = frame.end();
+
+ EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
+ EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), previousFence);
+
+ previousFence = fence;
+ }
+}
+
+TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAheadVrr) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::vrr_config, true);
+
+ VsyncId vsyncId{222};
+ TimePoint frameBeginTime(2000ms);
+ constexpr Fps kRefreshRate = 120_Hz;
+ constexpr Fps kPeakRefreshRate = 240_Hz;
+ constexpr Period kPeriod = kRefreshRate.getPeriod();
+ constexpr Duration kFrameDuration = 10ms;
+
+ FenceTimePtr previousFence = FenceTime::NO_FENCE;
+
+ for (int n = 5; n-- > 0;) {
+ Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate,
+ kPeakRefreshRate);
const auto fence = frame.end();
EXPECT_EQ(target().pastVsyncTime(kPeriod), frameBeginTime + kFrameDuration - 2 * kPeriod);
@@ -184,12 +219,12 @@
// The target is not early while past present fences are pending.
for (int n = 3; n-- > 0;) {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
}
// The target is early if the past present fence was signaled.
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
const auto fence = frame.end();
fence->signalForTest(frameBeginTime.ns());
@@ -204,18 +239,18 @@
// The target is not early while past present fences are pending.
for (int n = 3; n-- > 0;) {
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
}
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
const auto fence = frame.end();
fence->signalForTest(frameBeginTime.ns());
// The target is two VSYNCs ahead, so the past present fence is still pending.
EXPECT_FALSE(target().wouldPresentEarly(kPeriod));
- { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate); }
+ { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate); }
// The target is early if the past present fence was signaled.
EXPECT_TRUE(target().wouldPresentEarly(kPeriod));
@@ -226,7 +261,7 @@
constexpr Fps kRefreshRate = 144_Hz;
constexpr Period kPeriod = kRefreshRate.getPeriod();
- const Frame frame(this, VsyncId{555}, frameBeginTime, 16ms, kRefreshRate);
+ const Frame frame(this, VsyncId{555}, frameBeginTime, 16ms, kRefreshRate, kRefreshRate);
// The target is more than two VSYNCs ahead, but present fences are not tracked that far back.
EXPECT_TRUE(target().wouldPresentEarly(kPeriod));
@@ -243,7 +278,7 @@
EXPECT_FALSE(target().didMissHwcFrame());
{
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().isFramePending());
// The frame did not miss if the past present fence is invalid.
@@ -251,7 +286,8 @@
EXPECT_FALSE(target().didMissHwcFrame());
}
{
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, Frame::fencePending);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate,
+ Frame::fencePending);
EXPECT_TRUE(target().isFramePending());
// The frame missed if the past present fence is pending.
@@ -261,7 +297,8 @@
frame.end(CompositionCoverage::Gpu);
}
{
- const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, Frame::fencePending);
+ const Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate,
+ Frame::fencePending);
EXPECT_TRUE(target().isFramePending());
// The GPU frame missed if the past present fence is pending.
@@ -269,7 +306,7 @@
EXPECT_FALSE(target().didMissHwcFrame());
}
{
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().isFramePending());
const auto fence = frame.end();
@@ -277,7 +314,7 @@
fence->signalForTest(expectedPresentTime.ns() + kPeriod.ns() / 2 + 1);
}
{
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().isFramePending());
const auto fence = frame.end();
@@ -289,7 +326,7 @@
EXPECT_TRUE(target().didMissHwcFrame());
}
{
- Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate);
+ Frame frame(this, vsyncId++, frameBeginTime, 10ms, kRefreshRate, kRefreshRate);
EXPECT_FALSE(target().isFramePending());
// The frame did not miss if the past present fence was signaled within slop.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2e70b22..89486a3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2671,16 +2671,16 @@
refreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::milliseconds(mDebugFlashDelay);
}
- const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
+ const Period minFramePeriod = mScheduler->getVsyncSchedule()->minFramePeriod();
if (!getHwComposer().getComposer()->isSupported(
Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
- pacesetterTarget.wouldPresentEarly(vsyncPeriod)) {
+ pacesetterTarget.wouldPresentEarly(minFramePeriod)) {
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
// TODO(b/255601557): Calculate and pass per-display values for each FrameTarget.
refreshArgs.earliestPresentTime =
- pacesetterTarget.previousFrameVsyncTime(vsyncPeriod) - hwcMinWorkDuration;
+ pacesetterTarget.previousFrameVsyncTime(minFramePeriod) - hwcMinWorkDuration;
}
refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
@@ -4703,7 +4703,7 @@
return false;
}
- const Duration earlyLatchVsyncThreshold = mScheduler->getVsyncSchedule()->period() / 2;
+ const Duration earlyLatchVsyncThreshold = mScheduler->getVsyncSchedule()->minFramePeriod() / 2;
return predictedPresentTime >= expectedPresentTime &&
predictedPresentTime - expectedPresentTime >= earlyLatchVsyncThreshold;
diff --git a/services/surfaceflinger/tests/unittests/FlagUtils.h b/services/surfaceflinger/common/include/common/test/FlagUtils.h
similarity index 100%
rename from services/surfaceflinger/tests/unittests/FlagUtils.h
rename to services/surfaceflinger/common/include/common/test/FlagUtils.h
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 101f04f..b690d8d 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -433,6 +433,7 @@
Period period() const { return getFuzzedDuration(fuzzer); }
TimePoint vsyncDeadlineAfter(TimePoint) const { return getFuzzedTimePoint(fuzzer); }
+ Period minFramePeriod() const { return period(); }
} vsyncSource{mFdp};
int i = 10;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
index 165de1d..2fca4cb 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
@@ -89,6 +89,7 @@
nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t /* timePoint */) const override { return 1; }
nsecs_t currentPeriod() const override { return 1; }
+ Period minFramePeriod() const override { return Period::fromNs(currentPeriod()); }
void resetModel() override {}
diff --git a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
index c040f29..803710d 100644
--- a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "FlagManagerTest"
#include <common/FlagManager.h>
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 6d87717..9dd1431 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "com_android_graphics_surfaceflinger_flags.h"
#include "gmock/gmock-spec-builders.h"
#include "mock/MockTimeStats.h"
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index f1e841b..4a22731 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -35,11 +35,11 @@
#include <log/log.h>
#include <chrono>
+#include <common/test/FlagUtils.h>
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
#include "DisplayIdentificationTestHelpers.h"
-#include "FlagUtils.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockHWC2.h"
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
index befef48..c1059d7 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
@@ -25,7 +25,7 @@
#include <renderengine/mock/FakeExternalTexture.h>
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "FpsOps.h"
#include "LayerHierarchyTest.h"
#include "Scheduler/LayerHistory.h"
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 1adf14f..c24d397 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -27,7 +27,7 @@
#include <gtest/gtest.h>
#include <log/log.h>
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "FpsOps.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/LayerInfo.h"
diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
index 047ef5a..07a522a 100644
--- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
@@ -21,7 +21,7 @@
#include <scheduler/Fps.h>
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "FpsOps.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/LayerInfo.h"
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index dc13a8d..a9567b2 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -26,6 +26,7 @@
#include <log/log.h>
#include <ui/Size.h>
+#include <common/test/FlagUtils.h>
#include <scheduler/Fps.h>
#include <scheduler/FrameRateMode.h>
#include "DisplayHardware/HWC2.h"
@@ -34,7 +35,6 @@
#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockFrameRateMode.h"
-#include "FlagUtils.h"
#include "libsurfaceflinger_unittest_main.h"
#include <com_android_graphics_surfaceflinger_flags.h>
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index 2188831..ca2f92a 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -49,6 +49,7 @@
}
nsecs_t currentPeriod() const final { return mPeriod; }
+ Period minFramePeriod() const final { return Period::fromNs(currentPeriod()); }
void resetModel() final {}
bool needsMoreSamples() const final { return false; }
@@ -88,6 +89,8 @@
return mPeriod;
}
+ Period minFramePeriod() const final { return Period::fromNs(currentPeriod()); }
+
void resetModel() final {}
bool needsMoreSamples() const final { return false; }
bool isVSyncInPhase(nsecs_t, Fps) const final { return false; }
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index b97ebba..2047018 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -30,7 +30,7 @@
#include <scheduler/TimeKeeper.h>
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "Scheduler/VSyncDispatchTimerQueue.h"
#include "Scheduler/VSyncTracker.h"
#include "mock/MockVSyncTracker.h"
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index 01f5af4..16aa249 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -23,7 +23,7 @@
#define LOG_TAG "LibSurfaceFlingerUnittests"
#define LOG_NDEBUG 0
-#include "FlagUtils.h"
+#include <common/test/FlagUtils.h>
#include "Scheduler/VSyncPredictor.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockVsyncTrackerCallback.h"
diff --git a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
index ec22b70..0858c28 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockVSyncTracker.h
@@ -30,6 +30,7 @@
MOCK_METHOD(bool, addVsyncTimestamp, (nsecs_t), (override));
MOCK_METHOD(nsecs_t, nextAnticipatedVSyncTimeFrom, (nsecs_t), (const, override));
MOCK_METHOD(nsecs_t, currentPeriod, (), (const, override));
+ MOCK_METHOD(Period, minFramePeriod, (), (const, override));
MOCK_METHOD(void, resetModel, (), (override));
MOCK_METHOD(bool, needsMoreSamples, (), (const, override));
MOCK_METHOD(bool, isVSyncInPhase, (nsecs_t, Fps), (const, override));