diff options
-rw-r--r-- | libs/gui/DisplayEventDispatcher.cpp | 16 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventDispatcher.h | 24 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventReceiver.h | 9 | ||||
-rw-r--r-- | libs/nativedisplay/AChoreographer.cpp | 34 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.cpp | 45 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/EventThreadTest.cpp | 51 |
7 files changed, 33 insertions, 150 deletions
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index c986b82fd8..6f1a7aed9c 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -130,19 +130,6 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { return 1; // keep the callback } -void DisplayEventDispatcher::populateFrameTimelines(const DisplayEventReceiver::Event& event, - VsyncEventData* outVsyncEventData) const { - for (size_t i = 0; i < DisplayEventReceiver::kFrameTimelinesLength; i++) { - DisplayEventReceiver::Event::VSync::FrameTimeline receiverTimeline = - event.vsync.frameTimelines[i]; - outVsyncEventData->frameTimelines[i] = {.id = receiverTimeline.vsyncId, - .deadlineTimestamp = - receiverTimeline.deadlineTimestamp, - .expectedPresentTime = - receiverTimeline.expectedVSyncTimestamp}; - } -} - bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, @@ -167,9 +154,6 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; outVsyncEventData->frameInterval = ev.vsync.frameInterval; outVsyncEventData->expectedPresentTime = ev.vsync.expectedVSyncTimestamp; - outVsyncEventData->preferredFrameTimelineIndex = - ev.vsync.preferredFrameTimelineIndex; - populateFrameTimelines(ev, outVsyncEventData); break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 92c89b8bde..f3bd139e8c 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -17,7 +17,6 @@ #include <gui/DisplayEventReceiver.h> #include <utils/Log.h> #include <utils/Looper.h> -#include <array> namespace android { using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; @@ -37,26 +36,6 @@ struct VsyncEventData { // The anticipated Vsync present time. int64_t expectedPresentTime = 0; - - struct FrameTimeline { - // The Vsync Id corresponsing to this vsync event. This will be used to - // populate ISurfaceComposer::setFrameTimelineVsync and - // SurfaceComposerClient::setFrameTimelineVsync - int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID; - - // The deadline in CLOCK_MONOTONIC that the app needs to complete its - // frame by (both on the CPU and the GPU) - int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max(); - - // The anticipated Vsync present time. - int64_t expectedPresentTime = 0; - }; - - // Sorted possible frame timelines. - std::array<FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength> frameTimelines; - - // Index into the frameTimelines that represents the platform's preferred frame timeline. - size_t preferredFrameTimelineIndex = std::numeric_limits<size_t>::max(); }; class DisplayEventDispatcher : public LooperCallback { @@ -98,8 +77,5 @@ private: bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, VsyncEventData* outVsyncEventData); - - void populateFrameTimelines(const DisplayEventReceiver::Event& event, - VsyncEventData* outVsyncEventData) const; }; } // namespace android diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index ca368433b1..0dffbde88a 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -49,9 +49,6 @@ static inline constexpr uint32_t fourcc(char c1, char c2, char c3, char c4) { // ---------------------------------------------------------------------------- class DisplayEventReceiver { public: - // Max amount of frame timelines is arbitrarily set to be reasonable. - static constexpr int64_t kFrameTimelinesLength = 7; - enum { DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), @@ -80,12 +77,6 @@ public: nsecs_t deadlineTimestamp __attribute__((aligned(8))); nsecs_t frameInterval __attribute__((aligned(8))); int64_t vsyncId; - size_t preferredFrameTimelineIndex __attribute__((aligned(8))); - struct FrameTimeline { - nsecs_t expectedVSyncTimestamp __attribute__((aligned(8))); - nsecs_t deadlineTimestamp __attribute__((aligned(8))); - int64_t vsyncId; - } frameTimelines[kFrameTimelinesLength]; }; struct Hotplug { diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index fc9680babb..79d9b9313c 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -100,10 +100,17 @@ class Choreographer; * Implementation of AChoreographerFrameCallbackData. */ struct ChoreographerFrameCallbackDataImpl { + struct FrameTimeline { + int64_t vsyncId{0}; + int64_t expectedPresentTimeNanos{0}; + int64_t deadlineNanos{0}; + }; + int64_t frameTimeNanos{0}; - std::array<VsyncEventData::FrameTimeline, DisplayEventReceiver::kFrameTimelinesLength> - frameTimelines; + size_t frameTimelinesLength; + + std::vector<FrameTimeline> frameTimelines; size_t preferredFrameTimelineIndex; @@ -449,9 +456,14 @@ bool Choreographer::inCallback() const { } ChoreographerFrameCallbackDataImpl Choreographer::createFrameCallbackData(nsecs_t timestamp) const { + std::vector<ChoreographerFrameCallbackDataImpl::FrameTimeline> frameTimelines; + frameTimelines.push_back({.vsyncId = mLastVsyncEventData.id, + .expectedPresentTimeNanos = mLastVsyncEventData.expectedPresentTime, + .deadlineNanos = mLastVsyncEventData.deadlineTimestamp}); return {.frameTimeNanos = timestamp, - .preferredFrameTimelineIndex = mLastVsyncEventData.preferredFrameTimelineIndex, - .frameTimelines = mLastVsyncEventData.frameTimelines, + .frameTimelinesLength = 1, + .preferredFrameTimelineIndex = 0, + .frameTimelines = frameTimelines, .choreographer = this}; } @@ -634,7 +646,7 @@ size_t AChoreographerFrameCallbackData_getFrameTimelinesLength( AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(), "Data is only valid in callback"); - return frameCallbackData->frameTimelines.size(); + return frameCallbackData->frameTimelinesLength; } size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex( const AChoreographerFrameCallbackData* data) { @@ -650,8 +662,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineVsyncId( AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(), "Data is only valid in callback"); - LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds"); - return frameCallbackData->frameTimelines[index].id; + LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds"); + return frameCallbackData->frameTimelines[index].vsyncId; } int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime( const AChoreographerFrameCallbackData* data, size_t index) { @@ -659,8 +671,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime( AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(), "Data is only valid in callback"); - LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds"); - return frameCallbackData->frameTimelines[index].expectedPresentTime; + LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds"); + return frameCallbackData->frameTimelines[index].expectedPresentTimeNanos; } int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline( const AChoreographerFrameCallbackData* data, size_t index) { @@ -668,8 +680,8 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline( AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(), "Data is only valid in callback"); - LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds"); - return frameCallbackData->frameTimelines[index].deadlineTimestamp; + LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelinesLength, "Index out of bounds"); + return frameCallbackData->frameTimelines[index].deadlineNanos; } AChoreographer* AChoreographer_create() { diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index e07eae79c8..2bdcaf6ad0 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -355,7 +355,14 @@ void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp std::lock_guard<std::mutex> lock(mMutex); LOG_FATAL_IF(!mVSyncState); - const int64_t vsyncId = generateToken(timestamp, deadlineTimestamp, expectedVSyncTimestamp); + const int64_t vsyncId = [&] { + if (mTokenManager != nullptr) { + return mTokenManager->generateTokenForPredictions( + {timestamp, deadlineTimestamp, expectedVSyncTimestamp}); + } + return FrameTimelineInfo::INVALID_VSYNC_ID; + }(); + mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count, expectedVSyncTimestamp, deadlineTimestamp, vsyncId)); mCondition.notify_all(); @@ -560,48 +567,12 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, } } -int64_t EventThread::generateToken(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp, - nsecs_t deadlineTimestamp) const { - if (mTokenManager != nullptr) { - return mTokenManager->generateTokenForPredictions( - {timestamp, deadlineTimestamp, expectedVSyncTimestamp}); - } - return FrameTimelineInfo::INVALID_VSYNC_ID; -} - -void EventThread::generateFrameTimeline(DisplayEventReceiver::Event& event) const { - // Add 1 to ensure the preferredFrameTimelineIndex entry (when multiplier == 0) is included. - for (int multiplier = -DisplayEventReceiver::kFrameTimelinesLength + 1, currentIndex = 0; - currentIndex < DisplayEventReceiver::kFrameTimelinesLength; multiplier++) { - nsecs_t deadline = event.vsync.deadlineTimestamp + multiplier * event.vsync.frameInterval; - // Valid possible frame timelines must have future values. - if (deadline > event.header.timestamp) { - if (multiplier == 0) { - event.vsync.preferredFrameTimelineIndex = currentIndex; - event.vsync.frameTimelines[currentIndex] = - {.vsyncId = event.vsync.vsyncId, - .deadlineTimestamp = event.vsync.deadlineTimestamp, - .expectedVSyncTimestamp = event.vsync.expectedVSyncTimestamp}; - } else { - nsecs_t expectedVSync = - event.vsync.expectedVSyncTimestamp + multiplier * event.vsync.frameInterval; - event.vsync.frameTimelines[currentIndex] = - {.vsyncId = generateToken(event.header.timestamp, expectedVSync, deadline), - .deadlineTimestamp = deadline, - .expectedVSyncTimestamp = expectedVSync}; - } - currentIndex++; - } - } -} - void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, const DisplayEventConsumers& consumers) { for (const auto& consumer : consumers) { DisplayEventReceiver::Event copy = event; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); - generateFrameTimeline(copy); } switch (consumer->postEvent(copy)) { case NO_ERROR: diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 73ae5dc9e3..9265a25b86 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -204,10 +204,6 @@ private: void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp, nsecs_t deadlineTimestamp) override; - int64_t generateToken(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp, - nsecs_t deadlineTimestamp) const; - void generateFrameTimeline(DisplayEventReceiver::Event& event) const; - const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index cb690aa0e4..28d0222829 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -28,7 +28,6 @@ #include "AsyncCallRecorder.h" #include "DisplayHardware/DisplayMode.h" -#include "FrameTimeline.h" #include "Scheduler/EventThread.h" using namespace std::chrono_literals; @@ -97,8 +96,6 @@ protected: ConnectionEventRecorder& connectionEventRecorder, nsecs_t expectedTimestamp, unsigned expectedCount); void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount); - void expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTimestamp, - nsecs_t preferredDeadline); void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, bool expectedConnected); void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, @@ -123,7 +120,6 @@ protected: std::unique_ptr<impl::EventThread> mThread; sp<MockEventThreadConnection> mConnection; sp<MockEventThreadConnection> mThrottledConnection; - std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager; static constexpr uid_t mConnectionUid = 443; static constexpr uid_t mThrottledConnectionUid = 177; @@ -177,8 +173,8 @@ void EventThreadTest::createThread(std::unique_ptr<VSyncSource> source) { return VSYNC_PERIOD.count(); }; - mTokenManager = std::make_unique<frametimeline::impl::TokenManager>(); - mThread = std::make_unique<impl::EventThread>(std::move(source), mTokenManager.get(), + mThread = std::make_unique<impl::EventThread>(std::move(source), + /*tokenManager=*/nullptr, mInterceptVSyncCallRecorder.getInvocable(), throttleVsync, getVsyncPeriod); @@ -251,36 +247,6 @@ void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimes expectedCount); } -void EventThreadTest::expectVsyncEventFrameTimelinesCorrect(nsecs_t expectedTimestamp, - nsecs_t preferredDeadline) { - auto args = mConnectionEventCallRecorder.waitForCall(); - 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 < DisplayEventReceiver::kFrameTimelinesLength; i++) { - if (i > 0) { - EXPECT_GT(event.vsync.frameTimelines[i].deadlineTimestamp, - event.vsync.frameTimelines[i - 1].deadlineTimestamp) - << "Deadline timestamp out of order for frame timeline " << i; - EXPECT_GT(event.vsync.frameTimelines[i].expectedVSyncTimestamp, - event.vsync.frameTimelines[i - 1].expectedVSyncTimestamp) - << "Expected vsync timestamp out of order for frame timeline " << i; - } - if (event.vsync.frameTimelines[i].deadlineTimestamp == preferredDeadline) { - EXPECT_EQ(i, event.vsync.preferredFrameTimelineIndex) - << "Preferred frame timeline index should be " << i; - // For the platform-preferred frame timeline, the vsync ID is 0 because the first frame - // timeline is made before the rest. - EXPECT_EQ(0, event.vsync.frameTimelines[i].vsyncId) - << "Vsync ID incorrect for frame timeline " << i; - } else { - // Vsync ID 0 is used for the preferred frame timeline. - EXPECT_EQ(i + 1, event.vsync.frameTimelines[i].vsyncId) - << "Vsync ID incorrect for frame timeline " << i; - } - } -} - void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, bool expectedConnected) { auto args = mConnectionEventCallRecorder.waitForCall(); @@ -378,19 +344,6 @@ TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { expectVSyncSetEnabledCallReceived(false); } -TEST_F(EventThreadTest, requestNextVsyncEventFrameTimelinesCorrect) { - // Signal that we want the next vsync event to be posted to the connection - mThread->requestNextVsync(mConnection); - - expectVSyncSetEnabledCallReceived(true); - - // Use the received callback to signal a vsync event. - // The interceptor should receive the event, as well as the connection. - mCallback->onVSyncEvent(123, 456, 789); - expectInterceptCallReceived(123); - expectVsyncEventFrameTimelinesCorrect(123, 789); -} - TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // Create a first connection, register it, and request a vsync rate of zero. ConnectionEventRecorder firstConnectionEventRecorder{0}; |