Merge "Use getLatestVsyncEventData for late frame." into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-22 22:35:50 +00:00
committed by Android (Google) Code Review
3 changed files with 81 additions and 57 deletions

View File

@@ -779,7 +779,9 @@ public final class Choreographer {
+ "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
}
frameTimeNanos = startNanos - lastFrameOffset;
frameData.setFrameTimeNanos(frameTimeNanos);
DisplayEventReceiver.VsyncEventData latestVsyncEventData =
mDisplayEventReceiver.getLatestVsyncEventData();
frameData.updateFrameData(frameTimeNanos, latestVsyncEventData);
}
if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -877,7 +879,9 @@ public final class Choreographer {
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
frameData.setFrameTimeNanos(frameTimeNanos);
DisplayEventReceiver.VsyncEventData latestVsyncEventData =
mDisplayEventReceiver.getLatestVsyncEventData();
frameData.updateFrameData(frameTimeNanos, latestVsyncEventData);
}
}
}
@@ -1012,11 +1016,6 @@ public final class Choreographer {
return mVsyncId;
}
/** Sets the vsync ID. */
void resetVsyncId() {
mVsyncId = FrameInfo.INVALID_VSYNC_ID;
}
/**
* The time in {@link System#nanoTime()} timebase which this frame is expected to be
* presented.
@@ -1061,17 +1060,15 @@ public final class Choreographer {
}
private long mFrameTimeNanos;
private final FrameTimeline[] mFrameTimelines;
private final FrameTimeline mPreferredFrameTimeline;
private FrameTimeline[] mFrameTimelines;
private FrameTimeline mPreferredFrameTimeline;
void setFrameTimeNanos(long frameTimeNanos) {
void updateFrameData(long frameTimeNanos,
DisplayEventReceiver.VsyncEventData latestVsyncEventData) {
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();
}
mFrameTimelines = convertFrameTimelines(latestVsyncEventData);
mPreferredFrameTimeline =
mFrameTimelines[latestVsyncEventData.preferredFrameTimelineIndex];
}
/** The time in nanoseconds when the frame started being rendered. */
@@ -1091,6 +1088,19 @@ public final class Choreographer {
public FrameTimeline getPreferredFrameTimeline() {
return mPreferredFrameTimeline;
}
private FrameTimeline[] convertFrameTimelines(
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);
}
return frameTimelines;
}
}
/**

View File

@@ -84,6 +84,7 @@ public abstract class DisplayEventReceiver {
private static native void nativeDispose(long receiverPtr);
@FastNative
private static native void nativeScheduleVsync(long receiverPtr);
private static native VsyncEventData nativeGetLatestVsyncEventData(long receiverPtr);
/**
* Creates a display event receiver.
@@ -279,6 +280,13 @@ public abstract class DisplayEventReceiver {
}
}
/**
* Gets the latest vsync event data from surface flinger.
*/
VsyncEventData getLatestVsyncEventData() {
return nativeGetLatestVsyncEventData(mReceiverPtr);
}
// Called from native code.
@SuppressWarnings("unused")
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,

View File

@@ -108,6 +108,32 @@ void NativeDisplayEventReceiver::dispose() {
DisplayEventDispatcher::dispose();
}
static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventData) {
ScopedLocalRef<jobjectArray>
frameTimelineObjs(env,
env->NewObjectArray(VsyncEventData::kFrameTimelinesLength,
gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.clazz,
/*initial element*/ NULL));
for (int i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
VsyncEventData::FrameTimeline frameTimeline = vsyncEventData.frameTimelines[i];
ScopedLocalRef<jobject>
frameTimelineObj(env,
env->NewObject(gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.clazz,
gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.init,
frameTimeline.vsyncId,
frameTimeline.expectedPresentationTime,
frameTimeline.deadlineTimestamp));
env->SetObjectArrayElement(frameTimelineObjs.get(), i, frameTimelineObj.get());
}
return env->NewObject(gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.init,
frameTimelineObjs.get(), vsyncEventData.preferredFrameTimelineIndex,
vsyncEventData.frameInterval);
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
uint32_t count, VsyncEventData vsyncEventData) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -116,37 +142,9 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDispla
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking vsync handler.", this);
ScopedLocalRef<jobjectArray>
frameTimelineObjs(env,
env->NewObjectArray(VsyncEventData::kFrameTimelinesLength,
gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.clazz,
/*initial element*/ NULL));
for (int i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
VsyncEventData::FrameTimeline frameTimeline = vsyncEventData.frameTimelines[i];
ScopedLocalRef<jobject>
frameTimelineObj(env,
env->NewObject(gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.clazz,
gDisplayEventReceiverClassInfo
.frameTimelineClassInfo.init,
frameTimeline.vsyncId,
frameTimeline.expectedPresentationTime,
frameTimeline.deadlineTimestamp));
env->SetObjectArrayElement(frameTimelineObjs.get(), i, frameTimelineObj.get());
}
ScopedLocalRef<jobject>
vsyncEventDataJava(env,
env->NewObject(gDisplayEventReceiverClassInfo
.vsyncEventDataClassInfo.clazz,
gDisplayEventReceiverClassInfo
.vsyncEventDataClassInfo.init,
frameTimelineObjs.get(),
vsyncEventData.preferredFrameTimelineIndex,
vsyncEventData.frameInterval));
jobject javaVsyncEventData = createJavaVsyncEventData(env, vsyncEventData);
env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
timestamp, displayId.value, count, vsyncEventDataJava.get());
timestamp, displayId.value, count, javaVsyncEventData);
ALOGV("receiver %p ~ Returned from vsync handler.", this);
}
@@ -255,19 +253,27 @@ static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
}
}
static jobject nativeGetLatestVsyncEventData(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp<NativeDisplayEventReceiver> receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
gui::ParcelableVsyncEventData parcelableVsyncEventData;
status_t status = receiver->getLatestVsyncEventData(&parcelableVsyncEventData);
if (status) {
ALOGW("Failed to get latest vsync event data from surface flinger");
return NULL;
}
return createJavaVsyncEventData(env, parcelableVsyncEventData.vsync);
}
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J",
(void*)nativeInit },
{ "nativeDispose",
"(J)V",
(void*)nativeDispose },
// @FastNative
{ "nativeScheduleVsync", "(J)V",
(void*)nativeScheduleVsync }
};
/* name, signature, funcPtr */
{"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J",
(void*)nativeInit},
{"nativeDispose", "(J)V", (void*)nativeDispose},
// @FastNative
{"nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync},
{"nativeGetLatestVsyncEventData", "(J)Landroid/view/DisplayEventReceiver$VsyncEventData;",
(void*)nativeGetLatestVsyncEventData}};
int register_android_view_DisplayEventReceiver(JNIEnv* env) {
int res = RegisterMethodsOrDie(env, "android/view/DisplayEventReceiver", gMethods,