summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/Choreographer.java85
1 files changed, 45 insertions, 40 deletions
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index cc68ddd9e211..91febcdcb0c4 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -765,11 +765,12 @@ public final class Choreographer {
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= frameIntervalNanos) {
- long lastFrameOffset = 0;
+ frameTimeNanos = startNanos;
if (frameIntervalNanos == 0) {
Log.i(TAG, "Vsync data empty due to timeout");
} else {
- lastFrameOffset = jitterNanos % frameIntervalNanos;
+ long lastFrameOffset = jitterNanos % frameIntervalNanos;
+ frameTimeNanos = frameTimeNanos - lastFrameOffset;
final long skippedFrames = jitterNanos / frameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
@@ -785,8 +786,7 @@ public final class Choreographer {
+ " ms in the past.");
}
}
- frameTimeNanos = startNanos - lastFrameOffset;
- frameData.updateFrameData(frameTimeNanos);
+ frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
}
if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -884,7 +884,7 @@ public final class Choreographer {
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
- frameData.updateFrameData(frameTimeNanos);
+ frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
}
}
}
@@ -998,9 +998,6 @@ public final class Choreographer {
/** Holds data that describes one possible VSync frame event to render at. */
public static class FrameTimeline {
- static final FrameTimeline INVALID_FRAME_TIMELINE = new FrameTimeline(
- FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE);
-
FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) {
this.mVsyncId = vsyncId;
this.mExpectedPresentTimeNanos = expectedPresentTimeNanos;
@@ -1019,11 +1016,6 @@ public final class Choreographer {
return mVsyncId;
}
- /** Reset the vsync ID to invalid. */
- void resetVsyncId() {
- mVsyncId = FrameInfo.INVALID_VSYNC_ID;
- }
-
/**
* The time in {@link System#nanoTime()} timebase which this frame is expected to be
* presented.
@@ -1046,39 +1038,20 @@ public final class Choreographer {
* information including deadline and expected present time.
*/
public static class FrameData {
- static final FrameTimeline[] INVALID_FRAME_TIMELINES = new FrameTimeline[0];
- FrameData() {
- this.mFrameTimelines = INVALID_FRAME_TIMELINES;
- this.mPreferredFrameTimeline = FrameTimeline.INVALID_FRAME_TIMELINE;
- }
-
FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
- FrameTimeline[] frameTimelines =
- new FrameTimeline[vsyncEventData.frameTimelines.length];
- for (int i = 0; i < vsyncEventData.frameTimelines.length; i++) {
- DisplayEventReceiver.VsyncEventData.FrameTimeline frameTimeline =
- vsyncEventData.frameTimelines[i];
- frameTimelines[i] = new FrameTimeline(frameTimeline.vsyncId,
- frameTimeline.expectedPresentTime, frameTimeline.deadline);
- }
this.mFrameTimeNanos = frameTimeNanos;
- this.mFrameTimelines = frameTimelines;
- this.mPreferredFrameTimeline =
- frameTimelines[vsyncEventData.preferredFrameTimelineIndex];
+ this.mFrameTimelines = convertFrameTimelines(vsyncEventData);
+ this.mPreferredFrameTimelineIndex =
+ vsyncEventData.preferredFrameTimelineIndex;
}
private long mFrameTimeNanos;
- private FrameTimeline[] mFrameTimelines;
- private FrameTimeline mPreferredFrameTimeline;
+ private final FrameTimeline[] mFrameTimelines;
+ private int mPreferredFrameTimelineIndex;
- void updateFrameData(long frameTimeNanos) {
+ void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
mFrameTimeNanos = frameTimeNanos;
- for (FrameTimeline ft : mFrameTimelines) {
- // The ID is no longer valid because the frame time that was registered with the ID
- // no longer matches.
- // TODO(b/205721584): Ask SF for valid vsync information.
- ft.resetVsyncId();
- }
+ mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
}
/** The time in nanoseconds when the frame started being rendered. */
@@ -1096,7 +1069,7 @@ public final class Choreographer {
/** The platform-preferred frame timeline. */
@NonNull
public FrameTimeline getPreferredFrameTimeline() {
- return mPreferredFrameTimeline;
+ return mFrameTimelines[mPreferredFrameTimelineIndex];
}
private FrameTimeline[] convertFrameTimelines(
@@ -1114,6 +1087,38 @@ public final class Choreographer {
}
/**
+ * Update the frame data when the frame is late.
+ *
+ * @param jitterNanos currentTime - frameTime
+ */
+ private FrameData getUpdatedFrameData(long frameTimeNanos, FrameData frameData,
+ long jitterNanos) {
+ int newPreferredIndex = 0;
+ FrameTimeline[] frameTimelines = frameData.getFrameTimelines();
+ final long minimumDeadline =
+ frameData.getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
+ // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
+ // query for new frame data. Note that binder is relatively slow, O(ms), so it is
+ // only called when the existing frame data does not hold a valid frame.
+ while (newPreferredIndex < frameTimelines.length - 1
+ && frameTimelines[newPreferredIndex].getDeadlineNanos()
+ < minimumDeadline) {
+ newPreferredIndex++;
+ }
+
+ long newPreferredDeadline =
+ frameData.getFrameTimelines()[newPreferredIndex].getDeadlineNanos();
+ if (newPreferredDeadline < minimumDeadline) {
+ DisplayEventReceiver.VsyncEventData latestVsyncEventData =
+ mDisplayEventReceiver.getLatestVsyncEventData();
+ return new FrameData(frameTimeNanos, latestVsyncEventData);
+ } else {
+ frameData.updateFrameData(frameTimeNanos, newPreferredIndex);
+ return frameData;
+ }
+ }
+
+ /**
* Implement this interface to receive a callback to start the next frame. The callback is
* invoked on the {@link Looper} thread to which the {@link Choreographer} is attached. The
* callback payload contains information about multiple possible frames, allowing choice of