Merge "Disallow accessing data outside of vsync callback" into udc-dev

This commit is contained in:
Rachel Lee
2023-03-02 02:51:24 +00:00
committed by Android (Google) Code Review

View File

@@ -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);
} }
} }