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);
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 06bbfd2..09ffb02 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -100,8 +100,9 @@
void SchedulerFuzzer::fuzzDispSyncSource() {
std::unique_ptr<FuzzImplVSyncDispatch> vSyncDispatch =
std::make_unique<FuzzImplVSyncDispatch>();
+ std::unique_ptr<FuzzImplVSyncTracker> vSyncTracker = std::make_unique<FuzzImplVSyncTracker>();
std::unique_ptr<scheduler::DispSyncSource> dispSyncSource = std::make_unique<
- scheduler::DispSyncSource>(*vSyncDispatch,
+ scheduler::DispSyncSource>(*vSyncDispatch, *vSyncTracker,
(std::chrono::nanoseconds)
mFdp.ConsumeIntegral<uint64_t>() /*workDuration*/,
(std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
index 89cf819..84b3912 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
@@ -103,6 +103,8 @@
void setDuration(std::chrono::nanoseconds /* workDuration */,
std::chrono::nanoseconds /* readyDuration */) override {}
+ VSyncData getLatestVSyncData() const override { return {}; }
+
void dump(std::string& /* result */) const override {}
};
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 7b86229..2ede830 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -31,6 +31,7 @@
"Credentials_test.cpp",
"DereferenceSurfaceControl_test.cpp",
"DisplayConfigs_test.cpp",
+ "DisplayEventReceiver_test.cpp",
"EffectLayer_test.cpp",
"InvalidHandles_test.cpp",
"LayerCallback_test.cpp",
diff --git a/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp b/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp
new file mode 100644
index 0000000..01adbc8
--- /dev/null
+++ b/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/DisplayEventReceiver.h>
+
+namespace android {
+
+class DisplayEventReceiverTest : public ::testing::Test {
+public:
+ void SetUp() override { EXPECT_EQ(NO_ERROR, mDisplayEventReceiver.initCheck()); }
+
+ DisplayEventReceiver mDisplayEventReceiver;
+};
+
+TEST_F(DisplayEventReceiverTest, getLatestVsyncEventData) {
+ const nsecs_t now = systemTime();
+ VsyncEventData vsyncEventData;
+ EXPECT_EQ(NO_ERROR, mDisplayEventReceiver.getLatestVsyncEventData(&vsyncEventData));
+
+ EXPECT_NE(std::numeric_limits<size_t>::max(), vsyncEventData.preferredFrameTimelineIndex);
+ EXPECT_GT(vsyncEventData.frameTimelines[0].deadlineTimestamp, now)
+ << "Deadline timestamp should be greater than frame time";
+ for (size_t i = 0; i < vsyncEventData.frameTimelines.size(); i++) {
+ EXPECT_NE(FrameTimelineInfo::INVALID_VSYNC_ID, vsyncEventData.frameTimelines[i].id);
+ EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentTime,
+ vsyncEventData.frameTimelines[i].deadlineTimestamp)
+ << "Expected vsync timestamp should be greater than deadline";
+ if (i > 0) {
+ EXPECT_GT(vsyncEventData.frameTimelines[i].deadlineTimestamp,
+ vsyncEventData.frameTimelines[i - 1].deadlineTimestamp)
+ << "Deadline timestamp out of order for frame timeline " << i;
+ EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentTime,
+ vsyncEventData.frameTimelines[i - 1].expectedPresentTime)
+ << "Expected vsync timestamp out of order for frame timeline " << i;
+ }
+ }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 5a0ea35..0b6b475 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -28,6 +28,7 @@
#include "AsyncCallRecorder.h"
#include "Scheduler/DispSyncSource.h"
#include "Scheduler/VSyncDispatch.h"
+#include "mock/MockVSyncTracker.h"
namespace android {
namespace {
@@ -125,12 +126,13 @@
DispSyncSourceTest();
~DispSyncSourceTest() override;
- void createDispSync();
+ void SetUp() override;
void createDispSyncSource();
void onVSyncEvent(nsecs_t when, VSyncSource::VSyncData) override;
std::unique_ptr<MockVSyncDispatch> mVSyncDispatch;
+ std::unique_ptr<mock::VSyncTracker> mVSyncTracker;
std::unique_ptr<scheduler::DispSyncSource> mDispSyncSource;
AsyncCallRecorder<void (*)(nsecs_t, VSyncSource::VSyncData)> mVSyncEventCallRecorder;
@@ -154,20 +156,21 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
+void DispSyncSourceTest::SetUp() {
+ mVSyncDispatch = std::make_unique<MockVSyncDispatch>();
+ mVSyncTracker = std::make_unique<mock::VSyncTracker>();
+}
+
void DispSyncSourceTest::onVSyncEvent(nsecs_t when, VSyncSource::VSyncData vsyncData) {
ALOGD("onVSyncEvent: %" PRId64, when);
mVSyncEventCallRecorder.recordCall(when, vsyncData);
}
-void DispSyncSourceTest::createDispSync() {
- mVSyncDispatch = std::make_unique<MockVSyncDispatch>();
-}
-
void DispSyncSourceTest::createDispSyncSource() {
- mDispSyncSource =
- std::make_unique<scheduler::DispSyncSource>(*mVSyncDispatch, mWorkDuration,
- mReadyDuration, true, mName.c_str());
+ mDispSyncSource = std::make_unique<scheduler::DispSyncSource>(*mVSyncDispatch, *mVSyncTracker,
+ mWorkDuration, mReadyDuration,
+ true, mName.c_str());
mDispSyncSource->setCallback(this);
}
@@ -176,13 +179,10 @@
*/
TEST_F(DispSyncSourceTest, createDispSync) {
- createDispSync();
EXPECT_TRUE(mVSyncDispatch);
}
TEST_F(DispSyncSourceTest, createDispSyncSource) {
- createDispSync();
-
InSequence seq;
EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).WillOnce(Return(mFakeToken));
EXPECT_CALL(*mVSyncDispatch, cancel(mFakeToken))
@@ -194,8 +194,6 @@
}
TEST_F(DispSyncSourceTest, noCallbackAfterInit) {
- createDispSync();
-
InSequence seq;
EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1);
EXPECT_CALL(*mVSyncDispatch, cancel(_)).Times(1);
@@ -210,8 +208,6 @@
}
TEST_F(DispSyncSourceTest, waitForCallbacks) {
- createDispSync();
-
InSequence seq;
EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1);
EXPECT_CALL(*mVSyncDispatch,
@@ -239,8 +235,6 @@
}
TEST_F(DispSyncSourceTest, waitForCallbacksWithDurationChange) {
- createDispSync();
-
InSequence seq;
EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1);
EXPECT_CALL(*mVSyncDispatch,
@@ -296,5 +290,27 @@
EXPECT_CALL(*mVSyncDispatch, unregisterCallback(_)).Times(1);
}
+TEST_F(DispSyncSourceTest, getLatestVsyncData) {
+ const nsecs_t now = systemTime();
+ const nsecs_t vsyncInternalDuration = mWorkDuration.count() + mReadyDuration.count();
+ EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_))
+ .WillOnce(Return(now + vsyncInternalDuration + 1));
+ {
+ InSequence seq;
+ EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1);
+ EXPECT_CALL(*mVSyncDispatch, cancel(_)).Times(1);
+ EXPECT_CALL(*mVSyncDispatch, unregisterCallback(_)).Times(1);
+ }
+
+ createDispSyncSource();
+ EXPECT_TRUE(mDispSyncSource);
+
+ const auto vsyncData = mDispSyncSource->getLatestVSyncData();
+ ASSERT_GT(vsyncData.deadlineTimestamp, now);
+ ASSERT_GT(vsyncData.expectedVSyncTimestamp, vsyncData.deadlineTimestamp);
+ EXPECT_EQ(vsyncData.deadlineTimestamp,
+ vsyncData.expectedVSyncTimestamp - vsyncInternalDuration);
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index e5f7b03..cc0a40f 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -59,6 +59,7 @@
void(std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration));
MOCK_METHOD1(pauseVsyncCallback, void(bool));
+ MOCK_METHOD(VSyncSource::VSyncData, getLatestVSyncData, (), (const, override));
MOCK_CONST_METHOD1(dump, void(std::string&));
};
@@ -257,7 +258,7 @@
ASSERT_TRUE(args.has_value()) << " did not receive an event for timestamp "
<< expectedTimestamp;
const auto& event = std::get<0>(args.value());
- for (int i = 0; i < gui::VsyncEventData::kFrameTimelinesLength; i++) {
+ for (int i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
auto prediction =
mTokenManager->getPredictionsForToken(event.vsync.frameTimelines[i].vsyncId);
EXPECT_TRUE(prediction.has_value());
@@ -332,6 +333,8 @@
namespace {
+using namespace testing;
+
/* ------------------------------------------------------------------------
* Test cases
*/
@@ -399,6 +402,52 @@
expectVsyncEventFrameTimelinesCorrect(123, 789);
}
+TEST_F(EventThreadTest, getLatestVsyncEventData) {
+ const nsecs_t now = systemTime();
+ const nsecs_t preferredDeadline = now + 10000000;
+ const nsecs_t preferredExpectedVSyncTimestamp = now + 20000000;
+ const VSyncSource::VSyncData preferredData = {preferredExpectedVSyncTimestamp,
+ preferredDeadline};
+ EXPECT_CALL(*mVSyncSource, getLatestVSyncData()).WillOnce(Return(preferredData));
+
+ VsyncEventData vsyncEventData = mThread->getLatestVsyncEventData(mConnection);
+ EXPECT_GT(vsyncEventData.frameTimelines[0].deadlineTimestamp, now)
+ << "Deadline timestamp should be greater than frame time";
+ for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
+ auto prediction =
+ mTokenManager->getPredictionsForToken(vsyncEventData.frameTimelines[i].id);
+ EXPECT_TRUE(prediction.has_value());
+ EXPECT_EQ(prediction.value().endTime, vsyncEventData.frameTimelines[i].deadlineTimestamp)
+ << "Deadline timestamp does not match cached value";
+ EXPECT_EQ(prediction.value().presentTime,
+ vsyncEventData.frameTimelines[i].expectedPresentTime)
+ << "Expected vsync timestamp does not match cached value";
+ EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentTime,
+ vsyncEventData.frameTimelines[i].deadlineTimestamp)
+ << "Expected vsync timestamp should be greater than deadline";
+
+ if (i > 0) {
+ EXPECT_GT(vsyncEventData.frameTimelines[i].deadlineTimestamp,
+ vsyncEventData.frameTimelines[i - 1].deadlineTimestamp)
+ << "Deadline timestamp out of order for frame timeline " << i;
+ EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentTime,
+ vsyncEventData.frameTimelines[i - 1].expectedPresentTime)
+ << "Expected vsync timestamp out of order for frame timeline " << i;
+ }
+
+ // Vsync ID order lines up with registration into test token manager.
+ EXPECT_EQ(i, vsyncEventData.frameTimelines[i].id)
+ << "Vsync ID incorrect for frame timeline " << i;
+ if (i == vsyncEventData.preferredFrameTimelineIndex) {
+ EXPECT_EQ(vsyncEventData.frameTimelines[i].deadlineTimestamp, preferredDeadline)
+ << "Preferred deadline timestamp incorrect" << i;
+ EXPECT_EQ(vsyncEventData.frameTimelines[i].expectedPresentTime,
+ preferredExpectedVSyncTimestamp)
+ << "Preferred expected vsync timestamp incorrect" << i;
+ }
+ }
+}
+
TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
// Create a first connection, register it, and request a vsync rate of zero.
ConnectionEventRecorder firstConnectionEventRecorder{0};
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index d25973e..c5ca86a 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -44,6 +44,8 @@
status_t(const sp<android::EventThreadConnection> &));
MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &));
MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &));
+ MOCK_METHOD(VsyncEventData, getLatestVsyncEventData,
+ (const sp<android::EventThreadConnection> &), (const));
MOCK_METHOD1(requestLatestConfig, void(const sp<android::EventThreadConnection> &));
MOCK_METHOD1(pauseVsyncCallback, void(bool));
MOCK_METHOD0(getEventThreadConnectionCount, size_t());