Choreographer ——编舞者

Choreographer(编舞者)

官方解释

/**
 * Coordinates the timing of animations, input and drawing.
 * <p>
 * The choreographer receives timing pulses (such as vertical synchronization)
 * from the display subsystem then schedules work to occur as part of rendering
 * the next display frame.
 * </p><p>
 * Applications typically interact with the choreographer indirectly using
 * higher level abstractions in the animation framework or the view hierarchy.
 * Here are some examples of things you can do using the higher-level APIs.
 * </p>
 * <ul>
 * <li>To post an animation to be processed on a regular time basis synchronized with
 * display frame rendering, use {@link android.animation.ValueAnimator#start}.</li>
 * <li>To post a {@link Runnable} to be invoked once at the beginning of the next display
 * frame, use {@link View#postOnAnimation}.</li>
 * <li>To post a {@link Runnable} to be invoked once at the beginning of the next display
 * frame after a delay, use {@link View#postOnAnimationDelayed}.</li>
 * <li>To post a call to {@link View#invalidate()} to occur once at the beginning of the
 * next display frame, use {@link View#postInvalidateOnAnimation()} or
 * {@link View#postInvalidateOnAnimation(int, int, int, int)}.</li>
 * <li>To ensure that the contents of a {@link View} scroll smoothly and are drawn in
 * sync with display frame rendering, do nothing.  This already happens automatically.
 * {@link View#onDraw} will be called at the appropriate time.</li>
 * </ul>
 * <p>
 * However, there are a few cases where you might want to use the functions of the
 * choreographer directly in your application.  Here are some examples.
 * </p>
 * <ul>
 * <li>If your application does its rendering in a different thread, possibly using GL,
 * or does not use the animation framework or view hierarchy at all
 * and you want to ensure that it is appropriately synchronized with the display, then use
 * {@link Choreographer#postFrameCallback}.</li>
 * <li>... and that's about it.</li>
 * </ul>
 * <p>
 * Each {@link Looper} thread has its own choreographer.  Other threads can
 * post callbacks to run on the choreographer but they will run on the {@link Looper}
 * to which the choreographer belongs.
 * </p>
 */
  • . 协调动画、输入和绘图的时间

  • . 当 choreographer 从子显示系统 接受到定时脉冲(例如垂直脉冲),然后会将 工作 作为下一个显示帧 的一部分,显示。

  • . 应用程序,通常和 choreographer 交互,是直接使用 动画框架 或者 视图层次的 高级抽象。

    • 将要处理的动画按固定时间同步发布 显示帧渲染 ——android.animation.ValueAnimator#start
    • 发布一个{@link Runnable},在下一帧显示开始前用——View#postOnAnimation
    • 发布一个调用 {@link View#invalidate()},在下一帧显示开始前调用——View#postInvalidateOnAnimation()、View#postInvalidateOnAnimation(int, int, int, int)
    • 确保{@link View}的内容平滑地滚动并被绘制进来,同步显示在帧渲染中,不做任何事。这已经自动发生了。
      {@link View#onDraw}将在适当的时间被调用。
  • 有些情况需要我们直接使用 choreographer

    • 如果 应用 在不同的线程渲染,例如GL
    • 或者完全不适用动画框架,或者视图层次
      如果 想确保和 显示同步,可以,通过 Choreographer#postFrameCallback 达到目的。
  • 每一个线程都有自己的choreographer,其它线程可以发送 回调,运行在choreographer,但是他们将会运行在 choreographer 所属的 Looper中。

概况

public final class Choreographer {

 private static final ThreadLocal<Choreographer> sThreadInstance =
            new ThreadLocal<Choreographer>() {
        @Override
        protected Choreographer initialValue() {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalStateException("The current thread must have a looper!");
            }
            Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
            if (looper == Looper.getMainLooper()) {
                mMainInstance = choreographer;
            }
            return choreographer;
        }
    };

    // 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);
            //从系统中获取是否使用帧时间
// Enable/disable using the frame time instead of returning now.
    private static final boolean USE_FRAME_TIME = SystemProperties.getBoolean(
            "debug.choreographer.frametime", true);
            //从系统中,获取跳帧的阀值
   // Set a limit to warn about skipped frames.
    // Skipped frames imply jank.
    private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
            "debug.choreographer.skipwarning", 30);   

   /*******************handler 想关*************/
    private final FrameHandler mHandler;
    //mHandler 中Message的类型
    //刷新当前这一帧
    private static final int MSG_DO_FRAME = 0;
    //做VSYNC的信号同步
    private static final int MSG_DO_SCHEDULE_VSYNC = 1;
    // //将当前任务加入执行队列
    private static final int MSG_DO_SCHEDULE_CALLBACK = 2;    
    /*******************handler 想关*************/
    //接受native 层,垂直同步的回调方法
    private final FrameDisplayEventReceiver mDisplayEventReceiver;
    //缓存中没在使用的 CallbackRecord 
    private CallbackRecord mCallbackPool;
    //存储不同类型的 CallbackQueue(存储 CallbackRecord )
    private final CallbackQueue[] mCallbackQueues;
    //frame是否开始绘制 
    private boolean mFrameScheduled;
    //mCallbacks 是否在运行
    private boolean mCallbacksRunning;
    //上一次刷新时间
    private long mLastFrameTimeNanos;
    //屏幕刷新时间
    private long mFrameIntervalNanos;
    private boolean mDebugPrintNextFrameTimeDelta;
    private int mFPSDivisor = 1;

   /**
     * Must be kept in sync with CALLBACK_* ints below, used to index into this array.
     * @hide
     */
    private static final String[] CALLBACK_TRACE_TITLES = {
            "input", "animation", "traversal", "commit"
    };

    /**
     * Callback type: Input callback.  Runs first.
     * @hide
     */
     //输入回调,首先执行
    public static final int CALLBACK_INPUT = 0;

    /**
     * Callback type: Animation callback.  Runs before traversals.
     * @hide
     */
    @TestApi
    //动画回调,在CALLBACK_TRAVERSAL  回调之前执行
    public static final int CALLBACK_ANIMATION = 1;

    /**
     * Callback type: Traversal callback.  Handles layout and draw.  Runs
     * after all other asynchronous messages have been handled.
     * @hide
     */
     //处理,layout 和 draw ,开始于,在所有异步消息处理完之后。
    public static final int CALLBACK_TRAVERSAL = 2;

    /**
     * Callback type: Commit callback.  Handles post-draw operations for the frame.
     * Runs after traversal completes.  The {@link #getFrameTime() frame time} reported
     * during this callback may be updated to reflect delays that occurred while
     * traversals were in progress in case heavy layout operations caused some frames
     * to be skipped.  The frame time reported during this callback provides a better
     * estimate of the start time of the frame in which animations (and other updates
     * to the view hierarchy state) actually took effect.
     * @hide
     */
    public static final int CALLBACK_COMMIT = 3;

    private static final int CALLBACK_LAST = CALLBACK_COMMIT;
}

