diff options
| -rw-r--r-- | core/java/android/view/Choreographer.java | 140 | ||||
| -rw-r--r-- | core/java/android/view/DisplayEventReceiver.java | 11 |
2 files changed, 82 insertions, 69 deletions
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 4a83bbe7e72b..efaddecfd3a9 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -197,6 +197,7 @@ public final class Choreographer { private int mFPSDivisor = 1; private DisplayEventReceiver.VsyncEventData mLastVsyncEventData = new DisplayEventReceiver.VsyncEventData(); + private final FrameData mFrameData = new FrameData(); /** * Contains information about the current frame for jank-tracking, @@ -789,7 +790,7 @@ public final class Choreographer { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId); } - FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData); + mFrameData.update(frameTimeNanos, vsyncEventData); synchronized (mLock) { if (!mFrameScheduled) { traceMessage("Frame not scheduled"); @@ -827,7 +828,7 @@ public final class Choreographer { + " ms in the past."); } } - frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos); + mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos); } if (frameTimeNanos < mLastFrameTimeNanos) { @@ -862,17 +863,16 @@ public final class Choreographer { AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); mFrameInfo.markInputHandlingStart(); - doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos); + doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos); mFrameInfo.markAnimationsStart(); - doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos); - doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData, - frameIntervalNanos); + doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos); + doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos); mFrameInfo.markPerformTraversalsStart(); - doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos); + doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos); - doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos); + doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos); } finally { AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); @@ -886,9 +886,9 @@ public final class Choreographer { } } - void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) { + void doCallbacks(int callbackType, long frameIntervalNanos) { CallbackRecord callbacks; - long frameTimeNanos = frameData.mFrameTimeNanos; + long frameTimeNanos = mFrameData.getFrameTimeNanos(); synchronized (mLock) { // We use "now" to determine when callbacks become due because it's possible // for earlier processing phases in a frame to post callbacks that should run @@ -925,7 +925,7 @@ public final class Choreographer { } frameTimeNanos = now - lastFrameOffset; mLastFrameTimeNanos = frameTimeNanos; - frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos); + mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos); } } } @@ -937,7 +937,7 @@ public final class Choreographer { + ", action=" + c.action + ", token=" + c.token + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime)); } - c.run(frameData); + c.run(mFrameData); } } finally { synchronized (mLock) { @@ -1039,15 +1039,19 @@ public final class Choreographer { /** Holds data that describes one possible VSync frame event to render at. */ public static class FrameTimeline { - FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) { - this.mVsyncId = vsyncId; - this.mExpectedPresentTimeNanos = expectedPresentTimeNanos; - this.mDeadlineNanos = deadlineNanos; + private long mVsyncId = FrameInfo.INVALID_VSYNC_ID; + private long mExpectedPresentationTimeNanos = -1; + private long mDeadlineNanos = -1; + + FrameTimeline() { + // Intentionally empty; defined so that it is not API/public by default. } - private long mVsyncId; - private long mExpectedPresentTimeNanos; - private long mDeadlineNanos; + void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) { + mVsyncId = vsyncId; + mExpectedPresentationTimeNanos = expectedPresentationTimeNanos; + mDeadlineNanos = deadlineNanos; + } /** * The id that corresponds to this frame timeline, used to correlate a frame @@ -1062,7 +1066,7 @@ public final class Choreographer { * presented. */ public long getExpectedPresentationTimeNanos() { - return mExpectedPresentTimeNanos; + return mExpectedPresentationTimeNanos; } /** @@ -1079,20 +1083,15 @@ public final class Choreographer { * information including deadline and expected present time. */ public static class FrameData { - FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) { - this.mFrameTimeNanos = frameTimeNanos; - this.mFrameTimelines = convertFrameTimelines(vsyncEventData); - this.mPreferredFrameTimelineIndex = - vsyncEventData.preferredFrameTimelineIndex; - } - private long mFrameTimeNanos; - private final FrameTimeline[] mFrameTimelines; + private final FrameTimeline[] mFrameTimelines = + new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH]; private int mPreferredFrameTimelineIndex; - void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) { - mFrameTimeNanos = frameTimeNanos; - mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex; + FrameData() { + for (int i = 0; i < mFrameTimelines.length; i++) { + mFrameTimelines[i] = new FrameTimeline(); + } } /** The time in nanoseconds when the frame started being rendered. */ @@ -1113,49 +1112,58 @@ public final class Choreographer { return mFrameTimelines[mPreferredFrameTimelineIndex]; } - private FrameTimeline[] convertFrameTimelines( - DisplayEventReceiver.VsyncEventData vsyncEventData) { - FrameTimeline[] frameTimelines = - new FrameTimeline[vsyncEventData.frameTimelines.length]; + /** + * Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from + * native. + */ + void update(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) { + if (vsyncEventData.frameTimelines.length != mFrameTimelines.length) { + throw new IllegalStateException( + "Length of native frame timelines received does not match Java. Did " + + "FRAME_TIMELINES_LENGTH or kFrameTimelinesLength (native) " + + "change?"); + } + mFrameTimeNanos = frameTimeNanos; + mPreferredFrameTimelineIndex = vsyncEventData.preferredFrameTimelineIndex; 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); + mFrameTimelines[i].update(frameTimeline.vsyncId, + frameTimeline.expectedPresentationTime, frameTimeline.deadline); } - return frameTimelines; } - } - /** - * 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++; + /** + * Update the frame data when the frame is late. + * + * @param jitterNanos currentTime - frameTime + */ + void update( + long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) { + int newPreferredIndex = 0; + final long minimumDeadline = + 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 < mFrameTimelines.length - 1 + && mFrameTimelines[newPreferredIndex].getDeadlineNanos() < minimumDeadline) { + newPreferredIndex++; + } + + long newPreferredDeadline = mFrameTimelines[newPreferredIndex].getDeadlineNanos(); + if (newPreferredDeadline < minimumDeadline) { + DisplayEventReceiver.VsyncEventData latestVsyncEventData = + displayEventReceiver.getLatestVsyncEventData(); + update(frameTimeNanos, latestVsyncEventData); + } else { + update(frameTimeNanos, 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; + void update(long frameTimeNanos, int newPreferredFrameTimelineIndex) { + mFrameTimeNanos = frameTimeNanos; + mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex; } } diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index edce00181335..07ac5977c4e3 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -145,11 +145,16 @@ public abstract class DisplayEventReceiver { static final FrameTimeline[] INVALID_FRAME_TIMELINES = {new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)}; + // The amount of frame timeline choices. + // Must be in sync with VsyncEventData::kFrameTimelinesLength in + // frameworks/native/libs/gui/include/gui/VsyncEventData.h. If they do not match, a runtime + // assertion is thrown when Choreographer is processing VsyncEventData. + static final int FRAME_TIMELINES_LENGTH = 7; public static class FrameTimeline { - FrameTimeline(long vsyncId, long expectedPresentTime, long deadline) { + FrameTimeline(long vsyncId, long expectedPresentationTime, long deadline) { this.vsyncId = vsyncId; - this.expectedPresentTime = expectedPresentTime; + this.expectedPresentationTime = expectedPresentationTime; this.deadline = deadline; } @@ -158,7 +163,7 @@ public abstract class DisplayEventReceiver { public final long vsyncId; // The frame timestamp for when the frame is expected to be presented. - public final long expectedPresentTime; + public final long expectedPresentationTime; // The frame deadline timestamp in {@link System#nanoTime()} timebase that it is // allotted for the frame to be completed. |