booleanenqueueMessage(Message msg, long when) { ... synchronized (this) { ... msg.markInUse(); msg.when = when; Messagep= mMessages; boolean needWake; // 当前消息队列为空 or when等于0 or 新消息的when小于头消息的when if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. needWake = mBlocked && p.target == null && msg.isAsynchronous(); Message prev; for (;;) { prev = p; p = p.next; // 否则按照when的值将消息插入到队列的合适位置中 if (p == null || when < p.when) { break; } if (needWake && p.isAsynchronous()) { needWake = false; } } msg.next = p; // invariant: p == prev.next prev.next = msg; } ... } returntrue; }
if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. mBlocked = true; continue; }
a. 本次轮询中如果msg为空,或者msg还没到触发时间,则判定为空闲状态 b. 接着遍历mPendingIdleHandlers数组取出IdleHandler实例并调用queueIdle方法 c. 如果queueIdle返回false表示执行完后不需要保留,则在mIdleHandlers中直接彻底移除
a. 基于Unix系统的IPC的管道,FIFO,信号 b. 基于SystemV和Posix系统的IPC的消息队列,信号量,共享内存 c. 基于Socket的IPC d. Linux的内存映射函数mmap() e. Linux 2.6.22版本后才有的eventfd f. Android系统独有的Binder和匿名共享内存Ashmen
这里要讨论的是消息通信机制中的IPC变迁,其实也就是Looper唤醒方式的变迁,大体上是从【a. 基于Unix系统的IPC的管道,FIFO,信号】到【e. Linux 2.6.22版本后才有的eventfd】的升级。
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", errno);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", errno);
mIdling = false;
// Allocate the epoll instance and register the wake pipe. mEpollFd = epoll_create(EPOLL_SIZE_HINT); LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
structepoll_event eventItem; memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union eventItem.events = EPOLLIN; eventItem.data.fd = mWakeReadPipeFd; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno); }
a. 发送消息屏障,屏蔽同步消息,从而保证VSYNC信号到来时可被立即执行 b. mChoreographer.postCallback()方法投递mTraversalRunnable,其消息类型是CALLBACK_TRAVERSAL c. 执行mTraversalRunnable的run()方法,移除屏障,并执行performTraversals()方法
上面只是大致流程,这里还有一些疑问点:
a. VSYNC信号是怎么到来的,是怎样跟消息机制结合的? b. mChoreographer.postCallback()发送的CALLBACK_TRAVERSAL代表什么含义? c. mTraversalRunnable的run()方法是怎么被调起执行的?
/** * Callback type: Animation callback to handle inset updates. This is separate from * {@link #CALLBACK_ANIMATION} as we need to "gather" all inset animation updates via * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} for multiple * ongoing animations but then update the whole view system with a single callback to * {@link View#dispatchWindowInsetsAnimationProgress} that contains all the combined updated * insets. * <p> * Both input and animation may change insets, so we need to run this after these callbacks, but * before traversals. * <p> * Runs before traversals. * @hide */ publicstaticfinalintCALLBACK_INSETS_ANIMATION=2;
/** * Callback type: Traversal callback. Handles layout and draw. Runs * after all other asynchronous messages have been handled. * @hide */ publicstaticfinalintCALLBACK_TRAVERSAL=3;
/** * 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 */ publicstaticfinalintCALLBACK_COMMIT=4;
@Override publicvoidhandleMessage(Message msg) { switch (msg.what) { case MSG_DO_FRAME: // 布局和绘制过程 doFrame(System.nanoTime(), 0, newDisplayEventReceiver.VsyncEventData()); break; case MSG_DO_SCHEDULE_VSYNC: // 申请VSYNC信号,例如当前需要绘制任务时 doScheduleVsync(); break; case MSG_DO_SCHEDULE_CALLBACK: // 需要延迟的任务,最终还是执行上述两个事件 doScheduleCallback(msg.arg1); break; } } }
voiddoScheduleCallback(int callbackType) { synchronized (mLock) { if (!mFrameScheduled) { finallongnow= SystemClock.uptimeMillis(); if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) { scheduleFrameLocked(now); } } } }
privatevoidscheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; // 开启了VSYNC if (USE_VSYNC) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync."); }
a. 发送异步消息(因为前面设置了同步屏障) b. 有延迟的任务发延迟消息 c. 不在原线程的切换到原线程 d. 没开启VSYNC的直接走doFrame方法取执行绘制
总结下Choreographer与FrameHandler结合这一小节
a. 如果系统未开启VSYNC机制,此时直接发送MSG_DO_FRAME消息到FrameHandler执行doFrame()方法 b. Android4.1之后系统默认开启VSYNC,最终通过scheduleVsyncLocked()方法申请VSYNC信号 c. 如果当前不在原线程,通过FrameHandler切换到主线程,最终还是调用scheduleVsyncLocked()方法申请VSYNC信号
// 构造函数 publicDisplayEventReceiver(Looper looper, int vsyncSource, int eventRegistration) { if (looper == null) { thrownewIllegalArgumentException("looper must not be null"); }
publicvoidonVsync(long timestampNanos, long physicalDisplayId, int frame, VsyncEventData vsyncEventData) { try { if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#onVsync " + vsyncEventData.id); } // 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. longnow= 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; }
if (!mFrameScheduled) { traceMessage("Frame not scheduled"); return; // no work to do }
...
// 预计执行时间 longintendedFrameTimeNanos= frameTimeNanos; startNanos = System.nanoTime(); // 超时时间是否超过一帧 // 这是因为MessageQueue虽然添加了同步屏障,但还是有正在执行的同步任务,导致doFrame()延迟执行了 finallongjitterNanos= startNanos - frameTimeNanos; if (jitterNanos >= frameIntervalNanos) { // 计算掉帧数 finallongskippedFrames= jitterNanos / frameIntervalNanos; // 掉帧数超过30,打印日志 if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) { Log.i(TAG, "Skipped " + skippedFrames + " frames! " + "The application may be doing too much work on its main thread."); } finallonglastFrameOffset= jitterNanos % frameIntervalNanos; if (DEBUG_JANK) { Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms " + "which is more than the frame interval of " + (frameIntervalNanos * 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."); } traceMessage("Frame time goes backward"); scheduleVsyncLocked(); return; }
if (mFPSDivisor > 1) { longtimeSinceVsync= frameTimeNanos - mLastFrameTimeNanos; if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) { traceMessage("Frame skipped due to FPSDivisor"); scheduleVsyncLocked(); return; } }
// 提交任务类型 if (callbackType == Choreographer.CALLBACK_COMMIT) { finallongjitterNanos= now - frameTimeNanos; if (jitterNanos >= 2 * frameIntervalNanos) { finallonglastFrameOffset= jitterNanos % frameIntervalNanos + frameIntervalNanos; frameTimeNanos = now - lastFrameOffset; mLastFrameTimeNanos = frameTimeNanos; } } } try { // 遍历执行所有任务 for (CallbackRecordc= callbacks; c != null; c = c.next) { // 回调run()方法,内部回调Callback类型的run() c.run(frameTimeNanos); } } finally { synchronized (mLock) { mCallbacksRunning = false; do { finalCallbackRecordnext= callbacks.next; // 回收CallbackRecord recycleCallbackLocked(callbacks); callbacks = next; } while (callbacks != null); } Trace.traceEnd(Trace.TRACE_TAG_VIEW); } }
privatestaticfinalclassCallbackRecord { public CallbackRecord next; publiclong dueTime; public Object action; // Runnable or FrameCallback public Object token;