choreographer 类似于Looper ,是以ThreadLocal 副本的形式,存储在Thread 中。

CallbackRecord
public final class Choreographer {

   // All frame callbacks posted by applications have this token.
    //应用程序发布的所有 帧回调 ,都使用  FRAME_CALLBACK_TOKEN  作为token
    private static final Object FRAME_CALLBACK_TOKEN = new Object() {
        public String toString() { return "FRAME_CALLBACK_TOKEN"; }
    };
       ...
 private static final class CallbackRecord {
 //单链表结构,每个节点  持有下个CallbackRecord 的引用(next)
        public CallbackRecord next;
        //发生的时间
        public long dueTime;
        //执行动作,有runnable 或者 帧的回调
        public Object action; // Runnable or FrameCallback
        //根据token ,区分 action 
        public Object token;
        //回调记录的执行
        public void run(long frameTimeNanos) {
            if (token == FRAME_CALLBACK_TOKEN) {
                ((FrameCallback)action).doFrame(frameTimeNanos);
            } else {
                ((Runnable)action).run();
            }
        }
    }
   ....

 /**
     * Implement this interface to receive a callback when a new display frame is
     * being rendered.  The callback is invoked on the {@link Looper} thread to
     * which the {@link Choreographer} is attached.
     */
     //帧呈现的回调
    public interface FrameCallback {
        /**
         * Called when a new display frame is being rendered.
         * <p>
         * This method provides the time in nanoseconds when the frame started being rendered.
         * The frame time provides a stable time base for synchronizing animations
         * and drawing.  It should be used instead of {@link SystemClock#uptimeMillis()}
         * or {@link System#nanoTime()} for animations and drawing in the UI.  Using the frame
         * time helps to reduce inter-frame jitter because the frame time is fixed at the time
         * the frame was scheduled to start, regardless of when the animations or drawing
         * callback actually runs.  All callbacks that run as part of rendering a frame will
         * observe the same frame time so using the frame time also helps to synchronize effects
         * that are performed by different callbacks.
         * </p><p>
         * Please note that the framework already takes care to process animations and
         * drawing using the frame time as a stable time base.  Most applications should
         * not need to use the frame time information directly.
         * </p>
         *
         * @param frameTimeNanos The time in nanoseconds when the frame started being rendered,
         * in the {@link System#nanoTime()} timebase.  Divide this value by {@code 1000000}
         * to convert it to the {@link SystemClock#uptimeMillis()} time base.
         */
         //帧开始显示的时间(纳秒)
        public void doFrame(long frameTimeNanos);
    }

}
CallbackQueue
public final class Choreographer {
     //废弃的CallbackRecord  的链表
     private CallbackRecord mCallbackPool;
     //根据 执行时间+ action + token 组装成 CallbackRecord 
     private CallbackRecord obtainCallbackLocked(long dueTime, Object action, Object token) {
        //先用缓存的mCallbackPool 表头节点 
        CallbackRecord callback = mCallbackPool;
        //如果缓存的callback  为空则新建一个CallbackRecord
        if (callback == null) {
            callback = new CallbackRecord();
        } else {
        //如果callback  不为空,则mCallbackPool 指向 缓存列表头节点的下一个节点
            mCallbackPool = callback.next;
            callback.next = null;
        }
        callback.dueTime = dueTime;
        callback.action = action;
        callback.token = token;
        return callback;
    }

