From 0f50d93d4971e1612b5898a7a8fca7464654a2a9 Mon Sep 17 00:00:00 2001 From: Pascal Muetschard Date: Tue, 13 Dec 2022 13:45:58 +0100 Subject: [PATCH 1/2] Expose the flush jank data transaction via JNI. Bug: 235178314 Bug: 221393601 Bug: 225105422 Test: atest SurfaceFlinger_test Change-Id: I119a5264dfb7b831dc3d0bf051ddcf1a0ffe7e60 --- core/java/android/view/SurfaceControl.java | 10 ++++++++++ core/jni/android_view_SurfaceControl.cpp | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 7da141bc392ad..8e0941144b51e 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -173,6 +173,7 @@ public final class SurfaceControl implements Parcelable { boolean isTrustedOverlay); private static native void nativeSetDropInputMode( long transactionObj, long nativeObject, int flags); + private static native void nativeSurfaceFlushJankData(long nativeSurfaceObject); private static native boolean nativeClearContentFrameStats(long nativeObject); private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats); private static native boolean nativeClearAnimationFrameStats(); @@ -3884,6 +3885,15 @@ public final class SurfaceControl implements Parcelable { return this; } + /** + * Sends a flush jank data transaction for the given surface. + * @hide + */ + public static void sendSurfaceFlushJankData(SurfaceControl sc) { + sc.checkNotReleased(); + nativeSurfaceFlushJankData(sc.mNativeObject); + } + /** * @hide */ diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 97a0f50e760d8..5ca71b89f4834 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -951,6 +951,11 @@ static void nativeSetDropInputMode(JNIEnv* env, jclass clazz, jlong transactionO transaction->setDropInputMode(ctrl, static_cast(mode)); } +static void nativeSurfaceFlushJankData(JNIEnv* env, jclass clazz, jlong nativeObject) { + SurfaceControl* const ctrl = reinterpret_cast(nativeObject); + SurfaceComposerClient::Transaction::sendSurfaceFlushJankDataTransaction(ctrl); +} + static void nativeSanitize(JNIEnv* env, jclass clazz, jlong transactionObj) { auto transaction = reinterpret_cast(transactionObj); transaction->sanitize(); @@ -2246,6 +2251,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetLayerId }, {"nativeSetDropInputMode", "(JJI)V", (void*)nativeSetDropInputMode }, + {"nativeSurfaceFlushJankData", "(J)V", + (void*)nativeSurfaceFlushJankData }, {"nativeAddTransactionCommittedListener", "(JLandroid/view/SurfaceControl$TransactionCommittedListener;)V", (void*) nativeAddTransactionCommittedListener }, {"nativeSetTrustedPresentationCallback", "(JJJLandroid/view/SurfaceControl$TrustedPresentationThresholds;)V", From fce83c935a7ff01a0622b433bec8062a7ff7c9f9 Mon Sep 17 00:00:00 2001 From: Pascal Muetschard Date: Tue, 13 Dec 2022 14:00:07 +0100 Subject: [PATCH 2/2] 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 --- .../android/internal/jank/FrameTracker.java | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java index e4195d29c1ee0..3226669ee750c 100644 --- a/core/java/com/android/internal/jank/FrameTracker.java +++ b/core/java/com/android/internal/jank/FrameTracker.java @@ -68,6 +68,9 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener // 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 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener @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();