Send flush  transactions if jank data doesn't arrive in time.

The jank data flush transactions will wake up SurfaceFlinger and have it
process any possibly available jank data and report it back to us. This
is useful if no other transactions are submitted on a surface we care
about and would otherwise time out waiting for jank data.

Bug: 235178314
Bug: 221393601
Bug: 225105422
Test: atest SurfaceFlinger_test
Change-Id: I38f7a084f72f0e73013f854d432baeb54a511ae8
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index e4195d2..3226669 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -68,6 +68,9 @@
 
     private static final int MAX_LENGTH_EVENT_DESC = 20;
 
+    private static final int MAX_FLUSH_ATTEMPTS = 3;
+    private static final int FLUSH_DELAY_MILLISECOND = 60;
+
     static final int REASON_END_UNKNOWN = -1;
     static final int REASON_END_NORMAL = 0;
     static final int REASON_END_SURFACE_DESTROYED = 1;
@@ -358,11 +361,35 @@
             // will remove it when all the frame metrics in this duration are called back.
             // See onFrameMetricsAvailable for the logic of removing the observer.
             // Waiting at most 10 seconds for all callbacks to finish.
-            mWaitForFinishTimedOut = () -> {
-                Log.e(TAG, "force finish cuj because of time out:" + mSession.getName());
-                finish();
+            mWaitForFinishTimedOut = new Runnable() {
+                private int mFlushAttempts = 0;
+
+                @Override
+                public void run() {
+                    if (mWaitForFinishTimedOut == null || mMetricsFinalized) {
+                        return;
+                    }
+
+                    // Send a flush jank data transaction.
+                    if (mSurfaceControl != null && mSurfaceControl.isValid()) {
+                        SurfaceControl.Transaction.sendSurfaceFlushJankData(mSurfaceControl);
+                    }
+
+                    long delay;
+                    if (mFlushAttempts < MAX_FLUSH_ATTEMPTS) {
+                        delay = FLUSH_DELAY_MILLISECOND;
+                        mFlushAttempts++;
+                    } else {
+                        mWaitForFinishTimedOut = () -> {
+                            Log.e(TAG, "force finish cuj, time out: " + mSession.getName());
+                            finish();
+                        };
+                        delay = TimeUnit.SECONDS.toMillis(10);
+                    }
+                    getHandler().postDelayed(mWaitForFinishTimedOut, delay);
+                }
             };
-            getHandler().postDelayed(mWaitForFinishTimedOut, TimeUnit.SECONDS.toMillis(10));
+            getHandler().postDelayed(mWaitForFinishTimedOut, FLUSH_DELAY_MILLISECOND);
             notifyCujEvent(ACTION_SESSION_END);
             return true;
         }
@@ -537,11 +564,12 @@
 
     @UiThread
     private void finish() {
+        if (mMetricsFinalized || mCancelled) return;
+        mMetricsFinalized = true;
+
         getHandler().removeCallbacks(mWaitForFinishTimedOut);
         mWaitForFinishTimedOut = null;
-        if (mMetricsFinalized || mCancelled) return;
         markEvent("FT#finish#" + mJankInfos.size());
-        mMetricsFinalized = true;
 
         // The tracing has been ended, remove the observer, see if need to trigger perfetto.
         removeObservers();