Merge "Properly run window animations at vsync-sf (1/2)" into oc-dev
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index aac5baa..597be68 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,9 @@
package android.view;
+import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
+import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
+
import android.hardware.display.DisplayManagerGlobal;
import android.os.Handler;
import android.os.Looper;
@@ -102,10 +105,23 @@
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
- return new Choreographer(looper);
+ return new Choreographer(looper, VSYNC_SOURCE_APP);
}
};
+ // Thread local storage for the SF choreographer.
+ private static final ThreadLocal<Choreographer> sSfThreadInstance =
+ new ThreadLocal<Choreographer>() {
+ @Override
+ protected Choreographer initialValue() {
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalStateException("The current thread must have a looper!");
+ }
+ return new Choreographer(looper, VSYNC_SOURCE_SURFACE_FLINGER);
+ }
+ };
+
// Enable/disable vsync for animations and drawing.
private static final boolean USE_VSYNC = SystemProperties.getBoolean(
"debug.choreographer.vsync", true);
@@ -202,10 +218,12 @@
private static final int CALLBACK_LAST = CALLBACK_COMMIT;
- private Choreographer(Looper looper) {
+ private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);
- mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
+ mDisplayEventReceiver = USE_VSYNC
+ ? new FrameDisplayEventReceiver(looper, vsyncSource)
+ : null;
mLastFrameTimeNanos = Long.MIN_VALUE;
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
@@ -233,6 +251,13 @@
return sThreadInstance.get();
}
+ /**
+ * @hide
+ */
+ public static Choreographer getSfInstance() {
+ return sSfThreadInstance.get();
+ }
+
/** Destroys the calling thread's choreographer
* @hide
*/
@@ -816,8 +841,8 @@
private long mTimestampNanos;
private int mFrame;
- public FrameDisplayEventReceiver(Looper looper) {
- super(looper);
+ public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
+ super(looper, vsyncSource);
}
@Override
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 67cdfc5..caadc36 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -35,6 +35,23 @@
* @hide
*/
public abstract class DisplayEventReceiver {
+
+ /**
+ * When retrieving vsync events, this specifies that the vsync event should happen at the normal
+ * vsync-app tick.
+ * <p>
+ * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
+ */
+ public static final int VSYNC_SOURCE_APP = 0;
+
+ /**
+ * When retrieving vsync events, this specifies that the vsync event should happen whenever
+ * Surface Flinger is processing a frame.
+ * <p>
+ * Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h
+ */
+ public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;
+
private static final String TAG = "DisplayEventReceiver";
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -46,7 +63,7 @@
private MessageQueue mMessageQueue;
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
- MessageQueue messageQueue);
+ MessageQueue messageQueue, int vsyncSource);
private static native void nativeDispose(long receiverPtr);
@FastNative
private static native void nativeScheduleVsync(long receiverPtr);
@@ -55,14 +72,16 @@
* Creates a display event receiver.
*
* @param looper The looper to use when invoking callbacks.
+ * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
*/
- public DisplayEventReceiver(Looper looper) {
+ public DisplayEventReceiver(Looper looper, int vsyncSource) {
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mMessageQueue = looper.getQueue();
- mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
+ mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
+ vsyncSource);
mCloseGuard.open("dispose");
}
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 2eada3e..831393b 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -47,7 +47,7 @@
class NativeDisplayEventReceiver : public DisplayEventDispatcher {
public:
NativeDisplayEventReceiver(JNIEnv* env,
- jobject receiverWeak, const sp<MessageQueue>& messageQueue);
+ jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource);
void dispose();
@@ -65,8 +65,9 @@
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
- jobject receiverWeak, const sp<MessageQueue>& messageQueue) :
- DisplayEventDispatcher(messageQueue->getLooper()),
+ jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
+ DisplayEventDispatcher(messageQueue->getLooper(),
+ static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mMessageQueue(messageQueue) {
ALOGV("receiver %p ~ Initializing display event receiver.", this);
@@ -113,7 +114,7 @@
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
- jobject messageQueueObj) {
+ jobject messageQueueObj, jint vsyncSource) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
@@ -121,7 +122,7 @@
}
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
- receiverWeak, messageQueue);
+ receiverWeak, messageQueue, vsyncSource);
status_t status = receiver->initialize();
if (status) {
String8 message;
@@ -156,7 +157,7 @@
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
- "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J",
+ "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;I)J",
(void*)nativeInit },
{ "nativeDispose",
"(J)V",
diff --git a/libs/androidfw/DisplayEventDispatcher.cpp b/libs/androidfw/DisplayEventDispatcher.cpp
index b8ef9ea..7708e43 100644
--- a/libs/androidfw/DisplayEventDispatcher.cpp
+++ b/libs/androidfw/DisplayEventDispatcher.cpp
@@ -33,8 +33,9 @@
// using just a few large reads.
static const size_t EVENT_BUFFER_SIZE = 100;
-DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper) :
- mLooper(looper), mWaitingForVsync(false) {
+DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
+ ISurfaceComposer::VsyncSource vsyncSource) :
+ mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
diff --git a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
index 3ade215..e1dfb94 100644
--- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
+++ b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
@@ -22,7 +22,8 @@
class DisplayEventDispatcher : public LooperCallback {
public:
- DisplayEventDispatcher(const sp<Looper>& looper);
+ DisplayEventDispatcher(const sp<Looper>& looper,
+ ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
status_t initialize();
void dispose();
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 841a951..cdc973b 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -668,7 +668,7 @@
private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
public HotplugDisplayEventReceiver(Looper looper) {
- super(looper);
+ super(looper, VSYNC_SOURCE_APP);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index d85dd0c..03b5b827 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -83,10 +83,6 @@
// check if some got replaced and can be removed.
private boolean mRemoveReplacedWindows = false;
- private long mCurrentFrameTime;
- private final Runnable mAnimationTick;
- private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
-
private Choreographer mChoreographer;
/**
@@ -95,40 +91,19 @@
*/
private boolean mAnimationFrameCallbackScheduled;
- /**
- * Indicates whether we have an animation tick scheduled. The tick is the thing that actually
- * executes the animation step, which will happen at vsync-sf.
- */
- private boolean mAnimationTickScheduled;
-
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
mWindowPlacerLocked = service.mWindowPlacerLocked;
AnimationThread.getHandler().runWithScissors(
- () -> mChoreographer = Choreographer.getInstance(), 0 /* timeout */);
+ () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
- // TODO: Multi-display: If displays have different vsync tick, have a separate tick per
- // display.
- mSfChoreographer = new SurfaceFlingerVsyncChoreographer(AnimationThread.getHandler(),
- mService.getDefaultDisplayContentLocked().getDisplay(), mChoreographer);
- mAnimationTick = () -> {
- synchronized (mService.mWindowMap) {
- mAnimationTickScheduled = false;
- }
- animate(mCurrentFrameTime);
- };
mAnimationFrameCallback = frameTimeNs -> {
synchronized (mService.mWindowMap) {
- mCurrentFrameTime = frameTimeNs;
mAnimationFrameCallbackScheduled = false;
- if (mAnimationTickScheduled) {
- return;
- }
- mAnimationTickScheduled = true;
}
- mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
+ animate(frameTimeNs);
};
}
@@ -422,7 +397,7 @@
}
boolean isAnimationScheduled() {
- return mAnimationFrameCallbackScheduled || mAnimationTickScheduled;
+ return mAnimationFrameCallbackScheduled;
}
Choreographer getChoreographer() {