Fix Transaction tracking for FrameTimeline
The current setup only supports one SurfaceFrame per DrawingState for
Transactions. This becomes problematic if more than one Transaction is
submitted for the same vsync, on the same layer. On top of this, the
Blast transactions can have a buffer that could result in a buffer drop.
This change adds the support to hold multiple SurfaceFrames in the
Layer's State. It also adds a bufferSurfaceFrame that's intended only
for Blast Transactions with a Buffer. All other Transactions are tracked
in the bufferlessSurfaceFrames.
Additionally, this change also adds a lastLatchTime. It is needed for
classifying BufferStuffing properly.
Bug: 176106798
Test: open any app from the launcher and at the same time check dumpsys
Change-Id: Id3b8369ca206f8b89be3041e5fc018f1f1be1d23
Merged-In: Id3b8369ca206f8b89be3041e5fc018f1f1be1d23
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4b40c8e..89f2696 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -309,6 +309,20 @@
// When the transaction was posted
nsecs_t postTime;
+
+ // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one
+ // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync.
+ // If multiple buffers are queued, the prior ones will be dropped, along with the
+ // SurfaceFrame that's tracking them.
+ std::shared_ptr<frametimeline::SurfaceFrame> bufferSurfaceFrameTX;
+ // A map of token(frametimelineVsyncId) to the SurfaceFrame that's tracking a transaction
+ // that contains the token. Only one SurfaceFrame exisits for transactions that share the
+ // same token, unless they are presented in different vsyncs.
+ std::unordered_map<int64_t, std::shared_ptr<frametimeline::SurfaceFrame>>
+ bufferlessSurfaceFramesTX;
+ // An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to
+ // trigger a warning if the number of SurfaceFrames crosses the threshold.
+ static constexpr uint32_t kStateSurfaceFramesThreshold = 25;
};
/*
@@ -447,7 +461,8 @@
virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/,
nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/,
- uint64_t /* frameNumber */, std::optional<nsecs_t> /* dequeueTime */) {
+ uint64_t /* frameNumber */, std::optional<nsecs_t> /* dequeueTime */,
+ const FrameTimelineInfo& /*info*/) {
return false;
};
virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
@@ -611,6 +626,12 @@
virtual void pushPendingState();
+ /*
+ * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in
+ * both source and target, target's SurfaceFrame will be retained.
+ */
+ void mergeSurfaceFrames(State& source, State& target);
+
/**
* Returns active buffer size in the correct orientation. Buffer size is determined by undoing
* any buffer transformations. If the layer has no buffer then return INVALID_RECT.
@@ -866,8 +887,20 @@
bool setFrameRate(FrameRate);
virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {}
- void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo,
- nsecs_t postTime);
+ void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime);
+ void setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info,
+ nsecs_t postTime);
+
+ void addSurfaceFrameDroppedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
+ void addSurfaceFramePresentedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime,
+ nsecs_t currentLatchTime);
+
+ std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForTransaction(
+ const FrameTimelineInfo& info, nsecs_t postTime);
+ std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForBuffer(
+ const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName);
// Creates a new handle each time, so we only expect
// this to be called once.
@@ -972,6 +1005,7 @@
friend class TestableSurfaceFlinger;
friend class RefreshRateSelectionTest;
friend class SetFrameRateTest;
+ friend class TransactionSurfaceFrameTest;
virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom);
virtual std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
@@ -980,7 +1014,7 @@
const LayerFE::LayerSettings&, const Rect& layerStackRect,
ui::Dataspace outputDataspace);
virtual void preparePerFrameCompositionState();
- virtual void commitTransaction(const State& stateToCommit);
+ virtual void commitTransaction(State& stateToCommit);
virtual bool applyPendingStates(State* stateToCommit);
virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {}
@@ -1116,6 +1150,10 @@
// If created from a system process, the value can be passed in.
pid_t mOwnerPid;
+ // Keeps track of the time SF latched the last buffer from this layer.
+ // Used in buffer stuffing analysis in FrameTimeline.
+ nsecs_t mLastLatchTime = 0;
+
private:
virtual void setTransformHint(ui::Transform::RotationFlags) {}