SurfaceFlinger 进程中请求到 VSync 信号,并且封装成 Event 事件后回调给 EventThread 进行分发,EventThread 将数据通过文件描述符 mSendFd 关联的 socket 管道发送到一段指定大小的缓冲区中,现在应用进程端需要通过文件描述符 mReceiveFd 关联的 socket 管道从指定的缓冲区中读取出数据。
当 socket 管道的 mSendFd 端有数据写入时,就会把与之对应的 mReceiveFd 有关的 Request 取出并收集起来,待 Native 层的 Message 处理完后,循环遍历收集起来的 Request,取出每个 Request 并调用其 callback 回调的 handleEvent() 方法。该回调就是向 Looper 中添加 fd 时作为 LooperCallback 回调一并传入的 DisplayEventDispatcher 实现类,查看实现类的 handleEvent() 方法,代码如下:
//frameworks/native/libs/gui/DisplayEventDispatcher.cpp
int DisplayEventDispatcher::handleEvent(int, int events, void*) {
if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
ALOGE("Display event receiver pipe was closed or an error occurred. "
"events=0x%x",
events);
// 管道关闭或者出现了错误,则移除回调
return 0; // remove the callback
}
if (!(events & Looper::EVENT_INPUT)) {
ALOGW("Received spurious callback for unhandled poll event. "
"events=0x%x",
events);
// 收到未处理轮询事件的伪造事件 Event(前面分析过为了防止驱动程序停止),则保留回调
return 1; // keep the callback
}
// Drain all pending events, keep the last vsync.
// 清空所有挂起的事件,只保留最近一次 VSync 事件
nsecs_t vsyncTimestamp;
PhysicalDisplayId vsyncDisplayId;
uint32_t vsyncCount;
VsyncEventData vsyncEventData;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
", displayId=%s, count=%d, vsyncId=%" PRId64,
this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
vsyncEventData.preferredVsyncId());
// 获取到最近的 VSync 信息,将正在等待 VSync 标志位置为 false
mWaitingForVsync = false;
mLastVsyncCount = vsyncCount;
// 由于 DisplayEventDispatcher 类没有复写 dispatchVsync 方法,在其子类NativeDisplayEventReceiver 中复写了该方法
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
}
if (mWaitingForVsync) {
const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
const nsecs_t vsyncScheduleDelay = currentTime - mLastScheduleVsyncTime;
if (vsyncScheduleDelay > WAITING_FOR_VSYNC_TIMEOUT) {
ALOGW("Vsync time out! vsyncScheduleDelay=%" PRId64 "ms", ns2ms(vsyncScheduleDelay));
mWaitingForVsync = false;
dispatchVsync(currentTime, vsyncDisplayId /* displayId is not used */,
++mLastVsyncCount, vsyncEventData /* empty data */);
}
}
return 1; // keep the callback
}
调用NativeDisplayEventReceiver的dispatchVsync方法:
//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
uint32_t count, VsyncEventData vsyncEventData) {
// 获取 JNI 上下文环境
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
ALOGV("receiver %p ~ Invoking vsync handler.", this);
jobject javaVsyncEventData = createJavaVsyncEventData(env, vsyncEventData);
// 通过 JNI 方法调用,调用 Java 层 DisplayEventReceiver 的 dispatchVsync() 方法,参数传入对应的时间戳、显示屏 Id、VSync 个数、帧间隔等信息
env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
timestamp, displayId.value, count, javaVsyncEventData);
ALOGV("receiver %p ~ Returned from vsync handler.", this);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
DisplayEventReceiver dispatchVsync
调用DisplayEventReceiver的dispatchVsync方法:
//frameworks/base/core/java/android/view/DisplayEventReceiver.java
public abstract class DisplayEventReceiver {
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
VsyncEventData vsyncEventData) {
onVsync(timestampNanos, physicalDisplayId, frame, vsyncEventData);
}
}
调用onVsync方法,DisplayEventReceiver 是一个抽象类,onVsync() 方法是一个空方法,因此需要进入其实现类 FrameDisplayEventReceiver 中查看:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
@Override
public void onVsync(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.preferredFrameTimeline().vsyncId);
}
// 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;
mLastVsyncEventData = vsyncEventData;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
}
}
在该方法中通过 Message的obtain() 方法获取到 Message,由 FrameHandler 发送消息并执行获取消息时传入的回调。由于获取消息时传入的回调是 FrameDisplayEventReceiver 本身,并且实现了 Runnable 接口,因此会回调 FrameDisplayEventReceiver的run() 方法:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
}
}
}
Choreographer doFrame
调用Choreographer的doFrame方法:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
void doFrame(long frameTimeNanos, int frame,
DisplayEventReceiver.VsyncEventData vsyncEventData) {
final long startNanos;
final long frameIntervalNanos = vsyncEventData.frameInterval;
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId);
}
FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData);
synchronized (mLock) {
if (!mFrameScheduled) {
traceMessage("Frame not scheduled");
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(); // 记录实际开始执行当前 frame 的时间
final long jitterNanos = startNanos - frameTimeNanos; // 计算时间差值
if (jitterNanos >= frameIntervalNanos) { // 时间差值大于等于帧间隔,即发生了跳帧
long lastFrameOffset = 0;
if (frameIntervalNanos == 0) {
Log.i(TAG, "Vsync data empty due to timeout");
} else {
// 计算实际开始当前 frame 的时间戳与帧间隔的偏移值
lastFrameOffset = jitterNanos % frameIntervalNanos;
final long skippedFrames = jitterNanos / frameIntervalNanos; // 计算跳帧数
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main "
+ "thread.");
}
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;
frameData.updateFrameData(frameTimeNanos);
}
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");
// 当前帧的时间小于上一个帧的时间,可能是由于先前跳帧的缘故,申请并等待下一次 VSync 信号到来
scheduleVsyncLocked();
return;
}
if (mFPSDivisor > 1) {
long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
traceMessage("Frame skipped due to FPSDivisor");
// 由于 FPSDivisor 导致跳帧,继续申请并等待下一次 VSync 信号到来
scheduleVsyncLocked();
return;
}
}
// 记录当前 Frame 信息
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos,
vsyncEventData.preferredFrameTimeline().vsyncId,
vsyncEventData.preferredFrameTimeline().deadline, startNanos,
vsyncEventData.frameInterval);
// 收到 VSync 信号当前帧调度完,mFrameScheduled 标志位重置为 false,以便下一轮请求使用
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos; // 记录上一次 Frame 渲染的时间
mLastFrameIntervalNanos = frameIntervalNanos; // 记录上一次 Frame 渲染的帧间隔
mLastVsyncEventData = vsyncEventData; // 记录上一次 VSync 事件信息
}
// 动画锁定为当前线程的固定值
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
// 按照事件类型的优先级执行 CallBack
mFrameInfo.markInputHandlingStart();
// 输入事件,首先执行
doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);
mFrameInfo.markAnimationsStart();
// 动画事件,在 CALLBACK_INSETS_ANIMATION 之前执行
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
// 插入更新动画事件,INPUT 和 ANIMATION 后面执行,TRAVERSAL 之前执行
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,
frameIntervalNanos);
// 处理布局和绘制事件,在处理完上述异步消息之后运行
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);
} 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.");
}
}
}
调用Choreographer的doCallbacks方法:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {
CallbackRecord callbacks;
long frameTimeNanos = frameData.mFrameTimeNanos;
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.
// 获取正在运行的 Java 虚拟机的当前时间,单位为纳秒,以此来确定回调何时执行,因为帧中的前期处理阶段可能会发布应在下一阶段运行的回调,例如导致动画启动的输入事件
final long now = System.nanoTime();
// 从数组链表 mCallbackQueues 中获取指定类型的链表
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 * frameIntervalNanos) {
final long lastFrameOffset = jitterNanos % frameIntervalNanos
+ frameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
+ " ms which is more than twice the frame interval of "
+ (frameIntervalNanos * 0.000001f) + " ms! "
+ "Setting frame time to " + (lastFrameOffset * 0.000001f)
+ " ms in the past.");
mDebugPrintNextFrameTimeDelta = true;
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
frameData.updateFrameData(frameTimeNanos);
}
}
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
// 遍历 callbacks 链表获取 CallbackRecord 对象
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));
}
// 执行 CallbackRecord 对象的 run() 方法
c.run(frameData);
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
// 回收 callbacks,置空其内部 CallbackRecord 保存的信息,重组并赋值给 mCallbackPool 链表
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
}
调用c(CallbackRecord)的run方法:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
private static final class CallbackRecord {
void run(FrameData frameData) {
// 根据 token 判断当前回调类型
if (token == VSYNC_CALLBACK_TOKEN) {
((VsyncCallback) action).onVsync(frameData);
} else {
run(frameData.getFrameTimeNanos());
}
}
}
}
调用run方法:
//frameworks/base/core/java/android/view/Choreographer.java
public final class Choreographer {
private static final class CallbackRecord {
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
// 通过 postFrameCallback() 或 postFrameCallbackDelayed() 会执行这里
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
// 取出 Runnable 并执行其 run() 方法
((Runnable)action).run();
}
}
}
}
在Choreographer的postCallback方法中,提交一个任务 TraversalRunnable,将任务 TraversalRunnable 和执行时间一起被封装成 CallbackRecord,因此这里执行的就是 TraversalRunnable 的 run() 方法。
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
}
ViewRootImpl doTraversal
调用ViewRootImpl的doTraversal方法:
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
void doTraversal() {
if (mTraversalScheduled) {
// mTraversalScheduled 标志位重新置为 false
mTraversalScheduled = false;
// 通过调用 removeSyncBarrier 方法移除同步屏障消息,传入 postSyncBarrier() 方法的返回值作为参数
// 标识需要移除哪个屏障,然后将该屏障消息会从队列中移除,以确保消息队列恢复正常操作,否则应用程序可能会挂起
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
// 执行 View 的绘制流程开始渲染新页面
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
}
ViewRootImpl performTraversals
调用ViewRootImpl的performTraversals方法,开始View的三大流程(measure、layout、draw):