Add method to get current vsync from sf directly.
Bug: 205721584
Test: atest libsurfaceflinger_unittest
Test: atest DisplayEventReceiverTest
Change-Id: I38d4bd20bc2f2ad7ff964c3d613c28919478c0fc
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index c593340..747032b 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -23,6 +23,7 @@
#include <mutex>
#include "EventThread.h"
+#include "VSyncTracker.h"
#include "VsyncController.h"
namespace android::scheduler {
@@ -114,7 +115,7 @@
std::chrono::nanoseconds mLastCallTime GUARDED_BY(mMutex) = 0ns;
};
-DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,
+DispSyncSource::DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration, bool traceVsync,
const char* name)
@@ -122,6 +123,7 @@
mValue(base::StringPrintf("VSYNC-%s", name), 0),
mTraceVsync(traceVsync),
mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
+ mVSyncTracker(vSyncTracker),
mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
mReadyDuration(readyDuration) {
mCallbackRepeater =
@@ -184,6 +186,14 @@
}
}
+VSyncSource::VSyncData DispSyncSource::getLatestVSyncData() const {
+ std::lock_guard lock(mVsyncMutex);
+ nsecs_t expectedPresentTime = mVSyncTracker.nextAnticipatedVSyncTimeFrom(
+ systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
+ nsecs_t deadline = expectedPresentTime - mWorkDuration.get().count() - mReadyDuration.count();
+ return {expectedPresentTime, deadline};
+}
+
void DispSyncSource::dump(std::string& result) const {
std::lock_guard lock(mVsyncMutex);
StringAppendF(&result, "DispSyncSource: %s(%s)\n", mName, mEnabled ? "enabled" : "disabled");
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 2fce235..edcd3ac 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -24,11 +24,13 @@
namespace android::scheduler {
class CallbackRepeater;
+class VSyncTracker;
class DispSyncSource final : public VSyncSource {
public:
- DispSyncSource(VSyncDispatch& vSyncDispatch, std::chrono::nanoseconds workDuration,
- std::chrono::nanoseconds readyDuration, bool traceVsync, const char* name);
+ DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
+ std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
+ bool traceVsync, const char* name);
~DispSyncSource() override;
@@ -38,6 +40,7 @@
void setCallback(VSyncSource::Callback* callback) override;
void setDuration(std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) override;
+ VSyncData getLatestVSyncData() const override;
void dump(std::string&) const override;
@@ -50,6 +53,8 @@
const bool mTraceVsync;
const std::string mVsyncOnLabel;
+ const VSyncTracker& mVSyncTracker;
+
std::unique_ptr<CallbackRepeater> mCallbackRepeater;
std::mutex mCallbackMutex;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index adc1009..2d0da46 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -181,11 +181,17 @@
}
binder::Status EventThreadConnection::requestNextVsync() {
- ATRACE_NAME("requestNextVsync");
+ ATRACE_CALL();
mEventThread->requestNextVsync(this);
return binder::Status::ok();
}
+binder::Status EventThreadConnection::getLatestVsyncEventData(VsyncEventData* outVsyncEventData) {
+ ATRACE_CALL();
+ *outVsyncEventData = mEventThread->getLatestVsyncEventData(this);
+ return binder::Status::ok();
+}
+
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
constexpr auto toStatus = [](ssize_t size) {
return size < 0 ? status_t(size) : status_t(NO_ERROR);
@@ -330,6 +336,15 @@
}
}
+VsyncEventData EventThread::getLatestVsyncEventData(
+ const sp<EventThreadConnection>& connection) const {
+ nsecs_t frameInterval = mGetVsyncPeriodFunction(connection->mOwnerUid);
+ VsyncEventData vsyncEventData;
+ vsyncEventData.frameInterval = frameInterval;
+ generateFrameTimeline(vsyncEventData, frameInterval, systemTime(SYSTEM_TIME_MONOTONIC));
+ return vsyncEventData;
+}
+
void EventThread::onScreenReleased() {
std::lock_guard<std::mutex> lock(mMutex);
if (!mVSyncState || mVSyncState->synthetic) {
@@ -561,27 +576,64 @@
return FrameTimelineInfo::INVALID_VSYNC_ID;
}
-void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const {
+void EventThread::generateFrameTimeline(
+ nsecs_t frameInterval, nsecs_t timestamp, nsecs_t preferredExpectedVSyncTimestamp,
+ nsecs_t preferredDeadlineTimestamp,
+ std::function<void(int64_t index)> setPreferredFrameTimelineIndex,
+ std::function<void(int64_t index, int64_t vsyncId, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp)>
+ setFrameTimeline) const {
// Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included.
- for (int multiplier = -VsyncEventData::kFrameTimelinesLength + 1, currentIndex = 0;
+ for (int64_t multiplier = -VsyncEventData::kFrameTimelinesLength + 1, currentIndex = 0;
currentIndex < VsyncEventData::kFrameTimelinesLength; multiplier++) {
- nsecs_t deadline = event.vsync.deadlineTimestamp + multiplier * event.vsync.frameInterval;
+ nsecs_t deadline = preferredDeadlineTimestamp + multiplier * frameInterval;
// Valid possible frame timelines must have future values.
- if (deadline > event.header.timestamp) {
+ if (deadline > timestamp) {
if (multiplier == 0) {
- event.vsync.preferredFrameTimelineIndex = currentIndex;
+ setPreferredFrameTimelineIndex(currentIndex);
}
- nsecs_t expectedVSync =
- event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval;
- event.vsync.frameTimelines[currentIndex] =
- {.vsyncId = generateToken(event.header.timestamp, deadline, expectedVSync),
- .deadlineTimestamp = deadline,
- .expectedVSyncTimestamp = expectedVSync};
+ nsecs_t expectedVSyncTimestamp =
+ preferredExpectedVSyncTimestamp + multiplier * frameInterval;
+ setFrameTimeline(currentIndex,
+ generateToken(timestamp, deadline, expectedVSyncTimestamp),
+ expectedVSyncTimestamp, deadline);
currentIndex++;
}
}
}
+void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const {
+ generateFrameTimeline(
+ event.vsync.frameInterval, event.header.timestamp, event.vsync.expectedVSyncTimestamp,
+ event.vsync.deadlineTimestamp,
+ [&](int index) { event.vsync.preferredFrameTimelineIndex = index; },
+ [&](int64_t index, int64_t vsyncId, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp) {
+ event.vsync.frameTimelines[index] = {.vsyncId = vsyncId,
+ .deadlineTimestamp = deadlineTimestamp,
+ .expectedVSyncTimestamp =
+ expectedVSyncTimestamp};
+ });
+}
+
+void EventThread::generateFrameTimeline(VsyncEventData& out, const nsecs_t frameInterval,
+ const nsecs_t timestamp) const {
+ VSyncSource::VSyncData vsyncData;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ vsyncData = mVSyncSource->getLatestVSyncData();
+ }
+ generateFrameTimeline(
+ frameInterval, timestamp, vsyncData.expectedVSyncTimestamp, vsyncData.deadlineTimestamp,
+ [&](int index) { out.preferredFrameTimelineIndex = index; },
+ [&](int64_t index, int64_t vsyncId, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp) {
+ out.frameTimelines[index] =
+ VsyncEventData::FrameTimeline(vsyncId, deadlineTimestamp,
+ expectedVSyncTimestamp);
+ });
+}
+
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index c3b9129..a858169 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -45,6 +45,8 @@
class TokenManager;
} // namespace frametimeline
+using gui::VsyncEventData;
+
// ---------------------------------------------------------------------------
using ResyncCallback = std::function<void()>;
@@ -81,6 +83,7 @@
virtual void setCallback(Callback* callback) = 0;
virtual void setDuration(std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) = 0;
+ virtual VSyncData getLatestVSyncData() const = 0;
virtual void dump(std::string& result) const = 0;
};
@@ -96,6 +99,7 @@
binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
binder::Status setVsyncRate(int rate) override;
binder::Status requestNextVsync() override; // asynchronous
+ binder::Status getLatestVsyncEventData(VsyncEventData* outVsyncEventData) override;
// Called in response to requestNextVsync.
const ResyncCallback resyncCallback;
@@ -145,6 +149,8 @@
virtual void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) = 0;
// Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
+ virtual VsyncEventData getLatestVsyncEventData(
+ const sp<EventThreadConnection>& connection) const = 0;
// Retrieves the number of event connections tracked by this EventThread.
virtual size_t getEventThreadConnectionCount() = 0;
@@ -169,6 +175,8 @@
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
void requestNextVsync(const sp<EventThreadConnection>& connection) override;
+ VsyncEventData getLatestVsyncEventData(
+ const sp<EventThreadConnection>& connection) const override;
// called before the screen is turned off from main thread
void onScreenReleased() override;
@@ -211,6 +219,15 @@
int64_t generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp,
nsecs_t expectedVSyncTimestamp) const;
void generateFrameTimeline(DisplayEventReceiver::Event& event) const;
+ void generateFrameTimeline(VsyncEventData& out, const nsecs_t frameInterval,
+ const nsecs_t timestamp) const;
+ void generateFrameTimeline(
+ nsecs_t frameInterval, nsecs_t timestamp, nsecs_t preferredExpectedVSyncTimestamp,
+ nsecs_t preferredDeadlineTimestamp,
+ std::function<void(int64_t index)> setPreferredFrameTimelineIndex,
+ std::function<void(int64_t index, int64_t vsyncId, nsecs_t expectedVSyncTimestamp,
+ nsecs_t deadlineTimestamp)>
+ setFrameTimeline) const;
const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex);
frametimeline::TokenManager* const mTokenManager;
diff --git a/services/surfaceflinger/Scheduler/InjectVSyncSource.h b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
index 7b93f1e..760a4ee 100644
--- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h
+++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h
@@ -46,6 +46,7 @@
const char* getName() const override { return "inject"; }
void setVSyncEnabled(bool) override {}
void setDuration(std::chrono::nanoseconds, std::chrono::nanoseconds) override {}
+ VSyncData getLatestVSyncData() const override { return {}; }
void dump(std::string&) const override {}
private:
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 665d36982..de27bd1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -134,7 +134,8 @@
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
const char* name, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration, bool traceVsync) {
- return std::make_unique<scheduler::DispSyncSource>(getVsyncDispatch(), workDuration,
+ return std::make_unique<scheduler::DispSyncSource>(mVsyncSchedule->getDispatch(),
+ mVsyncSchedule->getTracker(), workDuration,
readyDuration, traceVsync, name);
}