 //回收掉从列表移除的CallbackRecord  ,加入到 mCallbackPool 链表的头部
 private void recycleCallbackLocked(CallbackRecord callback) {
        callback.action = null;
        callback.token = null;
        callback.next = mCallbackPool;
        mCallbackPool = callback;
    }

        ...
  //CallbackRecord 节点类型的链表,是以执行时间由 早到晚排列      
 private final class CallbackQueue {
     //CallbackQueue 列表的头节点
        private CallbackRecord mHead;

     //链表中添加 action(FrameCallback/Runnable)
     public void addCallbackLocked(long dueTime, Object action, Object token) {
         // 生成一个 CallbackRecord 
            CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
            CallbackRecord entry = mHead;
            //CallbackQueue 头节点为空,则callback  赋值为头节点
            if (entry == null) {
                mHead = callback;
                return;
            }
            //如果callback 的执行时间,小于 链表的头节点的执行时间,则callback 加入到表头
            if (dueTime < entry.dueTime) {
                callback.next = entry;
                mHead = callback;
                return;
            }
            //遍历链表,根据时间,将callback 插入到列表中
            while (entry.next != null) {
                if (dueTime < entry.next.dueTime) {
                    callback.next = entry.next;
                    break;
                }
                entry = entry.next;
            }
            entry.next = callback;
        }
        //移除 action(FrameCallback/Runnable)
        public void removeCallbacksLocked(Object action, Object token) {
            CallbackRecord predecessor = null;
            for (CallbackRecord callback = mHead; callback != null;) {
                final CallbackRecord next = callback.next;
                if ((action == null || callback.action == action)
                        && (token == null || callback.token == token)) {
                    if (predecessor != null) {
                        predecessor.next = next;
                    } else {
                        mHead = next;
                    }
                    recycleCallbackLocked(callback);
                } else {
                    predecessor = callback;
                }
                callback = next;
            }
        }
    }




