[SF] Adds callback from the VsyncPredictor
Hooks up the NotifyExpectedPresentIfRequired with
expectedPresentTime
BUG: 296636253
BUG: 284845445
Test: atest HWComposerTest
Change-Id: Idfd30929a0f4931b1a9f943340932c655ddd5903
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1a8713d..d3db523 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -67,11 +67,12 @@
namespace android::scheduler {
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
- sp<VsyncModulator> modulatorPtr)
+ sp<VsyncModulator> modulatorPtr, IVsyncTrackerCallback& vsyncTrackerCallback)
: impl::MessageQueue(compositor),
mFeatures(features),
mVsyncModulator(std::move(modulatorPtr)),
- mSchedulerCallback(callback) {}
+ mSchedulerCallback(callback),
+ mVsyncTrackerCallback(vsyncTrackerCallback) {}
Scheduler::~Scheduler() {
// MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -116,10 +117,10 @@
}
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
- auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures,
- [this](PhysicalDisplayId id, bool enable) {
- onHardwareVsyncRequest(id, enable);
- });
+ auto schedulePtr = std::make_shared<VsyncSchedule>(
+ displayId, mFeatures,
+ [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); },
+ mVsyncTrackerCallback);
registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}
@@ -562,7 +563,19 @@
ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
to_string(mode.modePtr->getVsyncRate()).c_str());
- display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
+ display.schedulePtr->getTracker().setDisplayModeData(
+ {.renderRate = renderFrameRate,
+ .notifyExpectedPresentTimeoutOpt = getNotifyExpectedPresentTimeout(mode)});
+}
+
+std::optional<Period> Scheduler::getNotifyExpectedPresentTimeout(const FrameRateMode& mode) {
+ if (mode.modePtr->getVrrConfig() && mode.modePtr->getVrrConfig()->notifyExpectedPresentConfig) {
+ return Period::fromNs(
+ mode.modePtr->getVrrConfig()
+ ->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs);
+ } else {
+ return std::nullopt;
+ }
}
void Scheduler::resync() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index b0520a6..a5a5e8d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -102,7 +102,8 @@
using Impl = android::impl::MessageQueue;
public:
- Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>);
+ Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>,
+ IVsyncTrackerCallback&);
virtual ~Scheduler();
void startTimers();
@@ -429,6 +430,9 @@
Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
void resync() override EXCLUDES(mDisplayLock);
+ std::optional<Period> getNotifyExpectedPresentTimeout(const FrameRateMode&)
+ REQUIRES(mDisplayLock);
+
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
@@ -462,6 +466,8 @@
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 e969fdc..799466b 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -35,6 +35,7 @@
#include <gui/TraceUtils.h>
#include <utils/Log.h>
+#include "FlagManager.h"
#include "RefreshRateSelector.h"
#include "VSyncPredictor.h"
@@ -47,12 +48,14 @@
VSyncPredictor::~VSyncPredictor() = default;
VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
- size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
+ size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
+ IVsyncTrackerCallback& callback)
: mId(id),
mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
kHistorySize(historySize),
kMinimumSamplesForPrediction(minimumSamplesForPrediction),
kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
+ mVsyncTrackerCallback(callback),
mIdealPeriod(idealPeriod) {
resetModel();
}
@@ -275,11 +278,11 @@
mLastVsyncSequence = getVsyncSequenceLocked(timePoint);
const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
- if (!mRenderRate) return 0;
+ if (!mDisplayModeDataOpt) return 0;
const auto divisor =
RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod),
- *mRenderRate);
+ mDisplayModeDataOpt->renderRate);
if (divisor <= 1) return 0;
const int mod = mLastVsyncSequence->seq % divisor;
@@ -289,12 +292,24 @@
}();
if (renderRatePhase == 0) {
- return mLastVsyncSequence->vsyncTime;
+ const auto vsyncTime = mLastVsyncSequence->vsyncTime;
+ if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+ mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(vsyncTime),
+ *mDisplayModeDataOpt,
+ Period::fromNs(mIdealPeriod));
+ }
+ return vsyncTime;
}
auto const [slope, intercept] = getVSyncPredictionModelLocked();
const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
- return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
+ const auto nextAnticipatedVsyncTime =
+ nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
+ if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
+ mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(nextAnticipatedVsyncTime),
+ *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod));
+ }
+ return nextAnticipatedVsyncTime;
}
/*
@@ -332,10 +347,14 @@
return vsyncSequence.seq % divisor == 0;
}
-void VSyncPredictor::setRenderRate(Fps fps) {
- ALOGV("%s %s: %s", __func__, to_string(mId).c_str(), to_string(fps).c_str());
+void VSyncPredictor::setDisplayModeData(const DisplayModeData& displayModeData) {
+ ALOGV("%s %s: RenderRate %s notifyExpectedPresentTimeout %s", __func__, to_string(mId).c_str(),
+ to_string(displayModeData.renderRate).c_str(),
+ displayModeData.notifyExpectedPresentTimeoutOpt
+ ? std::to_string(displayModeData.notifyExpectedPresentTimeoutOpt->ns()).c_str()
+ : "N/A");
std::lock_guard lock(mMutex);
- mRenderRate = fps;
+ mDisplayModeDataOpt = displayModeData;
}
VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const {
@@ -358,6 +377,7 @@
mRateMap.erase(mRateMap.begin());
}
+ // TODO(b/308610306) mIdealPeriod to be updated with setDisplayModeData
mIdealPeriod = period;
if (mRateMap.find(period) == mRateMap.end()) {
mRateMap[mIdealPeriod] = {period, 0};
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index c01c44d..c271eb7 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -36,9 +36,11 @@
* \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(PhysicalDisplayId, nsecs_t idealPeriod, size_t historySize,
- size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
+ size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
+ IVsyncTrackerCallback&);
~VSyncPredictor();
bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
@@ -69,7 +71,7 @@
bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);
- void setRenderRate(Fps) final EXCLUDES(mMutex);
+ void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex);
void dump(std::string& result) const final EXCLUDES(mMutex);
@@ -99,6 +101,7 @@
size_t const kHistorySize;
size_t const kMinimumSamplesForPrediction;
size_t const kOutlierTolerancePercent;
+ IVsyncTrackerCallback& mVsyncTrackerCallback;
std::mutex mutable mMutex;
nsecs_t mIdealPeriod GUARDED_BY(mMutex);
@@ -110,7 +113,7 @@
size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
- std::optional<Fps> mRenderRate GUARDED_BY(mMutex);
+ std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex);
mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex);
};
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index bc0e3bc..7eedc31 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -16,6 +16,7 @@
#pragma once
+#include <ui/DisplayId.h>
#include <utils/Timers.h>
#include <scheduler/Fps.h>
@@ -23,6 +24,23 @@
#include "VSyncDispatch.h"
namespace android::scheduler {
+
+struct DisplayModeData {
+ Fps renderRate;
+ std::optional<Period> notifyExpectedPresentTimeoutOpt;
+
+ bool operator==(const DisplayModeData& other) const {
+ return isApproxEqual(renderRate, other.renderRate) &&
+ notifyExpectedPresentTimeoutOpt == other.notifyExpectedPresentTimeoutOpt;
+ }
+};
+
+struct IVsyncTrackerCallback {
+ virtual ~IVsyncTrackerCallback() = default;
+ virtual void onVsyncGenerated(PhysicalDisplayId, TimePoint expectedPresentTime,
+ const DisplayModeData&, Period vsyncPeriod) = 0;
+};
+
/*
* VSyncTracker is an interface for providing estimates on future Vsync signal times based on
* historical vsync timing data.
@@ -80,16 +98,20 @@
virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 0;
/*
- * Sets a render rate on the tracker. If the render rate is not a divisor
- * of the period, the render rate is ignored until the period changes.
+ * Sets the metadata about the currently active display mode such as VRR
+ * timeout period, vsyncPeriod and framework property such as render rate.
+ * If the render rate is not a divisor of the period, the render rate is
+ * ignored until the period changes.
* The tracker will continue to track the vsync timeline and expect it
* to match the current period, however, nextAnticipatedVSyncTimeFrom will
* return vsyncs according to the render rate set. Setting a render rate is useful
* when a display is running at 120Hz but the render frame rate is 60Hz.
+ * When IVsyncTrackerCallback::onVsyncGenerated callback is made we will pass along
+ * the vsyncPeriod, render rate and timeoutNs.
*
- * \param [in] Fps The render rate the tracker should operate at.
+ * \param [in] DisplayModeData The DisplayModeData the tracker will use.
*/
- virtual void setRenderRate(Fps) = 0;
+ virtual void setDisplayModeData(const DisplayModeData&) = 0;
virtual void dump(std::string& result) const = 0;
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index ff3f29d..5fb53f9 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -54,10 +54,11 @@
};
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
- RequestHardwareVsync requestHardwareVsync)
+ RequestHardwareVsync requestHardwareVsync,
+ IVsyncTrackerCallback& callback)
: mId(id),
mRequestHardwareVsync(std::move(requestHardwareVsync)),
- mTracker(createTracker(id)),
+ mTracker(createTracker(id, callback)),
mDispatch(createDispatch(mTracker)),
mController(createController(id, *mTracker, features)),
mTracer(features.test(Feature::kTracePredictedVsync)
@@ -100,7 +101,8 @@
mDispatch->dump(out);
}
-VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
+VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id,
+ IVsyncTrackerCallback& callback) {
// TODO(b/144707443): Tune constants.
constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
constexpr size_t kHistorySize = 20;
@@ -108,7 +110,8 @@
constexpr uint32_t kDiscardOutlierPercent = 20;
return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
- kMinSamplesForPrediction, kDiscardOutlierPercent);
+ kMinSamplesForPrediction, kDiscardOutlierPercent,
+ callback);
}
VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 47e92e1..ca61f87 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -31,6 +31,7 @@
#include <scheduler/Time.h>
#include "ThreadContext.h"
+#include "VSyncTracker.h"
namespace android {
class EventThreadTest;
@@ -56,7 +57,7 @@
public:
using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
- VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync);
+ VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync, IVsyncTrackerCallback&);
~VsyncSchedule();
// IVsyncSource overrides:
@@ -124,7 +125,7 @@
friend class android::VsyncScheduleTest;
friend class android::fuzz::SchedulerFuzzer;
- static TrackerPtr createTracker(PhysicalDisplayId);
+ static TrackerPtr createTracker(PhysicalDisplayId, IVsyncTrackerCallback&);
static DispatchPtr createDispatch(TrackerPtr);
static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);