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/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(); 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",