summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/Choreographer.java14
-rw-r--r--core/java/android/view/SurfaceControl.java15
-rw-r--r--core/jni/android_view_SurfaceControl.cpp9
-rw-r--r--graphics/java/android/graphics/FrameInfo.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java7
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) {