        //判断  CallbackQueue 中是否有可执行的  节点
        public boolean hasDueCallbacksLocked(long now) {
        // 头节点时间都比now 时间早的话,那么链表中没有可执行的节点
            return mHead != null && mHead.dueTime <= now;
        }
        //根据now 时间,从链表中提取可以执行的  CallbackRecord 
        public CallbackRecord extractDueCallbacksLocked(long now) {
            CallbackRecord callbacks = mHead;
            if (callbacks == null || callbacks.dueTime > now) {
                return null;
            }

            CallbackRecord last = callbacks;
            CallbackRecord next = last.next;
            while (next != null) {
                if (next.dueTime > now) {
                    last.next = null;
                    break;
                }
                last = next;
                next = next.next;
            }
            mHead = next;
            return callbacks;
        }

      
            ...
}
Choreographer 对象的获取
//Choreographer.java
//单例构造方法:从当前线程中 ,获取 实例
 public static Choreographer getInstance() {
        return sThreadInstance.get();
    }

 private Choreographer(Looper looper, int vsyncSource) {
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        //当系统使用 垂直信号的时候,创建VSYNC的信号接受对象
        mDisplayEventReceiver = USE_VSYNC
                ? new FrameDisplayEventReceiver(looper, vsyncSource)
                : null;
        //初始化上一次frame渲染的时间点
        mLastFrameTimeNanos = Long.MIN_VALUE;
         //计算帧率,也就是一帧所需的渲染时间,getRefreshRate是刷新率,一般是60
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
        //根据回调类型(CALLBACK_INPUT ,CALLBACK_ANIMATION ,CALLBACK_TRAVERSAL ),实例化 mCallbackQueues 
        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
        for (int i = 0; i <= CALLBACK_LAST; i++) {
            mCallbackQueues[i] = new CallbackQueue();
        }
        // b/68769804: For low FPS experiments.
        setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
    }


