summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/Choreographer.java140
-rw-r--r--core/java/android/view/DisplayEventReceiver.java11
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.