Add inputEventId to SurfaceFrame
SurfaceFrame will now be aware of the id of the input event that caused
the current frame.
The flow of input event id is inputflinger -> app -> surfaceflinger.
Here, we are adding the 'inputEventId' parameter to the
'setFrameTimelineVsync' call. This call will now be responsible for
setting two pieces of information: the vsync id, and the input event id.
Since it will no longer be limited to the vsync id, we rename this call
to "setFrameTimelineInfo".
Once the inputEventId is stored in SurfaceFrame, we will add a binder
call to send the frame timing information to inputflinger (separate,
future CL). This will allow input to reconstruct the entire sequence of
events (at what time was input event getting processed in system_server,
app, and surfaceflinger) and will provide the ability to measure
end-to-end touch latency.
In a separate change, we will also add ATRACE calls to allow manual /
script-based latency analysis for local debugging. We will now know
which input event is being processed in surfaceflinger.
Bug: 169866723
Bug: 129481165
Design doc: https://docs.google.com/document/d/1G3bLaZYSmbe6AKcL-6ZChvrw_B_LXEz29Z6Ed9QoYXY/edit#
Test: atest WMShellUnitTests SurfaceParcelable_test libgui_test IPC_test SurfaceFlinger_test
Change-Id: If7e0eee82603b38b396b53ad7ced660973efcb50
Merged-In: If7e0eee82603b38b396b53ad7ced660973efcb50
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 17d1f3b..3743716 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -275,13 +275,15 @@
return ++mTraceCookie;
}
-SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName, PredictionState predictionState,
+SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
+ uid_t ownerUid, std::string layerName, std::string debugName,
+ PredictionState predictionState,
frametimeline::TimelineItem&& predictions,
std::shared_ptr<TimeStats> timeStats,
JankClassificationThresholds thresholds,
TraceCookieCounter* traceCookieCounter)
- : mToken(token),
+ : mToken(frameTimelineInfo.vsyncId),
+ mInputEventId(frameTimelineInfo.inputEventId),
mOwnerPid(ownerPid),
mOwnerUid(ownerUid),
mLayerName(std::move(layerName)),
@@ -295,27 +297,27 @@
mTraceCookieCounter(*traceCookieCounter) {}
void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.startTime = actualStartTime;
}
void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActualQueueTime = actualQueueTime;
}
void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
}
void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mPresentState = presentState;
mLastLatchTime = lastLatchTime;
}
std::optional<int32_t> SurfaceFrame::getJankType() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mActuals.presentTime == 0) {
return std::nullopt;
}
@@ -323,32 +325,32 @@
}
nsecs_t SurfaceFrame::getBaseTime() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return getMinTime(mPredictionState, mPredictions, mActuals);
}
TimelineItem SurfaceFrame::getActuals() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mActuals;
}
SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mPresentState;
}
FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFramePresentMetadata;
}
FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFrameReadyMetadata;
}
void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Layer - %s", mDebugName.c_str());
if (mJankType != JankType::None) {
@@ -387,7 +389,7 @@
void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
nsecs_t vsyncPeriod) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mPresentState != PresentState::Presented) {
// No need to update dropped buffers
return;
@@ -479,6 +481,9 @@
mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
}
+/**
+ * TODO(b/178637512): add inputEventId to the perfetto trace.
+ */
void SurfaceFrame::trace(int64_t displayFrameToken) {
using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
@@ -486,12 +491,12 @@
bool missingToken = false;
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ std::scoped_lock lock(mMutex);
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
missingToken = true;
return;
- } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken",
mLayerName.c_str());
missingToken = true;
@@ -521,7 +526,7 @@
// Expected timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
@@ -535,7 +540,7 @@
int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Actual timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
// Actual start time is not yet available, so use expected start instead
@@ -566,7 +571,7 @@
});
// Actual timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
@@ -582,7 +587,7 @@
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
const int64_t assignedToken = mCurrentToken++;
mPredictions[assignedToken] = {systemTime(), predictions};
flushTokens(systemTime());
@@ -590,7 +595,7 @@
}
std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto predictionsIterator = mPredictions.find(token);
if (predictionsIterator != mPredictions.end()) {
return predictionsIterator->second.predictions;
@@ -634,26 +639,28 @@
}
std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
- std::optional<int64_t> token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName) {
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) {
ATRACE_CALL();
- if (!token) {
- return std::make_shared<SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid,
- ownerUid, std::move(layerName), std::move(debugName),
+ if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
PredictionState::None, TimelineItem(), mTimeStats,
mJankClassificationThresholds, &mTraceCookieCounter);
}
- std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
+ std::optional<TimelineItem> predictions =
+ mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
if (predictions) {
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Valid,
- std::move(*predictions), mTimeStats,
- mJankClassificationThresholds, &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Valid, std::move(*predictions),
+ mTimeStats, mJankClassificationThresholds,
+ &mTraceCookieCounter);
}
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Expired,
- TimelineItem(), mTimeStats, mJankClassificationThresholds,
- &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Expired, TimelineItem(), mTimeStats,
+ mJankClassificationThresholds, &mTraceCookieCounter);
}
FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
@@ -669,13 +676,13 @@
void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
}
void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod,
mTokenManager.getPredictionsForToken(token), wakeUpTime);
}
@@ -683,7 +690,7 @@
void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
flushPendingPresentFences();
@@ -826,7 +833,7 @@
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace DisplayFrame with invalid token");
missingToken = true;
return;
@@ -999,7 +1006,7 @@
}
void FrameTimeline::dumpAll(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
@@ -1009,7 +1016,7 @@
}
void FrameTimeline::dumpJank(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
@@ -1031,7 +1038,7 @@
}
void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
// The size can either increase or decrease, clear everything, to be consistent
mDisplayFrames.clear();