FrameDisplayEventReceiver (继承自DisplayEventReceiver )
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();
    //初始化后,获得一个句柄
    private long mReceiverPtr;

    // We keep a reference message queue object here so that it is not
    // GC'd while the native peer of the receiver is using them.
    private MessageQueue mMessageQueue;
    
    private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
            MessageQueue messageQueue, int vsyncSource);
    private static native void nativeDispose(long receiverPtr);
    @FastNative
    private static native void nativeScheduleVsync(long receiverPtr);

    /**
     * Creates a display event receiver.
     *
     * @param looper The looper to use when invoking callbacks.
     */
    public DisplayEventReceiver(Looper looper) {
        this(looper, VSYNC_SOURCE_APP);
    }

    /**
     * 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, int vsyncSource) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mMessageQueue = looper.getQueue();
        //获取当前线程的 mMessageQueue  ,调用本地nativeInit 方法
        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
                vsyncSource);

        mCloseGuard.open("dispose");
    }
    //当 对象被回收的时候,执行该方法
    @Override
    protected void finalize() throws Throwable {
        try {
            dispose(true);
        } finally {
            super.finalize();
        }
    }

    /**
     * Disposes the receiver.
     */
    public void dispose() {
        dispose(false);
    }

    private void dispose(boolean finalized) {
        if (mCloseGuard != null) {
            if (finalized) {
                mCloseGuard.warnIfOpen();
            }
            mCloseGuard.close();
        }

        if (mReceiverPtr != 0) {
            nativeDispose(mReceiverPtr);
            mReceiverPtr = 0;
        }
        mMessageQueue = null;
    }

    /**
     * Called when a vertical sync pulse is received.
     * The recipient should render a frame and then call {@link #scheduleVsync}
     * to schedule the next vertical sync pulse.
     *
     * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
     * timebase.
     * @param builtInDisplayId The surface flinger built-in display id such as
     * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
     * @param frame The frame number.  Increases by one for each vertical sync interval.
     */
     //当收到垂直同步脉冲时候,调用
     //timestampNanos:  脉冲的时间戳
     //builtInDisplayId: 显示的displayId 
    //frame:帧号。为每个垂直同步间隔增加1
    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
    }

    /**
     * Called when a display hotplug event is received.
     *
     * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
     * timebase.
     * @param builtInDisplayId The surface flinger built-in display id such as
     * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
     * @param connected True if the display is connected, false if it disconnected.
     */
     //当接收到显示热插拔事件时调用
    public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
    }

    /**
     * Schedules a single vertical sync pulse to be delivered when the next
     * display frame begins.
     */
     //在下一帧开始前,发一个垂直同步信号
    public void scheduleVsync() {
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
                    + "receiver has already been disposed.");
        } else {
            nativeScheduleVsync(mReceiverPtr);
        }
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
        onVsync(timestampNanos, builtInDisplayId, frame);
    }

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
        onHotplug(timestampNanos, builtInDisplayId, connected);
    }



//负责,接收系统发出来的垂直同步信号,和 向系统发出信号
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
            //是否有将要执行的 垂直同步信号
        private boolean mHavePendingVsync;
        private long mTimestampNanos;
        //显示帧数
        private int mFrame;

        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource);
        }
       //接受到垂直同步信号
        @Override
        public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
            // Ignore vsync from secondary display.
            // This can be problematic because the call to scheduleVsync() is a one-shot.
            // We need to ensure that we will still receive the vsync from the primary
            // display which is the one we really care about.  Ideally we should schedule
            // vsync for a particular display.
            // At this time Surface Flinger won't send us vsyncs for secondary displays
            // but that could change in the future so let's log a message to help us remember
            // that we need to fix this.
            //当接收到的同步信号时,如果builtInDisplayId 不是 BUILT_IN_DISPLAY_ID_MAIN 重新调用 scheduleVsync 获取一个垂直同步信号
            if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                Log.d(TAG, "Received vsync from secondary display, but we don't support "
                        + "this case yet.  Choreographer needs a way to explicitly request "
                        + "vsync for a specific display to ensure it doesn't lose track "
                        + "of its scheduled vsync.");
                scheduleVsync();
                return;
            }

            // Post the vsync event to the Handler.
            // The idea is to prevent incoming vsync events from completely starving
            // the message queue.  If there are no messages in the queue with timestamps
            // earlier than the frame time, then the vsync event will be processed immediately.
            // Otherwise, messages that predate the vsync event will be handled first.
            long now = System.nanoTime();
            //如果接收到的信号发生时间大于大于当前时间,则置为当前时间
            if (timestampNanos > now) {
                Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
                        + " ms in the future!  Check that graphics HAL is generating vsync "
                        + "timestamps using the correct timebase.");
                timestampNanos = now;
            }
                
            if (mHavePendingVsync) {
                Log.w(TAG, "Already have a pending vsync event.  There should only be "
                        + "one at a time.");
            } else {
                mHavePendingVsync = true;
            }

            mTimestampNanos = timestampNanos;
            mFrame = frame;
  
            Message msg = Message.obtain(mHandler, this);
            msg.setAsynchronous(true);
            //发送message,通过handler  执行到 下面的run 方法
            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }

        @Override
        public void run() {
            //将是否有将要处理信号标志,置为false
            mHavePendingVsync = false;
            //执行都Frame 方法
            doFrame(mTimestampNanos, mFrame);
        }
    }
  • scheduleVsync : 向系发出 垂直同步信号,CPU ,GPU 接收到信号,开始处理帧数据
  • onVsync(long timestampNanos, int builtInDisplayId, int frame) :接收到系统 返回来的垂直同步信号。当CPU ,GPU 处理完帧数据的时候,回调到该方法,告诉Display 开始处理已经ok的对应帧数据。
