diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 8e3cc34706fc8..a521809eb9407 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -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; + } } /** diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index 774bab41fb9a9..3a74b2ed63a7c 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -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, diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp index 19402f7ed71a9..05855867ed625 100644 --- a/core/jni/android_view_DisplayEventReceiver.cpp +++ b/core/jni/android_view_DisplayEventReceiver.cpp @@ -108,6 +108,32 @@ void NativeDisplayEventReceiver::dispose() { DisplayEventDispatcher::dispose(); } +static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventData) { + ScopedLocalRef + 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 + 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 - 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 - frameTimelineObj(env, - env->NewObject(gDisplayEventReceiverClassInfo - .frameTimelineClassInfo.clazz, - gDisplayEventReceiverClassInfo - .frameTimelineClassInfo.init, - frameTimeline.vsyncId, - frameTimeline.expectedPresentationTime, - frameTimeline.deadlineTimestamp)); - env->SetObjectArrayElement(frameTimelineObjs.get(), i, frameTimelineObj.get()); - } - ScopedLocalRef - 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 receiver = + reinterpret_cast(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,