diff options
author | 2022-02-01 14:51:34 -0800 | |
---|---|---|
committer | 2022-02-07 13:53:34 -0800 | |
commit | ef2e21fa7cdd37dbca56f98da49c5406ae7414d2 (patch) | |
tree | 340fe04b46a6a22c4e1147325a6c3acff34dca86 | |
parent | f16da3cb8f2f0517821bb7d121f380f6b3da01d3 (diff) |
Add method to get current vsync from sf directly.
Bug: 205721584
Test: atest libsurfaceflinger_unittest
Test: atest DisplayEventReceiverTest
Change-Id: I38d4bd20bc2f2ad7ff964c3d613c28919478c0fc
17 files changed, 290 insertions, 35 deletions
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index b916e48f79..36e7d80d5e 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -20,6 +20,7 @@ #include <gui/DisplayEventReceiver.h> #include <gui/ISurfaceComposer.h> +#include <gui/VsyncEventData.h> #include <private/gui/ComposerService.h> @@ -79,6 +80,20 @@ status_t DisplayEventReceiver::requestNextVsync() { return NO_INIT; } +status_t DisplayEventReceiver::getLatestVsyncEventData(VsyncEventData* outVsyncEventData) const { + if (mEventConnection != nullptr) { + VsyncEventData vsyncEventData; + auto status = mEventConnection->getLatestVsyncEventData(&vsyncEventData); + if (!status.isOk()) { + ALOGE("Failed to get latest vsync event data: %s", status.exceptionMessage().c_str()); + return status.transactionError(); + } + *outVsyncEventData = vsyncEventData; + return NO_ERROR; + } + return NO_INIT; +} + ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) { return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count); diff --git a/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl b/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl index 9f41593539..e9a6a0c642 100644 --- a/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl +++ b/libs/gui/aidl/android/gui/IDisplayEventConnection.aidl @@ -17,6 +17,7 @@ package android.gui; import android.gui.BitTube; +import android.gui.VsyncEventData; /** @hide */ interface IDisplayEventConnection { @@ -38,4 +39,9 @@ interface IDisplayEventConnection { * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0. */ oneway void requestNextVsync(); // Asynchronous + + /* + * getLatestVsyncEventData() gets the latest vsync event data. + */ + VsyncEventData getLatestVsyncEventData(); } diff --git a/libs/gui/aidl/android/gui/VsyncEventData.aidl b/libs/gui/aidl/android/gui/VsyncEventData.aidl new file mode 100644 index 0000000000..7343515d25 --- /dev/null +++ b/libs/gui/aidl/android/gui/VsyncEventData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2021 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. + */ + +package android.gui; + +parcelable VsyncEventData cpp_header "gui/VsyncEventData.h"; diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index db41c32549..4e04db3cde 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -172,6 +172,11 @@ public: */ status_t requestNextVsync(); + /** + * getLatestVsyncEventData() gets the latest vsync event data. + */ + status_t getLatestVsyncEventData(VsyncEventData* outVsyncEventData) const; + private: sp<IDisplayEventConnection> mEventConnection; std::unique_ptr<gui::BitTube> mDataChannel; diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp index c593340625..747032be0d 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 @@ private: 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 @@ DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch, 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 @@ void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime } } +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 2fce235546..edcd3ac709 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 @@ public: 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 @@ private: 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 adc1009731..2d0da4643d 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -181,11 +181,17 @@ binder::Status EventThreadConnection::setVsyncRate(int rate) { } 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 @@ void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) } } +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 @@ int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t deadlineTimestamp, 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 c3b9129744..a858169e65 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -45,6 +45,8 @@ namespace frametimeline { class TokenManager; } // namespace frametimeline +using gui::VsyncEventData; + // --------------------------------------------------------------------------- using ResyncCallback = std::function<void()>; @@ -81,6 +83,7 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ private: 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 7b93f1eb13..760a4ee886 100644 --- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h +++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h @@ -46,6 +46,7 @@ public: 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 665d36982a..de27bd1823 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -134,7 +134,8 @@ void Scheduler::createVsyncSchedule(FeatureFlags features) { 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 06bbfd26c2..09ffb02b21 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp @@ -100,8 +100,9 @@ void SchedulerFuzzer::fuzzEventThread() { 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 89cf819614..84b391246e 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h @@ -103,6 +103,8 @@ public: 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 7b86229556..2ede8309fb 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -31,6 +31,7 @@ cc_test { "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 0000000000..01adbc8962 --- /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 5a0ea352d5..0b6b475222 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 @@ protected: 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 @@ DispSyncSourceTest::~DispSyncSourceTest() { 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 @@ void DispSyncSourceTest::createDispSyncSource() { */ 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, createDispSyncSource) { } 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, noCallbackAfterInit) { } TEST_F(DispSyncSourceTest, waitForCallbacks) { - createDispSync(); - InSequence seq; EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1); EXPECT_CALL(*mVSyncDispatch, @@ -239,8 +235,6 @@ TEST_F(DispSyncSourceTest, waitForCallbacks) { } TEST_F(DispSyncSourceTest, waitForCallbacksWithDurationChange) { - createDispSync(); - InSequence seq; EXPECT_CALL(*mVSyncDispatch, registerCallback(_, mName)).Times(1); EXPECT_CALL(*mVSyncDispatch, @@ -296,5 +290,27 @@ TEST_F(DispSyncSourceTest, waitForCallbacksWithDurationChange) { 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 e5f7b03732..cc0a40f74b 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -59,6 +59,7 @@ public: 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 @@ void EventThreadTest::expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTime 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 @@ void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection( namespace { +using namespace testing; + /* ------------------------------------------------------------------------ * Test cases */ @@ -399,6 +402,52 @@ TEST_F(EventThreadTest, requestNextVsyncEventFrameTimelinesCorrect) { 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 d25973e1ce..c5ca86a651 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -44,6 +44,8 @@ public: 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()); |