doFrame :处理帧数据
public final class Choreographer {

//两帧的时间间隔
private long mFrameIntervalNanos;

 private Choreographer(Looper looper, int vsyncSource) {
   
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
    }

 //获取系统的刷新频率(FPS)
 private static float getRefreshRate() {
        DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo(
                Display.DEFAULT_DISPLAY);
        return di.getMode().getRefreshRate();
    }
   ...

void doFrame(long frameTimeNanos, int frame) {
        final long startNanos;
        synchronized (mLock) {
           //是否有需要处理的 帧
            if (!mFrameScheduled) {
                return; // no work to do
            }

            if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) {
                mDebugPrintNextFrameTimeDelta = false;
                Log.d(TAG, "Frame time delta: "
                        + ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms");
            }
            //将要处理的帧时间
            long intendedFrameTimeNanos = frameTimeNanos;
            //系统当前时间
            startNanos = System.nanoTime();
            //获取时间差
            final long jitterNanos = startNanos - frameTimeNanos;
            //如果时间差大于 系统的帧时间间隔
            if (jitterNanos >= mFrameIntervalNanos) {
               //计算相差的帧数
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
                //SKIPPED_FRAME_WARNING_LIMIT系统默认 丢帧警告数
                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                            + "The application may be doing too much work on its main thread.");
                }
                //最后一帧的时间间隔
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                if (DEBUG_JANK) {
                    Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                            + "which is more than the frame interval of "
                            + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                            + "Skipping " + skippedFrames + " frames and setting frame "
                            + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
                }
                //重置将要执行帧的时间
                frameTimeNanos = startNanos - lastFrameOffset;
            }
               //如果帧时间小于上一帧执行时间
            if (frameTimeNanos < mLastFrameTimeNanos) {
                if (DEBUG_JANK) {
                    Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
                            + "previously skipped frame.  Waiting for next vsync.");
                }
                //发送垂直同步信号(mDisplayEventReceiver.scheduleVsync())
                scheduleVsyncLocked();
                return;
            }
            //mFPSDivisor :设置FPS devisor来降低FPS,一般默认是1
            if (mFPSDivisor > 1) {
                long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
                if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
                    scheduleVsyncLocked();
                    return;
                }
            }

            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
            //置为false
            mFrameScheduled = false;
            //重置上一帧时间
            mLastFrameTimeNanos = frameTimeNanos;
        }

        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
            //去设置动画
            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);

            mFrameInfo.markInputHandlingStart();
            // Input callback 类型callback
            doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);

            mFrameInfo.markAnimationsStart();
            //Animation callback 类型callback 
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);

            mFrameInfo.markPerformTraversalsStart();
            // Traversal callback 类型callback
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
             //CALLBACK_COMMIT 类型 callback
            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
        } finally {
            AnimationUtils.unlockAnimationClock();
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }

        if (DEBUG_FRAMES) {
            final long endNanos = System.nanoTime();
            Log.d(TAG, "Frame " + frame + ": Finished, took "
                    + (endNanos - startNanos) * 0.000001f + " ms, latency "
                    + (startNanos - frameTimeNanos) * 0.000001f + " ms.");
        }
    }
    ...
}
doCallbacks
public final class Choreographer {
  //是否有callbackRecord 在执行
 private boolean mCallbacksRunning;
 
