[SF] Send NotifyExpectedPresentHint at the transaction time
BUG: 314199179
BUG: 315989692
BUG: 284845445
Test: atest NotifyExpectedPresentTest
Change-Id: Ief7fff69e8b92f0affd228b2bdcdc5009806f905
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index edba50b..0436c3c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2759,7 +2759,11 @@
// TODO(b/255601557) Update frameInterval per display
refreshArgs.frameInterval =
mScheduler->getNextFrameInterval(pacesetterId, pacesetterTarget.expectedPresentTime());
- refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
+ const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult();
+ const auto scheduledFrameTimeOpt = scheduledFrameResultOpt
+ ? std::optional{scheduledFrameResultOpt->callbackTime}
+ : std::nullopt;
+ refreshArgs.scheduledFrameTime = scheduledFrameTimeOpt;
refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
@@ -4258,7 +4262,8 @@
auto hintStatus = data.hintStatus.load();
if (!expectedPresentWithinTimeout) {
- if (hintStatus != NotifyExpectedPresentHintStatus::Sent ||
+ if ((hintStatus != NotifyExpectedPresentHintStatus::Sent &&
+ hintStatus != NotifyExpectedPresentHintStatus::ScheduleOnTx) ||
(timeoutOpt && timeoutOpt->ns() == 0)) {
// Send the hint immediately if timeout, as the hint gets
// delayed otherwise, as the frame is scheduled close
@@ -4267,11 +4272,16 @@
.compare_exchange_strong(hintStatus,
NotifyExpectedPresentHintStatus::ScheduleOnTx)) {
scheduleNotifyExpectedPresentHint(displayId);
+ return;
}
- return;
}
}
+ if (hintStatus == NotifyExpectedPresentHintStatus::Sent &&
+ data.hintStatus.compare_exchange_strong(hintStatus,
+ NotifyExpectedPresentHintStatus::ScheduleOnTx)) {
+ return;
+ }
if (hintStatus != NotifyExpectedPresentHintStatus::Start) {
return;
}
@@ -4279,7 +4289,8 @@
mScheduler->scheduleFrame();
}
-void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId) {
+void SurfaceFlinger::scheduleNotifyExpectedPresentHint(PhysicalDisplayId displayId,
+ VsyncId vsyncId) {
auto itr = mNotifyExpectedPresentMap.find(displayId);
if (itr == mNotifyExpectedPresentMap.end()) {
return;
@@ -4288,10 +4299,30 @@
const char* const whence = __func__;
const auto sendHint = [=, this]() {
auto& data = mNotifyExpectedPresentMap.at(displayId);
- data.hintStatus.store(NotifyExpectedPresentHintStatus::Sent);
- const auto status =
- getHwComposer().notifyExpectedPresent(displayId, data.lastExpectedPresentTimestamp,
- data.lastFrameInterval);
+ TimePoint expectedPresentTime = data.lastExpectedPresentTimestamp;
+ if (ftl::to_underlying(vsyncId) != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ const auto predictionOpt = mFrameTimeline->getTokenManager()->getPredictionsForToken(
+ ftl::to_underlying(vsyncId));
+ const auto expectedPresentTimeOnPredictor = TimePoint::fromNs(
+ predictionOpt ? predictionOpt->presentTime : expectedPresentTime.ns());
+ const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult();
+ const auto expectedPresentTimeOnScheduler = scheduledFrameResultOpt.has_value()
+ ? scheduledFrameResultOpt->vsyncTime
+ : TimePoint::fromNs(0);
+ expectedPresentTime =
+ std::max(expectedPresentTimeOnPredictor, expectedPresentTimeOnScheduler);
+ }
+
+ if (expectedPresentTime < TimePoint::now()) {
+ expectedPresentTime =
+ mScheduler->getVsyncSchedule()->vsyncDeadlineAfter(TimePoint::now());
+ if (mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration >
+ mScheduler->getVsyncSchedule(displayId)->period()) {
+ expectedPresentTime += mScheduler->getVsyncSchedule(displayId)->period();
+ }
+ }
+ const auto status = getHwComposer().notifyExpectedPresent(displayId, expectedPresentTime,
+ data.lastFrameInterval);
if (status != NO_ERROR) {
ALOGE("%s failed to notifyExpectedPresentHint for display %" PRId64, whence,
displayId.value);
@@ -4309,7 +4340,11 @@
}
}));
}
- sendHint();
+ auto scheduleHintOnPresent = NotifyExpectedPresentHintStatus::ScheduleOnPresent;
+ if (itr->second.hintStatus.compare_exchange_strong(scheduleHintOnPresent,
+ NotifyExpectedPresentHintStatus::Sent)) {
+ sendHint();
+ }
}
void SurfaceFlinger::sendNotifyExpectedPresentHint(PhysicalDisplayId displayId) {
@@ -5112,6 +5147,11 @@
const auto frameHint = state.isFrameActive() ? FrameHint::kActive : FrameHint::kNone;
mTransactionHandler.queueTransaction(std::move(state));
+ for (const auto& [displayId, data] : mNotifyExpectedPresentMap) {
+ if (data.hintStatus.load() == NotifyExpectedPresentHintStatus::ScheduleOnTx) {
+ scheduleNotifyExpectedPresentHint(displayId, VsyncId{frameTimelineInfo.vsyncId});
+ }
+ }
setTransactionFlags(eTransactionFlushNeeded, schedule, applyToken, frameHint);
return NO_ERROR;
}
@@ -8820,7 +8860,11 @@
return;
}
- mRegionSamplingThread->onCompositionComplete(mScheduler->getScheduledFrameTime());
+ const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult();
+ const auto scheduleFrameTimeOpt = scheduledFrameResultOpt
+ ? std::optional{scheduledFrameResultOpt->callbackTime}
+ : std::nullopt;
+ mRegionSamplingThread->onCompositionComplete(scheduleFrameTimeOpt);
}
void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDisplay) {