diff options
| -rw-r--r-- | core/java/android/view/Choreographer.java | 14 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 15 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 9 | ||||
| -rw-r--r-- | graphics/java/android/graphics/FrameInfo.java | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowAnimator.java | 7 |
5 files changed, 44 insertions, 2 deletions
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 042808a4cad2..e520d7ccaa7a 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -181,6 +181,7 @@ public final class Choreographer { private long mFrameIntervalNanos; private boolean mDebugPrintNextFrameTimeDelta; private int mFPSDivisor = 1; + private long mLastVsyncId = FrameInfo.INVALID_VSYNC_ID; /** * Contains information about the current frame for jank-tracking, @@ -654,6 +655,18 @@ public final class Choreographer { } } + /** + * Returns the vsync id of the last frame callback. Client are expected to call + * this function from their frame callback function to get the vsyncId and pass + * it together with a buffer or transaction to the Surface Composer. Calling + * this function from anywhere else will return an undefined value. + * + * @hide + */ + public long getVsyncId() { + return mLastVsyncId; + } + void setFPSDivisor(int divisor) { if (divisor <= 0) divisor = 1; mFPSDivisor = divisor; @@ -713,6 +726,7 @@ public final class Choreographer { mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos, frameTimelineVsyncId); mFrameScheduled = false; mLastFrameTimeNanos = frameTimeNanos; + mLastVsyncId = frameTimelineVsyncId; } try { diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c698b926e233..44e603ea4900 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -225,6 +225,8 @@ public final class SurfaceControl implements Parcelable { int transformHint); private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken, IBinder focusedToken, int displayId); + private static native void nativeSetFrameTimelineVsync(long transactionObj, + long frameTimelineVsyncId); @Nullable @GuardedBy("mLock") @@ -3341,6 +3343,19 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the frame timeline vsync id received from choreographer + * {@link Choreographer#getVsyncId()} that corresponds to the transaction submitted on that + * surface control. + * + * @hide + */ + @NonNull + public Transaction setFrameTimelineVsync(long frameTimelineVsyncId) { + nativeSetFrameTimelineVsync(mNativeObject, frameTimelineVsyncId); + return this; + } + + /** * Writes the transaction to parcel, clearing the transaction as if it had been applied so * it can be used to store future transactions. It's the responsibility of the parcel * reader to apply the original transaction. diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 9efe4b15ce7a..ba18b56156a4 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -1557,6 +1557,13 @@ static void nativeSetFocusedWindow(JNIEnv* env, jclass clazz, jlong transactionO displayId); } +static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transactionObj, + jlong frameTimelineVsyncId) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + + transaction->setFrameTimelineVsync(frameTimelineVsyncId); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod sSurfaceControlMethods[] = { @@ -1741,6 +1748,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetFixedTransformHint}, {"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Landroid/os/IBinder;I)V", (void*)nativeSetFocusedWindow}, + {"nativeSetFrameTimelineVsync", "(JJ)V", + (void*)nativeSetFrameTimelineVsync }, // clang-format on }; diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java index 163823fde9f7..f768bc741447 100644 --- a/graphics/java/android/graphics/FrameInfo.java +++ b/graphics/java/android/graphics/FrameInfo.java @@ -52,6 +52,7 @@ public final class FrameInfo { public static final long FLAG_SURFACE_CANVAS = 1 << 2; // An invalid vsync id to be used when FRAME_TIMELINE_VSYNC_ID is unknown + // Needs to be in sync with android::ISurfaceComposer::INVALID_VSYNC_ID in native code public static final long INVALID_VSYNC_ID = -1; @LongDef(flag = true, value = { diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 5c6266a2f8c4..ff5c17487413 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -103,7 +103,8 @@ public class WindowAnimator { mAnimationFrameCallback = frameTimeNs -> { synchronized (mService.mGlobalLock) { mAnimationFrameCallbackScheduled = false; - animate(frameTimeNs); + final long vsyncId = mChoreographer.getVsyncId(); + animate(frameTimeNs, vsyncId); if (mNotifyWhenNoAnimation && !mLastRootAnimating) { mService.mGlobalLock.notifyAll(); } @@ -125,7 +126,7 @@ public class WindowAnimator { mInitialized = true; } - private void animate(long frameTimeNs) { + private void animate(long frameTimeNs, long vsyncId) { if (!mInitialized) { return; } @@ -133,6 +134,8 @@ public class WindowAnimator { // Schedule next frame already such that back-pressure happens continuously. scheduleAnimation(); + mTransaction.setFrameTimelineVsync(vsyncId); + mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS; mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; if (DEBUG_WINDOW_TRACE) { |