Loading core/java/com/android/internal/jank/FrameTracker.java +17 −5 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Trace; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.util.StatsLog; import android.view.Choreographer; import android.view.FrameMetrics; import android.view.SurfaceControl; Loading Loading @@ -481,6 +480,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener int missedFramesCount = 0; int missedAppFramesCount = 0; int missedSfFramesCount = 0; int maxSuccessiveMissedFramesCount = 0; int successiveMissedFramesCount = 0; for (int i = 0; i < mJankInfos.size(); i++) { JankInfo info = mJankInfos.valueAt(i); Loading Loading @@ -510,6 +511,11 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } if (missedFrame) { missedFramesCount++; successiveMissedFramesCount++; } else { maxSuccessiveMissedFramesCount = Math.max( maxSuccessiveMissedFramesCount, successiveMissedFramesCount); successiveMissedFramesCount = 0; } // TODO (b/174755489): Early latch currently gets fired way too often, so we have // to ignore it for now. Loading @@ -524,6 +530,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } } maxSuccessiveMissedFramesCount = Math.max( maxSuccessiveMissedFramesCount, successiveMissedFramesCount); // Log the frame stats as counters to make them easily accessible in traces. Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames", Loading @@ -536,6 +544,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener totalFramesCount); Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis", (int) (maxFrameTimeNanos / NANOS_IN_MILLISECOND)); Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxSuccessiveMissedFrames", maxSuccessiveMissedFramesCount); // Trigger perfetto if necessary. if (shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) { Loading @@ -549,7 +559,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener missedFramesCount, maxFrameTimeNanos, /* will be 0 if mSurfaceOnly == true */ missedSfFramesCount, missedAppFramesCount); missedAppFramesCount, maxSuccessiveMissedFramesCount); } if (DEBUG) { Log.i(TAG, "finish: CUJ=" + mSession.getName() Loading @@ -558,7 +569,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener + " missedAppFrames=" + missedAppFramesCount + " missedSfFrames=" + missedSfFramesCount + " missedFrames=" + missedFramesCount + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND); + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND + " maxSuccessiveMissedFramesCount=" + maxSuccessiveMissedFramesCount); } } Loading Loading @@ -694,8 +706,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener public static class StatsLogWrapper { public void write(int code, int arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6); int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } } Loading core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +47 −9 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(5000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -196,7 +197,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, eq(1L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -230,7 +232,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -264,7 +267,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -301,7 +305,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(50000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } /** Loading Loading @@ -340,7 +345,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -462,7 +468,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -496,7 +503,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -530,7 +538,37 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test public void testMaxSuccessiveMissedFramesCount() { FrameTracker tracker = spyFrameTracker( CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 104L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 105L); when(mChoreographer.getVsyncId()).thenReturn(106L); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(6L) /* totalFrames */, eq(5L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(2L) /* missedSfFramesCount */, eq(3L) /* missedAppFramesCount */, eq(3L) /* maxSuccessiveMissedFramesCount */); } private void sendFirstWindowFrame(FrameTracker tracker, long durationMillis, Loading Loading
core/java/com/android/internal/jank/FrameTracker.java +17 −5 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Trace; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.util.StatsLog; import android.view.Choreographer; import android.view.FrameMetrics; import android.view.SurfaceControl; Loading Loading @@ -481,6 +480,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener int missedFramesCount = 0; int missedAppFramesCount = 0; int missedSfFramesCount = 0; int maxSuccessiveMissedFramesCount = 0; int successiveMissedFramesCount = 0; for (int i = 0; i < mJankInfos.size(); i++) { JankInfo info = mJankInfos.valueAt(i); Loading Loading @@ -510,6 +511,11 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } if (missedFrame) { missedFramesCount++; successiveMissedFramesCount++; } else { maxSuccessiveMissedFramesCount = Math.max( maxSuccessiveMissedFramesCount, successiveMissedFramesCount); successiveMissedFramesCount = 0; } // TODO (b/174755489): Early latch currently gets fired way too often, so we have // to ignore it for now. Loading @@ -524,6 +530,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } } } maxSuccessiveMissedFramesCount = Math.max( maxSuccessiveMissedFramesCount, successiveMissedFramesCount); // Log the frame stats as counters to make them easily accessible in traces. Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames", Loading @@ -536,6 +544,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener totalFramesCount); Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis", (int) (maxFrameTimeNanos / NANOS_IN_MILLISECOND)); Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxSuccessiveMissedFrames", maxSuccessiveMissedFramesCount); // Trigger perfetto if necessary. if (shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) { Loading @@ -549,7 +559,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener missedFramesCount, maxFrameTimeNanos, /* will be 0 if mSurfaceOnly == true */ missedSfFramesCount, missedAppFramesCount); missedAppFramesCount, maxSuccessiveMissedFramesCount); } if (DEBUG) { Log.i(TAG, "finish: CUJ=" + mSession.getName() Loading @@ -558,7 +569,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener + " missedAppFrames=" + missedAppFramesCount + " missedSfFrames=" + missedSfFramesCount + " missedFrames=" + missedFramesCount + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND); + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND + " maxSuccessiveMissedFramesCount=" + maxSuccessiveMissedFramesCount); } } Loading Loading @@ -694,8 +706,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener public static class StatsLogWrapper { public void write(int code, int arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6); int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } } Loading
core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +47 −9 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(5000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -196,7 +197,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, eq(1L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -230,7 +232,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -264,7 +267,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(40000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -301,7 +305,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(50000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } /** Loading Loading @@ -340,7 +345,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(4000000L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -462,7 +468,8 @@ public class FrameTrackerTest { eq(1L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(1L) /* missedAppFramesCount */); eq(1L) /* missedAppFramesCount */, eq(1L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -496,7 +503,8 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test Loading Loading @@ -530,7 +538,37 @@ public class FrameTrackerTest { eq(0L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(0L) /* missedSfFramesCount */, eq(0L) /* missedAppFramesCount */); eq(0L) /* missedAppFramesCount */, eq(0L) /* maxSuccessiveMissedFramesCount */); } @Test public void testMaxSuccessiveMissedFramesCount() { FrameTracker tracker = spyFrameTracker( CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true); when(mChoreographer.getVsyncId()).thenReturn(100L); tracker.begin(); verify(mSurfaceControlWrapper).addJankStatsListener(any(), any()); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 100L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 102L); sendFrame(tracker, JANK_NONE, 103L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 104L); sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 105L); when(mChoreographer.getVsyncId()).thenReturn(106L); tracker.end(FrameTracker.REASON_END_NORMAL); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L); sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L); verify(mSurfaceControlWrapper).removeJankStatsListener(any()); verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(6L) /* totalFrames */, eq(5L) /* missedFrames */, eq(0L) /* maxFrameTimeNanos */, eq(2L) /* missedSfFramesCount */, eq(3L) /* missedAppFramesCount */, eq(3L) /* maxSuccessiveMissedFramesCount */); } private void sendFirstWindowFrame(FrameTracker tracker, long durationMillis, Loading