Skip to content

Commit 519e91e

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Detect bad behavior earlier in Choreographer." into jb-dev
2 parents 72b8fc7 + 4fdf9c6 commit 519e91e

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

core/java/android/view/Choreographer.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ protected Choreographer initialValue() {
103103
private static final boolean USE_FRAME_TIME = SystemProperties.getBoolean(
104104
"debug.choreographer.frametime", true);
105105

106+
// Set a limit to warn about skipped frames.
107+
// Skipped frames imply jank.
108+
private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
109+
"debug.choreographer.skipwarning", 30);
110+
106111
private static final long NANOS_PER_MS = 1000000;
107112

108113
private static final int MSG_DO_FRAME = 0;
@@ -486,21 +491,26 @@ void doFrame(long frameTimeNanos, int frame) {
486491
startNanos = System.nanoTime();
487492
final long jitterNanos = startNanos - frameTimeNanos;
488493
if (jitterNanos >= mFrameIntervalNanos) {
494+
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
495+
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
496+
Log.w(TAG, "Skipped " + skippedFrames + " frames! "
497+
+ "The application may be doing too much work on its main thread.");
498+
}
489499
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
490500
if (DEBUG) {
491501
Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
492502
+ "which is more than the frame interval of "
493503
+ (mFrameIntervalNanos * 0.000001f) + " ms! "
494-
+ "Setting frame time to " + (lastFrameOffset * 0.000001f)
495-
+ " ms in the past.");
504+
+ "Skipping " + skippedFrames + " frames and setting frame "
505+
+ "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
496506
}
497507
frameTimeNanos = startNanos - lastFrameOffset;
498508
}
499509

500510
if (frameTimeNanos < mLastFrameTimeNanos) {
501511
if (DEBUG) {
502512
Log.d(TAG, "Frame time appears to be going backwards. May be due to a "
503-
+ "previously skipped frame. Waiting for next vsync");
513+
+ "previously skipped frame. Waiting for next vsync.");
504514
}
505515
scheduleVsyncLocked();
506516
return;
@@ -658,6 +668,7 @@ public void handleMessage(Message msg) {
658668

659669
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
660670
implements Runnable {
671+
private boolean mHavePendingVsync;
661672
private long mTimestampNanos;
662673
private int mFrame;
663674

@@ -672,6 +683,21 @@ public void onVsync(long timestampNanos, int frame) {
672683
// the message queue. If there are no messages in the queue with timestamps
673684
// earlier than the frame time, then the vsync event will be processed immediately.
674685
// Otherwise, messages that predate the vsync event will be handled first.
686+
long now = System.nanoTime();
687+
if (timestampNanos > now) {
688+
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
689+
+ " ms in the future! Check that graphics HAL is generating vsync "
690+
+ "timestamps using the correct timebase.");
691+
timestampNanos = now;
692+
}
693+
694+
if (mHavePendingVsync) {
695+
Log.w(TAG, "Already have a pending vsync event. There should only be "
696+
+ "one at a time.");
697+
} else {
698+
mHavePendingVsync = true;
699+
}
700+
675701
mTimestampNanos = timestampNanos;
676702
mFrame = frame;
677703
Message msg = Message.obtain(mHandler, this);
@@ -681,6 +707,7 @@ public void onVsync(long timestampNanos, int frame) {
681707

682708
@Override
683709
public void run() {
710+
mHavePendingVsync = false;
684711
doFrame(mTimestampNanos, mFrame);
685712
}
686713
}

0 commit comments

Comments
 (0)