Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59bbef0c authored by Jeff Brown's avatar Jeff Brown
Browse files

Improve animation timing.

Detect when a vsync message was significantly delayed which may
indicate that a frame was skipped.  When this happens, update
the frame time to reflect the approximate start time of the
current frame instead of the start time of the frame that was
skipped a long time ago.

Removed an unnecessary call to getCurrentPlayTime() in the
animator framework.  The result was always zero and the call
just made the code confusing.

Bug: 6443611
Change-Id: I92b24f7ffd74c59b75a727b6bfc0bb51fc92a73a
parent 2321301f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -910,7 +910,7 @@ public class ValueAnimator extends Animator {
        animationHandler.mPendingAnimations.add(this);
        if (mStartDelay == 0) {
            // This sets the initial value of the animation, prior to actually starting it running
            setCurrentPlayTime(getCurrentPlayTime());
            setCurrentPlayTime(0);
            mPlayingState = STOPPED;
            mRunning = true;
            notifyStartListeners();
+28 −5
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public final class Choreographer {
    private boolean mFrameScheduled;
    private boolean mCallbacksRunning;
    private long mLastFrameTimeNanos;
    private long mFrameIntervalNanos;

    /**
     * Callback type: Input callback.  Runs first.
@@ -116,6 +117,8 @@ public final class Choreographer {
        mHandler = new FrameHandler(looper);
        mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
        mLastFrameTimeNanos = Long.MIN_VALUE;
        mFrameIntervalNanos = (long)(1000000000 /
                new Display(Display.DEFAULT_DISPLAY, null).getRefreshRate());

        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
        for (int i = 0; i <= CALLBACK_LAST; i++) {
@@ -343,17 +346,37 @@ public final class Choreographer {
    }

    void doFrame(long timestampNanos, int frame) {
        final long startNanos;
        synchronized (mLock) {
            if (!mFrameScheduled) {
                return; // no work to do
            }
            mFrameScheduled = false;
            mLastFrameTimeNanos = timestampNanos;

            startNanos = System.nanoTime();
            final long jitterNanos = startNanos - timestampNanos;
            if (jitterNanos >= mFrameIntervalNanos) {
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                if (DEBUG) {
                    Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                            + "which is more than the frame interval of "
                            + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                            + "Setting frame time to " + (lastFrameOffset * 0.000001f)
                            + " ms in the past.");
                }
                timestampNanos = startNanos - lastFrameOffset;
            }

        final long startNanos;
            if (timestampNanos < mLastFrameTimeNanos) {
                if (DEBUG) {
            startNanos = System.nanoTime();
                    Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
                            + "previously skipped frame.  Waiting for next vsync");
                }
                scheduleVsyncLocked();
                return;
            }

            mFrameScheduled = false;
            mLastFrameTimeNanos = timestampNanos;
        }

        doCallbacks(Choreographer.CALLBACK_INPUT);