 void doCallbacks(int callbackType, long frameTimeNanos) {
        CallbackRecord callbacks;
        synchronized (mLock) {
            // We use "now" to determine when callbacks become due because it's possible
            // for earlier processing phases in a frame to post callbacks that should run
            // in a following phase, such as an input event that causes an animation to start.
            final long now = System.nanoTime();
            //callbackType 的链表中,根据now 选择执行  符合条件的callbacks 
            // 详见上面 所讲  CallbackQueue
            callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
                    now / TimeUtils.NANOS_PER_MS);
            if (callbacks == null) {
                return;
            }
            mCallbacksRunning = true;

            // Update the frame time if necessary when committing the frame.
            // We only update the frame time if we are more than 2 frames late reaching
            // the commit phase.  This ensures that the frame time which is observed by the
            // callbacks will always increase from one frame to the next and never repeat.
            // We never want the next frame's starting frame time to end up being less than
            // or equal to the previous frame's commit frame time.  Keep in mind that the
            // next frame has most likely already been scheduled by now so we play it
            // safe by ensuring the commit time is always at least one frame behind.
            if (callbackType == Choreographer.CALLBACK_COMMIT) {
                final long jitterNanos = now - frameTimeNanos;
                Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
                if (jitterNanos >= 2 * mFrameIntervalNanos) {
                    final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
                            + mFrameIntervalNanos;
                    if (DEBUG_JANK) {
                        Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
                                + " ms which is more than twice the frame interval of "
                                + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                                + "Setting frame time to " + (lastFrameOffset * 0.000001f)
                                + " ms in the past.");
                        mDebugPrintNextFrameTimeDelta = true;
                    }
                    frameTimeNanos = now - lastFrameOffset;
                    mLastFrameTimeNanos = frameTimeNanos;
                }
            }
        }
        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
            //callbacks 到 链表表尾 直接所有节点,执行run 方法
            for (CallbackRecord c = callbacks; c != null; c = c.next) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "RunCallback: type=" + callbackType
                            + ", action=" + c.action + ", token=" + c.token
                            + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
                }
                c.run(frameTimeNanos);
            }
        } finally {
            synchronized (mLock) {
                mCallbacksRunning = false;
                //移除执行完的callbackRecord
                do {
                    final CallbackRecord next = callbacks.next;
                    recycleCallbackLocked(callbacks);
                    callbacks = next;
                } while (callbacks != null);
            }
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }
}
FrameHandler
public final class Choreographer {

private final FrameHandler mHandler;

private final FrameDisplayEventReceiver mDisplayEventReceiver;



void doScheduleVsync() {
        synchronized (mLock) {
           //如果有frame 在处理
            if (mFrameScheduled) {
                scheduleVsyncLocked();
            }
        }
    }
 private void scheduleVsyncLocked() {
        mDisplayEventReceiver.scheduleVsync();
    }

  private final class FrameHandler extends Handler {
        public FrameHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DO_FRAME:
                  //执行某帧,查看上面  doFrame
                    doFrame(System.nanoTime(), 0);
                    break;
                case MSG_DO_SCHEDULE_VSYNC:
                  //发送垂直同步信号 
                    doScheduleVsync();
                    break;
                case MSG_DO_SCHEDULE_CALLBACK:
                  //执行某类类型的 callback列表
                    doScheduleCallback(msg.arg1);
                    break;
            }
        }
    }

 void doScheduleCallback(int callbackType) {
        synchronized (mLock) {
        //如果没有帧在处理
            if (!mFrameScheduled) {
                final long now = SystemClock.uptimeMillis();
                //请参阅读上面所讲 CallbackQueues
                if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
                    scheduleFrameLocked(now);
                }
            }
        }
    }

    private void scheduleFrameLocked(long now) {
    // 如果没有帧在执行
        if (!mFrameScheduled) {
            mFrameScheduled = true;
            //如果使用垂直信号
            if (USE_VSYNC) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "Scheduling next frame on vsync.");
                }

                // If running on the Looper thread, then schedule the vsync immediately,
                // otherwise post a message to schedule the vsync from the UI thread
                // as soon as possible.
                //如果在主线程
                if (isRunningOnLooperThreadLocked()) {
                //发送垂直同步信号
                    scheduleVsyncLocked();
                } else {
                    //发送异步消息 插入,消息链表表头
                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtFrontOfQueue(msg);
                }
            } else {
            //如果没有使用垂直同步,
                 //计下一帧时间
                final long nextFrameTime = Math.max(
                        mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
                }
                //发送MSG_DO_FRAME 类型异步消息
                Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }
    }
}

