Merge "Disallow accessing data outside of vsync callback" into udc-dev
This commit is contained in:
@@ -888,7 +888,7 @@ public final class Choreographer {
|
|||||||
|
|
||||||
void doCallbacks(int callbackType, long frameIntervalNanos) {
|
void doCallbacks(int callbackType, long frameIntervalNanos) {
|
||||||
CallbackRecord callbacks;
|
CallbackRecord callbacks;
|
||||||
long frameTimeNanos = mFrameData.getFrameTimeNanos();
|
long frameTimeNanos = mFrameData.mFrameTimeNanos;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// We use "now" to determine when callbacks become due because it's possible
|
// 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
|
// for earlier processing phases in a frame to post callbacks that should run
|
||||||
@@ -1042,11 +1042,23 @@ public final class Choreographer {
|
|||||||
private long mVsyncId = FrameInfo.INVALID_VSYNC_ID;
|
private long mVsyncId = FrameInfo.INVALID_VSYNC_ID;
|
||||||
private long mExpectedPresentationTimeNanos = -1;
|
private long mExpectedPresentationTimeNanos = -1;
|
||||||
private long mDeadlineNanos = -1;
|
private long mDeadlineNanos = -1;
|
||||||
|
private boolean mInCallback = false;
|
||||||
|
|
||||||
FrameTimeline() {
|
FrameTimeline() {
|
||||||
// Intentionally empty; defined so that it is not API/public by default.
|
// Intentionally empty; defined so that it is not API/public by default.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setInCallback(boolean inCallback) {
|
||||||
|
mInCallback = inCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInCallback() {
|
||||||
|
if (!mInCallback) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"FrameTimeline is not valid outside of the vsync callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) {
|
void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) {
|
||||||
mVsyncId = vsyncId;
|
mVsyncId = vsyncId;
|
||||||
mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
|
mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
|
||||||
@@ -1058,6 +1070,7 @@ public final class Choreographer {
|
|||||||
* produced by HWUI with the timeline data stored in Surface Flinger.
|
* produced by HWUI with the timeline data stored in Surface Flinger.
|
||||||
*/
|
*/
|
||||||
public long getVsyncId() {
|
public long getVsyncId() {
|
||||||
|
checkInCallback();
|
||||||
return mVsyncId;
|
return mVsyncId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,6 +1079,7 @@ public final class Choreographer {
|
|||||||
* presented.
|
* presented.
|
||||||
*/
|
*/
|
||||||
public long getExpectedPresentationTimeNanos() {
|
public long getExpectedPresentationTimeNanos() {
|
||||||
|
checkInCallback();
|
||||||
return mExpectedPresentationTimeNanos;
|
return mExpectedPresentationTimeNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1073,6 +1087,7 @@ public final class Choreographer {
|
|||||||
* The time in {@link System#nanoTime()} timebase which this frame needs to be ready by.
|
* The time in {@link System#nanoTime()} timebase which this frame needs to be ready by.
|
||||||
*/
|
*/
|
||||||
public long getDeadlineNanos() {
|
public long getDeadlineNanos() {
|
||||||
|
checkInCallback();
|
||||||
return mDeadlineNanos;
|
return mDeadlineNanos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1087,6 +1102,7 @@ public final class Choreographer {
|
|||||||
private final FrameTimeline[] mFrameTimelines =
|
private final FrameTimeline[] mFrameTimelines =
|
||||||
new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH];
|
new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH];
|
||||||
private int mPreferredFrameTimelineIndex;
|
private int mPreferredFrameTimelineIndex;
|
||||||
|
private boolean mInCallback = false;
|
||||||
|
|
||||||
FrameData() {
|
FrameData() {
|
||||||
for (int i = 0; i < mFrameTimelines.length; i++) {
|
for (int i = 0; i < mFrameTimelines.length; i++) {
|
||||||
@@ -1096,6 +1112,7 @@ public final class Choreographer {
|
|||||||
|
|
||||||
/** The time in nanoseconds when the frame started being rendered. */
|
/** The time in nanoseconds when the frame started being rendered. */
|
||||||
public long getFrameTimeNanos() {
|
public long getFrameTimeNanos() {
|
||||||
|
checkInCallback();
|
||||||
return mFrameTimeNanos;
|
return mFrameTimeNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,15 +1120,31 @@ public final class Choreographer {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@SuppressLint("ArrayReturn") // For API consistency and speed.
|
@SuppressLint("ArrayReturn") // For API consistency and speed.
|
||||||
public FrameTimeline[] getFrameTimelines() {
|
public FrameTimeline[] getFrameTimelines() {
|
||||||
|
checkInCallback();
|
||||||
return mFrameTimelines;
|
return mFrameTimelines;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The platform-preferred frame timeline. */
|
/** The platform-preferred frame timeline. */
|
||||||
@NonNull
|
@NonNull
|
||||||
public FrameTimeline getPreferredFrameTimeline() {
|
public FrameTimeline getPreferredFrameTimeline() {
|
||||||
|
checkInCallback();
|
||||||
return mFrameTimelines[mPreferredFrameTimelineIndex];
|
return mFrameTimelines[mPreferredFrameTimelineIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setInCallback(boolean inCallback) {
|
||||||
|
mInCallback = inCallback;
|
||||||
|
for (int i = 0; i < mFrameTimelines.length; i++) {
|
||||||
|
mFrameTimelines[i].setInCallback(inCallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkInCallback() {
|
||||||
|
if (!mInCallback) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"FrameData is not valid outside of the vsync callback");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from
|
* Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from
|
||||||
* native.
|
* native.
|
||||||
@@ -1142,16 +1175,16 @@ public final class Choreographer {
|
|||||||
long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) {
|
long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) {
|
||||||
int newPreferredIndex = 0;
|
int newPreferredIndex = 0;
|
||||||
final long minimumDeadline =
|
final long minimumDeadline =
|
||||||
getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
|
mFrameTimelines[mPreferredFrameTimelineIndex].mDeadlineNanos + jitterNanos;
|
||||||
// Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
|
// 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
|
// 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.
|
// only called when the existing frame data does not hold a valid frame.
|
||||||
while (newPreferredIndex < mFrameTimelines.length - 1
|
while (newPreferredIndex < mFrameTimelines.length - 1
|
||||||
&& mFrameTimelines[newPreferredIndex].getDeadlineNanos() < minimumDeadline) {
|
&& mFrameTimelines[newPreferredIndex].mDeadlineNanos < minimumDeadline) {
|
||||||
newPreferredIndex++;
|
newPreferredIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
long newPreferredDeadline = mFrameTimelines[newPreferredIndex].getDeadlineNanos();
|
long newPreferredDeadline = mFrameTimelines[newPreferredIndex].mDeadlineNanos;
|
||||||
if (newPreferredDeadline < minimumDeadline) {
|
if (newPreferredDeadline < minimumDeadline) {
|
||||||
DisplayEventReceiver.VsyncEventData latestVsyncEventData =
|
DisplayEventReceiver.VsyncEventData latestVsyncEventData =
|
||||||
displayEventReceiver.getLatestVsyncEventData();
|
displayEventReceiver.getLatestVsyncEventData();
|
||||||
@@ -1288,11 +1321,13 @@ public final class Choreographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void run(FrameData frameData) {
|
void run(FrameData frameData) {
|
||||||
|
frameData.setInCallback(true);
|
||||||
if (token == VSYNC_CALLBACK_TOKEN) {
|
if (token == VSYNC_CALLBACK_TOKEN) {
|
||||||
((VsyncCallback) action).onVsync(frameData);
|
((VsyncCallback) action).onVsync(frameData);
|
||||||
} else {
|
} else {
|
||||||
run(frameData.getFrameTimeNanos());
|
run(frameData.getFrameTimeNanos());
|
||||||
}
|
}
|
||||||
|
frameData.setInCallback(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user