Android 平台提供两种信号,一种是硬件信号,另一种是软件信号,由 SurfaceFlinger 进程的一个线程定时发出,硬件信号由硬件发出;
App 进程若要通过 gpu 实现图像绘制,需要在接收到 Vsync 信号的条件下进行。因此,App 进程访问 SurfaceFlinger 进程获取这个信号,再进行 gpu 绘制;
Android4.1 之后增加了 Choreographer 机制,用于同 Vsync 机制配合,统一动画、输入和绘制时机;
Choreographer 就是负责获取 Vsync 同步信号并控制 App 主线程完成图像绘制的类;
Choreographer 源码分析 构造方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public final class Choreographer { public static final int CALLBACK_COMMIT = 4 ; private static final int CALLBACK_LAST = CALLBACK_COMMIT; private Choreographer (Looper looper, int vsyncSource) { mLooper = looper; mHandler = new FrameHandler (looper); mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver (looper, vsyncSource) : null ; mLastFrameTimeNanos = Long.MIN_VALUE; mFrameIntervalNanos = (long )(1000000000 / getRefreshRate()); mCallbackQueues = new CallbackQueue [CALLBACK_LAST + 1 ]; for (int i = 0 ; i <= CALLBACK_LAST; i++) { mCallbackQueues[i] = new CallbackQueue (); } setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1 )); } }
根据当前线程的 looper 创建 Handler 对象;
变量 USE_VSYNC 用于表示系统是否使用了 Vsync 同步机制,该值是通过读取系统属性 debug.choreographer.vsync 来获取的。4.1 以上默认是 true;
创建一个 FrameDisplayEventReceiver 对象用于接收 Vsync 事件;
使用 CallbackQueue(单链表结构)保存相同类型的任务,所有类型的任务保存在 CallbackQueue 数组中;
Choreographer 对象的获取 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; } }; public static Choreographer getInstance () { return sThreadInstance.get(); } }
Choreographer 对象通过 ThreadLocal 保存在每个线程中;
Choreographer 对象初始化时需要提供 Looper 对象,构造 Handler 发送消息;
Callback 类型 1 2 3 4 5 6 7 8 9 10 11 public static final int CALLBACK_INPUT = 0 ;public static final int CALLBACK_ANIMATION = 1 ;public static final int CALLBACK_INSETS_ANIMATION = 2 ;public static final int CALLBACK_TRAVERSAL = 3 ;public static final int CALLBACK_COMMIT = 4 ;
五种类型任务对应存入对应的 CallbackQueue 中;
每当收到 VSYNC 信号时,Choreographer 将首先处理 INPUT 类型的任务,然后是 ANIMATION 类型,最后才是 TRAVERSAL 类型;
FrameHandler 处理的消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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(System.nanoTime(), 0 ); break ; case MSG_DO_SCHEDULE_VSYNC: doScheduleVsync(); break ; case MSG_DO_SCHEDULE_CALLBACK: doScheduleCallback(msg.arg1); break ; } } }
FrameHandler 处理了如下三种消息:
MSG_DO_FRAME :处理注册在 Choreographer 的 Runnable;
MSG_DO_SCHEDULE_VSYNC :直接请求下一帧的 VSync 信号;
MSG_DO_SCHEDULE_CALLBACK :处理延时消息;
Choreographer 处理任务流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public abstract class DisplayEventReceiver { public void scheduleVsync () { nativeScheduleVsync(mReceiverPtr); } private void dispatchVsync (long timestampNanos, long physicalDisplayId, int frame) { onVsync(timestampNanos, physicalDisplayId, frame); } public void onVsync (long timestampNanos, long physicalDisplayId, int frame) { } }
DisplayEventReceiver 用来接收从底层发来的 Vsync 信号,并回调 onVsync 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable { @Override public void onVsync (long timestampNanos, long physicalDisplayId, int frame) { Message msg = Message.obtain(mHandler, this ); msg.setAsynchronous(true ); mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); } @Override public void run () { doFrame(mTimestampNanos, mFrame); } void doFrame (long frameTimeNanos, int frame) { if (!mFrameScheduled) { return ; } if (frameTimeNanos < mLastFrameTimeNanos) { scheduleVsyncLocked(); return ; } mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos); mFrameScheduled = false ; doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); } void doCallbacks (int callbackType, long frameTimeNanos) { CallbackRecord callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked( now / TimeUtils.NANOS_PER_MS); try { for (CallbackRecord c = callbacks; c != null ; c = c.next) { c.run(frameTimeNanos); } } finally { } } }
FrameDisplayEventReceiver 继承 DisplayEventReceiver 并实现了 Runnable,表明它接收到 Vsync 信号后会执行任务;
scheduleVsync() 方法通过 native 方法 nativeScheduleVsync() 向 SurfaceFlinger 服务注册,即在下一次脉冲接收后会调用 DisplayEventReceiver 的 dispatchVsync() 方法;
底层向应用层发送 VSYNC 信号,java 层通过 dispatchVsync() 接收,最后回调在 FrameDisplayEventReceiver#onVsync();
处理 View 绘制任务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public ViewRootImpl (Context context, Display display, IWindowSession session, boolean useSfChoreographer) { mChoreographer = useSfChoreographer ? Choreographer.getSfInstance() : Choreographer.getInstance(); } final TraversalRunnable mTraversalRunnable = new TraversalRunnable ();final class TraversalRunnable implements Runnable { @Override public void run () { doTraversal(); } } void doTraversal () { if (mTraversalScheduled) { mTraversalScheduled = false ; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); performTraversals(); } } void scheduleTraversals () { if (!mTraversalScheduled) { mTraversalScheduled = true ; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null ); } } void unscheduleTraversals () { if (mTraversalScheduled) { mTraversalScheduled = false ; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); mChoreographer.removeCallbacks( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null ); } } public void requestLayout () { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true ; scheduleTraversals(); } }
VSync 机制 Android 系统每隔 16ms 发出 VSYNC 信号,触发对 UI 进行渲染,VSync 是 Vertical Synchronization(垂直同步)的缩写。
16ms 内只会申请一次垂直同步信号;
VSync 信号由 SurfaceFlinger 实现并定时发送。
总结
Choreographer 的职责是统一处理输入、绘制、动画和提交任务;
主线程通过 Choreographer 把不同类型的 Callback 添加到单链表中。时间到后,根据 Callback 优先级遍历各个单链表执行任务;
参考 [1] 屏幕刷新机制 Choreographer 原理分析 [2] Android 屏幕刷新机制解析 [3] Android 屏幕刷新机制与 Choreographer 全面解读