如果想绘制某一帧,必须先发送垂直同步信号,在FrameDisplayEventReceiver 的 onVsync 方法中,接收到回调后,才开始 doFrame()->doCallBack()

CallbackQueue 数组中,添加,移除 对应的 CallbackRecord
public final class Choreographer {
/***************************添加 runnable****************************/
 @TestApi
 //添加runnable
    public void postCallback(int callbackType, Runnable action, Object token) {
        postCallbackDelayed(callbackType, action, token, 0);
    }
@TestApi
    public void postCallbackDelayed(int callbackType,
            Runnable action, Object token, long delayMillis) {
        if (action == null) {
            throw new IllegalArgumentException("action must not be null");
        }
        if (callbackType < 0 || callbackType > CALLBACK_LAST) {
            throw new IllegalArgumentException("callbackType is invalid");
        }

        postCallbackDelayedInternal(callbackType, action, token, delayMillis);
    }
/***************************添加 runnable****************************/

/***************************添加 FrameCallback ****************************/

//添加 FrameCallBack
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }

        postCallbackDelayedInternal(CALLBACK_ANIMATION,
                callback, FRAME_CALLBACK_TOKEN, delayMillis);
    }
    
/***************************添加 FrameCallback ****************************/


 private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
        if (DEBUG_FRAMES) {
            Log.d(TAG, "PostCallback: type=" + callbackType
                    + ", action=" + action + ", token=" + token
                    + ", delayMillis=" + delayMillis);
        }

        synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            //计算执行时间
            final long dueTime = now + delayMillis;
            //加入对应类型的链表中
            mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
             //如果执行时间小于等于当前时间
            if (dueTime <= now) {
            //立即执行 scheduleFrameLocked,该方法上午已讲
                scheduleFrameLocked(now);
            } else {
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
                msg.arg1 = callbackType;
                msg.setAsynchronous(true);
                 //通过handler 定时执行 scheduleFrameLocked,该方法上午已讲
                mHandler.sendMessageAtTime(msg, dueTime);
            }
        }
    }
//移除FrameCallback 
 public void removeFrameCallback(FrameCallback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }

        removeCallbacksInternal(CALLBACK_ANIMATION, callback, FRAME_CALLBACK_TOKEN);
    }
//移除Runnable
  @TestApi
    public void removeCallbacks(int callbackType, Runnable action, Object token) {
        if (callbackType < 0 || callbackType > CALLBACK_LAST) {
            throw new IllegalArgumentException("callbackType is invalid");
        }

        removeCallbacksInternal(callbackType, action, token);
    }

   private void removeCallbacksInternal(int callbackType, Object action, Object token) {
        if (DEBUG_FRAMES) {
            Log.d(TAG, "RemoveCallbacks: type=" + callbackType
                    + ", action=" + action + ", token=" + token);
        }

        synchronized (mLock) {
            mCallbackQueues[callbackType].removeCallbacksLocked(action, token);
            if (action != null && token == null) {
            //MessageQueue中 移除 callbackType 和 action 对应的 message 
                mHandler.removeMessages(MSG_DO_SCHEDULE_CALLBACK, action);
            }
        }
    }

}

编舞者的大体流程,已经过了一边。大体流程:
在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值