[SF] Updates to not send hints without a present being followed
Updates the hint to be sent through a frame scheduling.
Reduce the number of callbacks to notifyExpectedPresentIfRequired
by making calls only through EventThread.
Timeout hint is sent directly without scheduling a frame
to avoid delay in sending the hint.
A hint through setTransactionState for ScheduleOnTx will
be in a follow up CL
BUG: 316615878
Test: atest NotifyExpectedPresentTest
Change-Id: I60f555d69626656901951808353f4a632e9b5e71
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c80c8fd..ccd1c0f 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -404,6 +404,9 @@
}();
generateFrameTimeline(vsyncEventData, frameInterval.ns(), systemTime(SYSTEM_TIME_MONOTONIC),
presentTime, deadline);
+ if (FlagManager::getInstance().vrr_config()) {
+ mCallback.onExpectedPresentTimePosted(TimePoint::fromNs(presentTime));
+ }
return vsyncEventData;
}
@@ -721,6 +724,11 @@
removeDisplayEventConnectionLocked(consumer);
}
}
+ if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC &&
+ FlagManager::getInstance().vrr_config()) {
+ mCallback.onExpectedPresentTimePosted(
+ TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime()));
+ }
}
void EventThread::dump(std::string& result) const {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 8970103..90e61a9 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -142,6 +142,7 @@
virtual bool throttleVsync(TimePoint, uid_t) = 0;
virtual Period getVsyncPeriod(uid_t) = 0;
virtual void resync() = 0;
+ virtual void onExpectedPresentTimePosted(TimePoint) = 0;
};
namespace impl {
diff --git a/services/surfaceflinger/Scheduler/ISchedulerCallback.h b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
index 3b61de7..9f4f5b6 100644
--- a/services/surfaceflinger/Scheduler/ISchedulerCallback.h
+++ b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
@@ -30,6 +30,8 @@
virtual void kernelTimerChanged(bool expired) = 0;
virtual void triggerOnFrameRateOverridesChanged() = 0;
virtual void onChoreographerAttached() = 0;
+ virtual void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>,
+ Fps renderRate) = 0;
protected:
~ISchedulerCallback() = default;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index fff97f7..ce47c8d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -71,15 +71,13 @@
namespace android::scheduler {
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
- surfaceflinger::Factory& factory, Fps activeRefreshRate, TimeStats& timeStats,
- IVsyncTrackerCallback& vsyncTrackerCallback)
+ surfaceflinger::Factory& factory, Fps activeRefreshRate, TimeStats& timeStats)
: android::impl::MessageQueue(compositor),
mFeatures(features),
mVsyncConfiguration(factory.createVsyncConfiguration(activeRefreshRate)),
mVsyncModulator(sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs())),
mRefreshRateStats(std::make_unique<RefreshRateStats>(timeStats, activeRefreshRate)),
- mSchedulerCallback(callback),
- mVsyncTrackerCallback(vsyncTrackerCallback) {}
+ mSchedulerCallback(callback) {}
Scheduler::~Scheduler() {
// MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -134,10 +132,11 @@
}
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
- auto schedulePtr = std::make_shared<VsyncSchedule>(
- selectorPtr->getActiveMode().modePtr, mFeatures,
- [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); },
- mVsyncTrackerCallback);
+ auto schedulePtr =
+ std::make_shared<VsyncSchedule>(selectorPtr->getActiveMode().modePtr, mFeatures,
+ [this](PhysicalDisplayId id, bool enable) {
+ onHardwareVsyncRequest(id, enable);
+ });
registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}
@@ -222,7 +221,12 @@
targets.try_emplace(id, &targeter.target());
}
- if (!compositor.commit(pacesetterPtr->displayId, targets)) return;
+ if (!compositor.commit(pacesetterPtr->displayId, targets)) {
+ if (FlagManager::getInstance().vrr_config()) {
+ compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
+ }
+ return;
+ }
}
// The pacesetter may have changed or been registered anew during commit.
@@ -263,6 +267,9 @@
}
const auto resultsPerDisplay = compositor.composite(pacesetterPtr->displayId, targeters);
+ if (FlagManager::getInstance().vrr_config()) {
+ compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
+ }
compositor.sample();
for (const auto& [id, targeter] : targeters) {
@@ -323,6 +330,19 @@
// behaviour.
return Period::fromNs(currentPeriod.ns() * divisor);
}
+void Scheduler::onExpectedPresentTimePosted(TimePoint expectedPresentTime) {
+ const auto frameRateMode = [this] {
+ std::scoped_lock lock(mDisplayLock);
+ const auto pacesetterOpt = pacesetterDisplayLocked();
+ const Display& pacesetter = *pacesetterOpt;
+ return pacesetter.selectorPtr->getActiveMode();
+ }();
+
+ if (frameRateMode.modePtr->getVrrConfig()) {
+ mSchedulerCallback.onExpectedPresentTimePosted(expectedPresentTime, frameRateMode.modePtr,
+ frameRateMode.fps);
+ }
+}
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
frametimeline::TokenManager* tokenManager,
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 9912622..9f29e9f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -111,7 +111,7 @@
public:
Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, surfaceflinger::Factory&,
- Fps activeRefreshRate, TimeStats&, IVsyncTrackerCallback&);
+ Fps activeRefreshRate, TimeStats&);
virtual ~Scheduler();
void startTimers();
@@ -458,6 +458,7 @@
bool throttleVsync(TimePoint, uid_t) override;
Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
void resync() override EXCLUDES(mDisplayLock);
+ void onExpectedPresentTimePosted(TimePoint expectedPresentTime) override EXCLUDES(mDisplayLock);
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
@@ -497,8 +498,6 @@
ISchedulerCallback& mSchedulerCallback;
- IVsyncTrackerCallback& mVsyncTrackerCallback;
-
// mDisplayLock may be locked while under mPolicyLock.
mutable std::mutex mPolicyLock;
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 6e12b33..8697696 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -48,14 +48,12 @@
VSyncPredictor::~VSyncPredictor() = default;
VSyncPredictor::VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
- size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
- IVsyncTrackerCallback& callback)
+ size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
: mId(modePtr->getPhysicalDisplayId()),
mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
kHistorySize(historySize),
kMinimumSamplesForPrediction(minimumSamplesForPrediction),
kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
- mVsyncTrackerCallback(callback),
mDisplayModePtr(modePtr) {
resetModel();
}
@@ -312,13 +310,7 @@
FlagManager::getInstance().vrr_config() && !lastFrameMissed && lastVsyncOpt
? std::max(timePoint, *lastVsyncOpt + minFramePeriod - threshold)
: timePoint;
- const auto vsyncTime = snapToVsyncAlignedWithRenderRate(baseTime);
- if (FlagManager::getInstance().vrr_config() && mDisplayModePtr->getVrrConfig()) {
- const auto vsyncTimePoint = TimePoint::fromNs(vsyncTime);
- const Fps renderRate = mRenderRateOpt ? *mRenderRateOpt : mDisplayModePtr->getPeakFps();
- mVsyncTrackerCallback.onVsyncGenerated(vsyncTimePoint, mDisplayModePtr, renderRate);
- }
- return vsyncTime;
+ return snapToVsyncAlignedWithRenderRate(baseTime);
}
nsecs_t VSyncPredictor::snapToVsyncAlignedWithRenderRate(nsecs_t timePoint) const {
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 9191003..8fd7e60 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -37,11 +37,9 @@
* \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
* predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
* samples that fall outlierTolerancePercent from an anticipated vsync event.
- * \param [in] IVsyncTrackerCallback The callback for the VSyncTracker.
*/
VSyncPredictor(ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
- size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
- IVsyncTrackerCallback&);
+ size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
~VSyncPredictor();
bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
@@ -106,7 +104,6 @@
size_t const kHistorySize;
size_t const kMinimumSamplesForPrediction;
size_t const kOutlierTolerancePercent;
- IVsyncTrackerCallback& mVsyncTrackerCallback;
std::mutex mutable mMutex;
std::optional<nsecs_t> mKnownTimestamp GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 417163f..37bd4b4 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -26,12 +26,6 @@
namespace android::scheduler {
-struct IVsyncTrackerCallback {
- virtual ~IVsyncTrackerCallback() = default;
- virtual void onVsyncGenerated(TimePoint expectedPresentTime, ftl::NonNull<DisplayModePtr>,
- Fps renderRate) = 0;
-};
-
/*
* VSyncTracker is an interface for providing estimates on future Vsync signal times based on
* historical vsync timing data.
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index db6a187..1eeccd3 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -57,11 +57,10 @@
};
VsyncSchedule::VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags features,
- RequestHardwareVsync requestHardwareVsync,
- IVsyncTrackerCallback& callback)
+ RequestHardwareVsync requestHardwareVsync)
: mId(modePtr->getPhysicalDisplayId()),
mRequestHardwareVsync(std::move(requestHardwareVsync)),
- mTracker(createTracker(modePtr, callback)),
+ mTracker(createTracker(modePtr)),
mDispatch(createDispatch(mTracker)),
mController(createController(modePtr->getPhysicalDisplayId(), *mTracker, features)),
mTracer(features.test(Feature::kTracePredictedVsync)
@@ -111,15 +110,14 @@
mDispatch->dump(out);
}
-VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(ftl::NonNull<DisplayModePtr> modePtr,
- IVsyncTrackerCallback& callback) {
+VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(ftl::NonNull<DisplayModePtr> modePtr) {
// TODO(b/144707443): Tune constants.
constexpr size_t kHistorySize = 20;
constexpr size_t kMinSamplesForPrediction = 6;
constexpr uint32_t kDiscardOutlierPercent = 20;
return std::make_unique<VSyncPredictor>(modePtr, kHistorySize, kMinSamplesForPrediction,
- kDiscardOutlierPercent, callback);
+ kDiscardOutlierPercent);
}
VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 722ea0b..4ff4cdf 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -57,8 +57,7 @@
public:
using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
- VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync,
- IVsyncTrackerCallback&);
+ VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync);
~VsyncSchedule();
// IVsyncSource overrides:
@@ -127,7 +126,7 @@
friend class android::VsyncScheduleTest;
friend class android::fuzz::SchedulerFuzzer;
- static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr, IVsyncTrackerCallback&);
+ static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr);
static DispatchPtr createDispatch(TrackerPtr);
static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
index 12ee36e..8673a22 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h
@@ -47,6 +47,9 @@
virtual CompositeResultsPerDisplay composite(PhysicalDisplayId pacesetterId,
const scheduler::FrameTargeters&) = 0;
+ // Sends a hint about the expected present time
+ virtual void sendNotifyExpectedPresentHint(PhysicalDisplayId) = 0;
+
// Samples the composited frame via RegionSamplingThread.
virtual void sample() = 0;