Recover from buffer stuffing for canned animations

Buffer stuffing occurs when SurfaceFlinger misses a frame, but the
client continues to produce buffers at the same rate, causing a
greater risk for jank to occur. Recovery is achieved for canned
animations by adjusting the animation timeline on the client side so
that SurfaceFlinger is no longer behind.

Use SF backdoor command 1045 to inject jank.
Usage: adb shell service call SurfaceFlinger 1045 f 1

Bug: b/294922229
Test: atest EventThreadTest
Test: presubmit, manually check perfetto traces
Flag: android.view.flags.buffer_stuffing_recovery
Change-Id: I38f0eb3d6ef1331e07d6022fa3a0e16c556ba06f
diff --git a/libs/gui/BufferStuffing.md b/libs/gui/BufferStuffing.md
new file mode 100644
index 0000000..6ed8ad9
--- /dev/null
+++ b/libs/gui/BufferStuffing.md
@@ -0,0 +1,7 @@
+### Buffer Stuffing and Recovery ###
+
+Buffer stuffing happens on the client side when SurfaceFlinger misses a frame, but the client continues producing buffers at the same rate. This could occur anytime when SurfaceFlinger does not meet the expected timeline’s deadline to finish composing a frame. As a result, SurfaceFlinger cannot yet release the buffer for the frame that it missed and the client has one less buffer to render into. The client may then run out of buffers or have to wait for buffer release callbacks, increasing the chances of janking when clients render multiple windows.
+
+Recovery is implemented by first detecting when buffer stuffing occurs and ensuring that the elevated buffer counts in the server are from a relevant SurfaceControl (is a ViewRootImpl). Other SurfaceControl buffer producers such as games, media, and camera have other reasons for expectedly increased buffer counts, which do not need buffer stuffing recovery.
+
+The actual recovery adjusts the animation timeline in the Choreographer so that the client deadlines for subsequent frames are moved forward in time by one frame. This approach adjusts the client buffer production timeline such that SurfaceFlinger does not fall behind when it misses a frame because the client will simply match its frame production rate with SurfaceFlinger. Ordinarily, buffer stuffing is problematic because the client continues producing buffers when SurfaceFlinger is behind. However, if the client delays producing its buffers to match SurfaceFlinger’s rate, the animation has new frame deadlines that can be reasonably met. The animation is effectively paused for one frame longer than originally intended, and continues the remainder of the animation normally.
\ No newline at end of file
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 4dbf9e1..40a6e79 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -119,7 +119,7 @@
             HdcpLevelsChange hdcpLevelsChange;
         };
     };
-    static_assert(sizeof(Event) == 216);
+    static_assert(sizeof(Event) == 224);
 
 public:
     /*
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 6bfeaec..e296e58 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -170,6 +170,10 @@
         // Sets a property on this layer indicating that its visible region should be considered
         // when computing TrustedPresentation Thresholds.
         eCanOccludePresentation = 0x1000,
+        // Indicates that the SurfaceControl should recover from buffer stuffing when
+        // possible. This is the case when the SurfaceControl is the root SurfaceControl
+        // owned by ViewRootImpl.
+        eRecoverableFromBufferStuffing = 0x2000,
     };
 
     enum {
diff --git a/libs/gui/include/gui/VsyncEventData.h b/libs/gui/include/gui/VsyncEventData.h
index b40a840..ced5130 100644
--- a/libs/gui/include/gui/VsyncEventData.h
+++ b/libs/gui/include/gui/VsyncEventData.h
@@ -36,6 +36,9 @@
     // Size of frame timelines provided by the platform; max is kFrameTimelinesCapacity.
     uint32_t frameTimelinesLength;
 
+    // Number of queued buffers to indicate if buffer stuffing mode is detected.
+    uint32_t numberQueuedBuffers;
+
     struct alignas(8) FrameTimeline {
         // The Vsync Id corresponsing to this vsync event. This will be used to
         // populate ISurfaceComposer::setFrameTimelineVsync and
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 29eeaa8..791f471 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -36,15 +36,16 @@
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameInterval, 8);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.preferredFrameTimelineIndex, 16);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelinesLength, 20);
-    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines, 24);
-    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].vsyncId, 24);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.numberQueuedBuffers, 24);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines, 32);
+    CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].vsyncId, 32);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].deadlineTimestamp,
-                 32);
+                 40);
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync,
-                 vsyncData.frameTimelines[0].expectedPresentationTime, 40);
+                 vsyncData.frameTimelines[0].expectedPresentationTime, 48);
     // Also test the offsets of the last frame timeline. A loop is not used because the non-const
     // index cannot be used in static_assert.
-    const int lastFrameTimelineOffset = /* Start of array */ 24 +
+    const int lastFrameTimelineOffset = /* Start of array */ 32 +
             (VsyncEventData::kFrameTimelinesCapacity - 1) * /* Size of FrameTimeline */ 24;
     CHECK_OFFSET(DisplayEventReceiver::Event::VSync,
                  vsyncData.frameTimelines[VsyncEventData::kFrameTimelinesCapacity - 1].vsyncId,