SF: Decouple MessageQueue
Define an ICompositor interface against which MessageQueue (which ought
to be an implementation detail of Scheduler) is implemented. Change the
equivocal invalidate/refresh nomenclature to commit/composite. Schedule
sampling only after composite.
Bug: 185535769
Test: libsurfaceflinger_unittest
Change-Id: I0c18f312459bae48531449f24f7b53c104fc5812
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 4d51125..043a536 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -27,49 +27,55 @@
#include "EventThread.h"
#include "FrameTimeline.h"
#include "MessageQueue.h"
-#include "SurfaceFlinger.h"
namespace android::impl {
-void MessageQueue::Handler::dispatchRefresh() {
- if ((mEventMask.fetch_or(eventMaskRefresh) & eventMaskRefresh) == 0) {
- mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
+void MessageQueue::Handler::dispatchComposite() {
+ if ((mEventMask.fetch_or(kComposite) & kComposite) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(kComposite));
}
}
-void MessageQueue::Handler::dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp) {
- if ((mEventMask.fetch_or(eventMaskInvalidate) & eventMaskInvalidate) == 0) {
+void MessageQueue::Handler::dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime) {
+ if ((mEventMask.fetch_or(kCommit) & kCommit) == 0) {
mVsyncId = vsyncId;
- mExpectedVSyncTime = expectedVSyncTimestamp;
- mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
+ mExpectedVsyncTime = expectedVsyncTime;
+ mQueue.mLooper->sendMessage(this, Message(kCommit));
}
}
-bool MessageQueue::Handler::invalidatePending() {
- constexpr auto pendingMask = eventMaskInvalidate | eventMaskRefresh;
- return (mEventMask.load() & pendingMask) != 0;
+bool MessageQueue::Handler::isFramePending() const {
+ constexpr auto kPendingMask = kCommit | kComposite;
+ return (mEventMask.load() & kPendingMask) != 0;
}
void MessageQueue::Handler::handleMessage(const Message& message) {
+ const nsecs_t frameTime = systemTime();
switch (message.what) {
- case INVALIDATE:
- mEventMask.fetch_and(~eventMaskInvalidate);
- mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
- break;
- case REFRESH:
- mEventMask.fetch_and(~eventMaskRefresh);
- mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
+ case kCommit:
+ mEventMask.fetch_and(~kCommit);
+ if (!mQueue.mCompositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
+ return;
+ }
+ // Composite immediately, rather than after pending tasks through scheduleComposite.
+ [[fallthrough]];
+ case kComposite:
+ mEventMask.fetch_and(~kComposite);
+ mQueue.mCompositor.composite(frameTime);
+ mQueue.mCompositor.sample();
break;
}
}
-// ---------------------------------------------------------------------------
+MessageQueue::MessageQueue(ICompositor& compositor)
+ : MessageQueue(compositor, sp<Handler>::make(*this)) {}
-void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
- mFlinger = flinger;
- mLooper = new Looper(true);
- mHandler = new Handler(*this);
-}
+constexpr bool kAllowNonCallbacks = true;
+
+MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
+ : mCompositor(compositor),
+ mLooper(sp<Looper>::make(kAllowNonCallbacks)),
+ mHandler(std::move(handler)) {}
// TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly
// and remove the EventThread from MessageQueue
@@ -110,11 +116,13 @@
{
std::lock_guard lock(mVsync.mutex);
mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
- mVsync.scheduled = false;
+ mVsync.scheduledFrameTime.reset();
}
- mHandler->dispatchInvalidate(mVsync.tokenManager->generateTokenForPredictions(
- {targetWakeupTime, readyTime, vsyncTime}),
- vsyncTime);
+
+ const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
+ {targetWakeupTime, readyTime, vsyncTime});
+
+ mHandler->dispatchCommit(vsyncId, vsyncTime);
}
void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
@@ -135,8 +143,8 @@
ATRACE_CALL();
std::lock_guard lock(mVsync.mutex);
mVsync.workDuration = workDuration;
- if (mVsync.scheduled) {
- mVsync.expectedWakeupTime = mVsync.registration->schedule(
+ if (mVsync.scheduledFrameTime) {
+ mVsync.scheduledFrameTime = mVsync.registration->schedule(
{mVsync.workDuration.get().count(),
/*readyDuration=*/0, mVsync.lastCallbackTime.count()});
}
@@ -168,7 +176,7 @@
mLooper->sendMessage(handler, Message());
}
-void MessageQueue::invalidate() {
+void MessageQueue::scheduleCommit() {
ATRACE_CALL();
{
@@ -181,15 +189,14 @@
}
std::lock_guard lock(mVsync.mutex);
- mVsync.scheduled = true;
- mVsync.expectedWakeupTime =
+ mVsync.scheduledFrameTime =
mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
.readyDuration = 0,
.earliestVsync = mVsync.lastCallbackTime.count()});
}
-void MessageQueue::refresh() {
- mHandler->dispatchRefresh();
+void MessageQueue::scheduleComposite() {
+ mHandler->dispatchComposite();
}
void MessageQueue::injectorCallback() {
@@ -198,24 +205,22 @@
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.vsyncId,
- buffer[i].vsync.expectedVSyncTimestamp);
+ mHandler->dispatchCommit(buffer[i].vsync.vsyncId,
+ buffer[i].vsync.expectedVSyncTimestamp);
break;
}
}
}
}
-std::optional<std::chrono::steady_clock::time_point> MessageQueue::nextExpectedInvalidate() {
- if (mHandler->invalidatePending()) {
- return std::chrono::steady_clock::now();
+auto MessageQueue::getScheduledFrameTime() const -> std::optional<Clock::time_point> {
+ if (mHandler->isFramePending()) {
+ return 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);
+ if (const auto time = mVsync.scheduledFrameTime) {
+ return Clock::time_point(std::chrono::nanoseconds(*time));
}
return std::nullopt;