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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e90af3a..bb65bae 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -371,7 +371,7 @@
mTimeStats(std::make_shared<impl::TimeStats>()),
mFrameTracer(mFactory.createFrameTracer()),
mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, getpid())),
- mEventQueue(mFactory.createMessageQueue()),
+ mEventQueue(mFactory.createMessageQueue(*this)),
mCompositionEngine(mFactory.createCompositionEngine()),
mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
@@ -506,10 +506,6 @@
SurfaceFlinger::~SurfaceFlinger() = default;
-void SurfaceFlinger::onFirstRef() {
- mEventQueue->init(this);
-}
-
void SurfaceFlinger::binderDied(const wp<IBinder>&) {
// the window manager died on us. prepare its eulogy.
mBootFinished = false;
@@ -1104,7 +1100,7 @@
}
if (display->setDesiredActiveMode(info)) {
- scheduleRefresh(FrameHint::kNone);
+ scheduleComposite(FrameHint::kNone);
// Start receiving vsync samples now, so that we can detect a period
// switch.
@@ -1704,31 +1700,26 @@
return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}
-void SurfaceFlinger::scheduleInvalidate(FrameHint hint) {
+void SurfaceFlinger::scheduleCommit(FrameHint hint) {
if (hint == FrameHint::kActive) {
mScheduler->resetIdleTimer();
}
mPowerAdvisor.notifyDisplayUpdateImminent();
- mEventQueue->invalidate();
+ mEventQueue->scheduleCommit();
}
-void SurfaceFlinger::scheduleRefresh(FrameHint hint) {
- mForceRefresh = true;
- scheduleInvalidate(hint);
+void SurfaceFlinger::scheduleComposite(FrameHint hint) {
+ mMustComposite = true;
+ scheduleCommit(hint);
}
void SurfaceFlinger::scheduleRepaint() {
mGeometryDirty = true;
- scheduleRefresh(FrameHint::kActive);
+ scheduleComposite(FrameHint::kActive);
}
-void SurfaceFlinger::signalLayerUpdate() {
- scheduleInvalidate(FrameHint::kActive);
-}
-
-void SurfaceFlinger::signalRefresh() {
- mRefreshPending = true;
- mEventQueue->refresh();
+void SurfaceFlinger::scheduleSample() {
+ static_cast<void>(schedule([this] { sample(); }));
}
nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
@@ -1834,7 +1825,7 @@
void SurfaceFlinger::onComposerHalRefresh(hal::HWDisplayId) {
Mutex::Autolock lock(mStateLock);
- scheduleRefresh(FrameHint::kNone);
+ scheduleComposite(FrameHint::kNone);
}
void SurfaceFlinger::setVsyncEnabled(bool enabled) {
@@ -1889,40 +1880,26 @@
: stats.vsyncTime + stats.vsyncPeriod;
}
-void SurfaceFlinger::onMessageReceived(int32_t what, int64_t vsyncId, nsecs_t expectedVSyncTime) {
- switch (what) {
- case MessageQueue::INVALIDATE: {
- onMessageInvalidate(vsyncId, expectedVSyncTime);
- break;
- }
- case MessageQueue::REFRESH: {
- onMessageRefresh();
- break;
- }
- }
-}
-
-void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTime) {
- const nsecs_t frameStart = systemTime();
+bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) {
// calculate the expected present time once and use the cached
// value throughout this frame to make sure all layers are
// seeing this same value.
- if (expectedVSyncTime >= frameStart) {
- mExpectedPresentTime = expectedVSyncTime;
+ if (expectedVsyncTime >= frameTime) {
+ mExpectedPresentTime = expectedVsyncTime;
} else {
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameStart);
+ const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameTime);
mExpectedPresentTime = calculateExpectedPresentTime(stats);
}
const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
- mScheduledPresentTime = expectedVSyncTime;
+ mScheduledPresentTime = expectedVsyncTime;
const auto vsyncIn = [&] {
if (!ATRACE_ENABLED()) return 0.f;
return (mExpectedPresentTime - systemTime()) / 1e6f;
}();
- ATRACE_FORMAT("onMessageInvalidate %" PRId64 " vsyncIn %.2fms%s", vsyncId, vsyncIn,
- mExpectedPresentTime == expectedVSyncTime ? "" : " (adjusted)");
+ ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, vsyncId, vsyncIn,
+ mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)");
// When Backpressure propagation is enabled we want to give a small grace period
// for the present fence to fire instead of just giving up on this frame to handle cases
@@ -1969,11 +1946,11 @@
}
// If we are in the middle of a mode change and the fence hasn't
- // fired yet just wait for the next invalidate
+ // fired yet just wait for the next commit.
if (mSetActiveModePending) {
if (framePending) {
- mEventQueue->invalidate();
- return;
+ mEventQueue->scheduleCommit();
+ return false;
}
// We received the present fence from the HWC, so we assume it successfully updated
@@ -1984,8 +1961,8 @@
if (framePending) {
if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
- signalLayerUpdate();
- return;
+ scheduleCommit(FrameHint::kNone);
+ return false;
}
}
@@ -1997,11 +1974,12 @@
if (mRefreshRateOverlaySpinner) {
Mutex::Autolock lock(mStateLock);
if (const auto display = getDefaultDisplayDeviceLocked()) {
- display->onInvalidate();
+ display->animateRefreshRateOverlay();
}
}
- bool refreshNeeded = mForceRefresh.exchange(false);
+ // Composite if transactions were committed, or if requested by HWC.
+ bool mustComposite = mMustComposite.exchange(false);
{
mTracePostComposition = mTracing.flagIsSet(SurfaceTracing::TRACE_COMPOSITION) ||
mTracing.flagIsSet(SurfaceTracing::TRACE_SYNC) ||
@@ -2009,10 +1987,12 @@
const bool tracePreComposition = mTracingEnabled && !mTracePostComposition;
ConditionalLockGuard<std::mutex> lock(mTracingLock, tracePreComposition);
- mFrameTimeline->setSfWakeUp(vsyncId, frameStart, Fps::fromPeriodNsecs(stats.vsyncPeriod));
+ mFrameTimeline->setSfWakeUp(vsyncId, frameTime, Fps::fromPeriodNsecs(stats.vsyncPeriod));
- refreshNeeded |= flushAndCommitTransactions();
- refreshNeeded |= handleMessageInvalidate();
+ mustComposite |= flushAndCommitTransactions();
+ mustComposite |= latchBuffers();
+
+ updateLayerGeometry();
if (tracePreComposition) {
if (mVisibleRegionsDirty) {
@@ -2035,25 +2015,7 @@
updateCursorAsync();
updateInputFlinger();
- if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
- // Signal a refresh if a transaction modified the window state,
- // a new buffer was latched, or if HWC has requested a full
- // repaint
- if (mFrameStartTime <= 0) {
- // We should only use the time of the first invalidate
- // message that signals a refresh as the beginning of the
- // frame. Otherwise the real frame time will be
- // underestimated.
- mFrameStartTime = frameStart;
- }
-
- // Run the refresh immediately after invalidate as there is no point going thru the message
- // queue again, and to ensure that we actually refresh the screen instead of handling
- // other messages that were queued us already in the MessageQueue.
- mRefreshPending = true;
- onMessageRefresh();
- }
- notifyRegionSamplingThread();
+ return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}
bool SurfaceFlinger::flushAndCommitTransactions() {
@@ -2068,6 +2030,9 @@
commitTransactions();
}
+ // Invoke OnCommit callbacks.
+ mTransactionCallbackInvoker.sendCallbacks();
+
if (transactionFlushNeeded()) {
setTransactionFlags(eTransactionFlushNeeded);
}
@@ -2075,11 +2040,9 @@
return shouldCommit;
}
-void SurfaceFlinger::onMessageRefresh() {
+void SurfaceFlinger::composite(nsecs_t frameTime) {
ATRACE_CALL();
- mRefreshPending = false;
-
compositionengine::CompositionRefreshArgs refreshArgs;
const auto& displays = ON_MAIN_THREAD(mDisplays);
refreshArgs.outputs.reserve(displays.size());
@@ -2123,18 +2086,16 @@
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
- refreshArgs.nextInvalidateTime = mEventQueue->nextExpectedInvalidate();
+ refreshArgs.scheduledFrameTime = mEventQueue->getScheduledFrameTime();
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
const auto presentTime = systemTime();
mCompositionEngine->present(refreshArgs);
- mTimeStats->recordFrameDuration(mFrameStartTime, systemTime());
- // Reset the frame start time now that we've recorded this frame.
- mFrameStartTime = 0;
+ mTimeStats->recordFrameDuration(frameTime, systemTime());
- mScheduler->onDisplayRefreshed(presentTime);
+ mScheduler->onPostComposition(presentTime);
postFrame();
postComposition();
@@ -2177,17 +2138,12 @@
mVisibleRegionsDirty = false;
if (mCompositionEngine->needsAnotherUpdate()) {
- signalLayerUpdate();
+ scheduleCommit(FrameHint::kNone);
}
}
-bool SurfaceFlinger::handleMessageInvalidate() {
+void SurfaceFlinger::updateLayerGeometry() {
ATRACE_CALL();
- // Send on commit callbacks
- mTransactionCallbackInvoker.sendCallbacks();
-
- bool refreshNeeded = handlePageFlip();
-
if (mVisibleRegionsDirty) {
computeLayerBounds();
@@ -2199,7 +2155,6 @@
invalidateLayerStack(layer, visibleReg);
}
mLayersPendingRefresh.clear();
- return refreshNeeded;
}
void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
@@ -3301,11 +3256,10 @@
}
}
-bool SurfaceFlinger::handlePageFlip() {
+bool SurfaceFlinger::latchBuffers() {
ATRACE_CALL();
- ALOGV("handlePageFlip");
- nsecs_t latchTime = systemTime();
+ const nsecs_t latchTime = systemTime();
bool visibleRegions = false;
bool frameQueued = false;
@@ -3374,7 +3328,7 @@
// queued frame that shouldn't be displayed during this vsync period, wake
// up during the next vsync period to check again.
if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
- signalLayerUpdate();
+ scheduleCommit(FrameHint::kNone);
}
// enter boot animation on first buffer latch
@@ -3453,7 +3407,7 @@
const sp<IBinder>& applyToken) {
const uint32_t old = mTransactionFlags.fetch_or(mask);
modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken);
- if ((old & mask) == 0) scheduleInvalidate(FrameHint::kActive);
+ if ((old & mask) == 0) scheduleCommit(FrameHint::kActive);
return old;
}
@@ -4572,7 +4526,7 @@
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
- scheduleRefresh(FrameHint::kActive);
+ scheduleComposite(FrameHint::kActive);
} else if (mode == hal::PowerMode::OFF) {
// Turn off the display
if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
@@ -5430,8 +5384,8 @@
}
scheduleRepaint();
return NO_ERROR;
- case 1004: // Force refresh ahead of next VSYNC.
- scheduleRefresh(FrameHint::kActive);
+ case 1004: // Force composite ahead of next VSYNC.
+ scheduleComposite(FrameHint::kActive);
return NO_ERROR;
case 1005: { // Force commit ahead of next VSYNC.
Mutex::Autolock lock(mStateLock);
@@ -5439,8 +5393,8 @@
eTraversalNeeded);
return NO_ERROR;
}
- case 1006: // Force refresh immediately.
- signalRefresh();
+ case 1006: // Force composite immediately.
+ mEventQueue->scheduleComposite();
return NO_ERROR;
case 1007: // Unused.
return NAME_NOT_FOUND;
@@ -5834,7 +5788,7 @@
const bool timerExpired = mKernelIdleTimerEnabled && expired;
if (display->onKernelTimerChanged(desiredModeId, timerExpired)) {
- mEventQueue->invalidate();
+ mEventQueue->scheduleCommit();
}
}));
}
@@ -6265,12 +6219,6 @@
bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
- if (mRefreshPending) {
- ALOGW("Skipping screenshot for now");
- captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
- grayscale, captureListener);
- return;
- }
ScreenCaptureResults captureResults;
std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get();
if (!renderArea) {
@@ -6617,6 +6565,10 @@
}
}
+void SurfaceFlinger::onLayerUpdate() {
+ scheduleCommit(FrameHint::kActive);
+}
+
// WARNING: ONLY CALL THIS FROM LAYER DTOR
// Here we add children in the current state to offscreen layers and remove the
// layer itself from the offscreen layer list. Since
@@ -6941,16 +6893,12 @@
return layer;
}
-void SurfaceFlinger::scheduleRegionSamplingThread() {
- static_cast<void>(schedule([&] { notifyRegionSamplingThread(); }));
-}
-
-void SurfaceFlinger::notifyRegionSamplingThread() {
+void SurfaceFlinger::sample() {
if (!mLumaSampling || !mRegionSamplingThread) {
return;
}
- mRegionSamplingThread->onCompositionComplete(mEventQueue->nextExpectedInvalidate());
+ mRegionSamplingThread->onCompositionComplete(mEventQueue->getScheduledFrameTime());
}
void SurfaceFlinger::onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay) {