diff options
Diffstat (limited to 'services/surfaceflinger/Scheduler/MessageQueue.cpp')
-rw-r--r-- | services/surfaceflinger/Scheduler/MessageQueue.cpp | 149 |
1 files changed, 118 insertions, 31 deletions
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 6067e69ea0..4d51125156 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -14,9 +14,7 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <binder/IPCThreadState.h> @@ -25,36 +23,42 @@ #include <utils/threads.h> #include <gui/DisplayEventReceiver.h> -#include <gui/IDisplayEventConnection.h> #include "EventThread.h" +#include "FrameTimeline.h" #include "MessageQueue.h" #include "SurfaceFlinger.h" namespace android::impl { void MessageQueue::Handler::dispatchRefresh() { - if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) { + if ((mEventMask.fetch_or(eventMaskRefresh) & eventMaskRefresh) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); } } -void MessageQueue::Handler::dispatchInvalidate(nsecs_t expectedVSyncTimestamp) { - if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { +void MessageQueue::Handler::dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp) { + if ((mEventMask.fetch_or(eventMaskInvalidate) & eventMaskInvalidate) == 0) { + mVsyncId = vsyncId; mExpectedVSyncTime = expectedVSyncTimestamp; mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); } } +bool MessageQueue::Handler::invalidatePending() { + constexpr auto pendingMask = eventMaskInvalidate | eventMaskRefresh; + return (mEventMask.load() & pendingMask) != 0; +} + void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: - android_atomic_and(~eventMaskInvalidate, &mEventMask); - mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime); + mEventMask.fetch_and(~eventMaskInvalidate); + mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime); break; case REFRESH: - android_atomic_and(~eventMaskRefresh, &mEventMask); - mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime); + mEventMask.fetch_and(~eventMaskRefresh); + mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime); break; } } @@ -67,15 +71,75 @@ void MessageQueue::init(const sp<SurfaceFlinger>& flinger) { mHandler = new Handler(*this); } -void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) { - if (mEventTube.getFd() >= 0) { - mLooper->removeFd(mEventTube.getFd()); +// TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly +// and remove the EventThread from MessageQueue +void MessageQueue::setInjector(sp<EventThreadConnection> connection) { + auto& tube = mInjector.tube; + + if (const int fd = tube.getFd(); fd >= 0) { + mLooper->removeFd(fd); + } + + if (connection) { + // The EventThreadConnection is retained when disabling injection, so avoid subsequently + // stealing invalid FDs. Note that the stolen FDs are kept open. + if (tube.getFd() < 0) { + connection->stealReceiveChannel(&tube); + } else { + ALOGW("Recycling channel for VSYNC injection."); + } + + mLooper->addFd( + tube.getFd(), 0, Looper::EVENT_INPUT, + [](int, int, void* data) { + reinterpret_cast<MessageQueue*>(data)->injectorCallback(); + return 1; // Keep registration. + }, + this); + } + + std::lock_guard lock(mInjector.mutex); + mInjector.connection = std::move(connection); +} + +void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) { + ATRACE_CALL(); + // Trace VSYNC-sf + mVsync.value = (mVsync.value + 1) % 2; + + { + std::lock_guard lock(mVsync.mutex); + mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime); + mVsync.scheduled = false; } + mHandler->dispatchInvalidate(mVsync.tokenManager->generateTokenForPredictions( + {targetWakeupTime, readyTime, vsyncTime}), + vsyncTime); +} + +void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch, + frametimeline::TokenManager& tokenManager, + std::chrono::nanoseconds workDuration) { + setDuration(workDuration); + mVsync.tokenManager = &tokenManager; + mVsync.registration = std::make_unique< + scheduler::VSyncCallbackRegistration>(dispatch, + std::bind(&MessageQueue::vsyncCallback, this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3), + "sf"); +} - mEvents = connection; - mEvents->stealReceiveChannel(&mEventTube); - mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, - this); +void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) { + ATRACE_CALL(); + std::lock_guard lock(mVsync.mutex); + mVsync.workDuration = workDuration; + if (mVsync.scheduled) { + mVsync.expectedWakeupTime = mVsync.registration->schedule( + {mVsync.workDuration.get().count(), + /*readyDuration=*/0, mVsync.lastCallbackTime.count()}); + } } void MessageQueue::waitMessage() { @@ -105,33 +169,56 @@ void MessageQueue::postMessage(sp<MessageHandler>&& handler) { } void MessageQueue::invalidate() { - mEvents->requestNextVsync(); + ATRACE_CALL(); + + { + std::lock_guard lock(mInjector.mutex); + if (CC_UNLIKELY(mInjector.connection)) { + ALOGD("%s while injecting VSYNC", __FUNCTION__); + mInjector.connection->requestNextVsync(); + return; + } + } + + std::lock_guard lock(mVsync.mutex); + mVsync.scheduled = true; + mVsync.expectedWakeupTime = + mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(), + .readyDuration = 0, + .earliestVsync = mVsync.lastCallbackTime.count()}); } void MessageQueue::refresh() { mHandler->dispatchRefresh(); } -int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { - MessageQueue* queue = reinterpret_cast<MessageQueue*>(data); - return queue->eventReceiver(fd, events); -} - -int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { +void MessageQueue::injectorCallback() { ssize_t n; DisplayEventReceiver::Event buffer[8]; - while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) { + while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) { for (int i = 0; i < n; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { - mHandler->dispatchInvalidate(buffer[i].vsync.expectedVSyncTimestamp); + mHandler->dispatchInvalidate(buffer[i].vsync.vsyncId, + buffer[i].vsync.expectedVSyncTimestamp); break; } } } - return 1; } -} // namespace android::impl +std::optional<std::chrono::steady_clock::time_point> MessageQueue::nextExpectedInvalidate() { + if (mHandler->invalidatePending()) { + return std::chrono::steady_clock::now(); + } + + std::lock_guard lock(mVsync.mutex); + if (mVsync.scheduled) { + LOG_ALWAYS_FATAL_IF(!mVsync.expectedWakeupTime.has_value(), "callback was never scheduled"); + const auto expectedWakeupTime = std::chrono::nanoseconds(*mVsync.expectedWakeupTime); + return std::optional<std::chrono::steady_clock::time_point>(expectedWakeupTime); + } -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" + return std::nullopt; +} + +} // namespace android::impl |