Loading core/java/android/view/Choreographer.java +26 −16 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } } Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -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; } } /** Loading core/java/android/view/DisplayEventReceiver.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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, Loading core/jni/android_view_DisplayEventReceiver.cpp +47 −41 Original line number Diff line number Diff line Loading @@ -108,14 +108,7 @@ void NativeDisplayEventReceiver::dispose() { DisplayEventDispatcher::dispose(); } void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) { JNIEnv* env = AndroidRuntime::getJNIEnv(); ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventData) { ScopedLocalRef<jobjectArray> frameTimelineObjs(env, env->NewObjectArray(VsyncEventData::kFrameTimelinesLength, Loading @@ -135,18 +128,23 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDispla 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)); 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(); ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); 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); } Loading Loading @@ -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", {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J", (void*)nativeInit}, { "nativeDispose", "(J)V", (void*)nativeDispose }, {"nativeDispose", "(J)V", (void*)nativeDispose}, // @FastNative { "nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync } }; {"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, Loading Loading
core/java/android/view/Choreographer.java +26 −16 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } } Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -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; } } /** Loading
core/java/android/view/DisplayEventReceiver.java +8 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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, Loading
core/jni/android_view_DisplayEventReceiver.cpp +47 −41 Original line number Diff line number Diff line Loading @@ -108,14 +108,7 @@ void NativeDisplayEventReceiver::dispose() { DisplayEventDispatcher::dispose(); } void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) { JNIEnv* env = AndroidRuntime::getJNIEnv(); ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventData) { ScopedLocalRef<jobjectArray> frameTimelineObjs(env, env->NewObjectArray(VsyncEventData::kFrameTimelinesLength, Loading @@ -135,18 +128,23 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDispla 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)); 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(); ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); 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); } Loading Loading @@ -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", {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;II)J", (void*)nativeInit}, { "nativeDispose", "(J)V", (void*)nativeDispose }, {"nativeDispose", "(J)V", (void*)nativeDispose}, // @FastNative { "nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync } }; {"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, Loading