Choreographer.java
DisplayEventReceiver.java
frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
frameworks/native/libs/gui/DisplayEventReceiver.cpp
一. 概述
前面两篇文章介绍了SurfaceFlinger原理,讲述了SurfaceFlinger的启动过程,绘制过程,以及Vsync处理过程。 本文再介绍一下Choreographer的启动与Vsync处理过程。
二. Choreographer启动流程
在Activity启动过程,执行完onResume后,会调用Activity.makeVisible(),然后再调用到addView(), 层层调用会进入如下方法:
public ViewRootImpl(Context context, Display display) {
...
//这里便出现获取Choreographer实例【见小节2.1】
mChoreographer = Choreographer.getInstance();
...
}
2.1 getInstance
[-> Choreographer.java]
public static Choreographer getInstance() {
return sThreadInstance.get(); //单例模式
}
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
protected Choreographer initialValue() {
Looper looper = Looper.myLooper(); //获取当前线程的Looper
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
return new Choreographer(looper); //【见小节2.2】
}
};
当前所在线程为UI线程,也就是常说的主线程。
2.2 创建Choreographer
[-> Choreographer.java]
private Choreographer(Looper looper) {
mLooper = looper;
//创建Handler对象【见小节2.3】
mHandler = new FrameHandler(looper);
//创建用于接收VSync信号的对象【见小节2.4】
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : 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();
}
}
- mLastFrameTimeNanos:是指上一次帧绘制时间点;
- mFrameIntervalNanos:帧间时长,一般等于16.7ms.
2.3 创建FrameHandler
[-> Choreographer.java ::FrameHandler]
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;
}
}
}
2.4 创建FrameDisplayEventReceiver
[-> Choreographer.java ::FrameDisplayEventReceiver]
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
public FrameDisplayEventReceiver(Looper looper) {
super(looper); //【见小节2.4.1】
}
}
2.4.1 DisplayEventReceiver
[-> DisplayEventReceiver.java]
public DisplayEventReceiver(Looper looper) {
mMessageQueue = looper.getQueue(); //获取主线程的消息队列
//【见小节2.4.2】
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
}
经过JNI调用进入如下Native方法。
2.4.2 nativeInit
[-> android_view_DisplayEventReceiver.cpp]
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
//【见小节2.4.3】
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue);
//【见小节2.4.4】
status_t status = receiver->initialize();
...
//获取DisplayEventReceiver对象的引用
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz);
return reinterpret_cast<jlong>(receiver.get());
}
2.4.3 创建NativeDisplayEventReceiver
[-> android_view_DisplayEventReceiver.cpp]
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp<MessageQueue>& messageQueue) :
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mMessageQueue(messageQueue), mWaitingForVsync(false) {
ALOGV("receiver %p ~ Initializing display event receiver.", this);
}
NativeDisplayEventReceiver继承于LooperCallback对象,此处mReceiverWeakGlobal记录的是Java层 DisplayEventReceiver对象的全局引用。
2.4.4 initialize
[-> android_view_DisplayEventReceiver.cpp]
status_t NativeDisplayEventReceiver::initialize() {
//mReceiver为DisplayEventReceiver类型
status_t result = mReceiver.initCheck();
...
//监听mReceiver的所获取的文件句柄。
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
...
return OK;
}
此处跟文章SurfaceFlinger原理(一)的【小节2.8】的监听原理一样。 监听mReceiver的所获取的文件句柄,一旦有数据到来,则回调this(此处NativeDisplayEventReceiver)中所复写LooperCallback对象的 handleEvent。
三、Vysnc回调流程
当vysnc信号由SurfaceFlinger中创建HWC触发,唤醒DispSyncThread线程,再到EventThread线程,然后再通过BitTube直接传递到目标进程所对应的目标线程,执行handleEvent方法。 ,
3.1 handleEvent
[-> android_view_DisplayEventReceiver.cpp]
int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
...
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
//清除所有的pending事件,只保留最后一次vsync【见小节3.1.1】
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
mWaitingForVsync = false;
//分发Vsync【见小节3.2.2】
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
return 1;
}
3.1.1 processPendingEvents
bool NativeDisplayEventReceiver::processPendingEvents(
nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
bool gotVsync = false;
DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
ssize_t n;
while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
gotVsync = true; //获取VSync信号
*outTimestamp = ev.header.timestamp;
*outId = ev.header.id;
*outCount = ev.vsync.count;
break;
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
break;
default:
break;
}
}
}
return gotVsync;
}
遍历所有的事件,当有多个VSync事件到来,则只关注最近一次的事件。
3.1.2 dispatchVsync[C++]
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
//【见小节3.2】
env->CallVoidMethod(receiverObj.get(),
gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
}
mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}
此处调用到Java层的DisplayEventReceiver对象的dispatchVsync()方法,接下来进入Java层。
3.2 dispatchVsync[Java]
[-> DisplayEventReceiver.java]
private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
//【见小节3.3】
onVsync(timestampNanos, builtInDisplayId, frame);
}
再回到【小节2.2】可知Choreographer对象实例化的过程,创建的对象是DisplayEventReceiver子类 FrameDisplayEventReceiver对象,接下来进入该对象。
3.3 onVsync
[-> Choreographer.java ::FrameDisplayEventReceiver]
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
...
mTimestampNanos = timestampNanos;
mFrame = frame;
//该消息的callback为当前对象FrameDisplayEventReceiver
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
//此处mHandler为FrameHandler
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
...
}
可见onVsync()过程是通过FrameHandler向主线程Looper发送了一个自带callback的消息,此处callback为FrameDisplayEventReceiver。 当主线程Looper执行到该消息时,则调用FrameDisplayEventReceiver.run()方法.
3.3.1 FrameDisplayEventReceiver.run
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame); //【见小节3.4】
}
}
3.4 Choreographer.doFrame
[-> Choreographer.java]
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // mFrameScheduled=false,则直接返回。
}
long intendedFrameTimeNanos = frameTimeNanos; //原本计划的绘帧时间点
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
//当掉帧个数超过30,则输出相应log
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;
frameTimeNanos = startNanos - lastFrameOffset; //对齐帧的时间间隔
}
if (frameTimeNanos < mLastFrameTimeNanos) {
scheduleVsyncLocked();
return;
}
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
//标记动画开始时间
mFrameInfo.markAnimationsStart();
//执行回调方法【见小节3.5】
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
此处frameTimeNanos是底层VSYNC信号到达的时间戳。
- 每调用一次scheduleFrameLocked(),则mFrameScheduled=true,能执行一次doFrame()操作,执行完doFrame()并设置mFrameScheduled=false;
- 最终有4个回调类别,如下所示:
- INPUT:输入事件
- ANIMATION:动画
- TRAVERSAL:窗口刷新,执行measure/layout/draw操作
- COMMIT:遍历完成的提交操作,用来修正动画启动时间
3.5 doCallbacks
[-> Choreographer.java]
void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;
synchronized (mLock) {
final long now = System.nanoTime();
// 从队列查找相应类型的CallbackRecord对象【见小节2.9.1】
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
if (callbacks == null) {
return; //当队列为空,则直接返回
}
mCallbacksRunning = true;
if (callbackType == Choreographer.CALLBACK_COMMIT) {
final long jitterNanos = now - frameTimeNanos;
//当commit类型回调执行的时间点超过2帧,则更新mLastFrameTimeNanos。
if (jitterNanos >= 2 * mFrameIntervalNanos) {
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
+ mFrameIntervalNanos;
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
}
}
}
try {
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos); //【见小节3.6】
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
//回收callbacks,加入对象池mCallbackPool
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
该方法主要功能:
- 从队列头mHead查找CallbackRecord对象,当队列头部的callbacks对象为空或者执行时间还没到达,则直接返回;
- 开始执行相应回调的run()方法;
- 回收callbacks,加入对象池mCallbackPool,就是说callback一旦执行完成,则会被回收。
3.6 CallbackRecord.run
[-> Choreographer.java ::CallbackRecord]
private static final class CallbackRecord {
public CallbackRecord next;
public long dueTime;
public Object action; // Runnable或者 FrameCallback
public Object token;
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}
这里的回调方法run()有两种执行情况:
- 当token的数据类型为FRAME_CALLBACK_TOKEN,则执行该对象的doFrame()方法;
- 当token为其他类型,则执行该对象的run()方法。
那么需要的场景便是由WMS调用scheduleAnimationLocked()方法来设置mFrameScheduled=true来触发动画, 接下来说说动画控制的过程。
四. 动画显示过程
调用栈:
WMS.scheduleAnimationLocked
postFrameCallback
postFrameCallbackDelayed
postCallbackDelayedInternal
scheduleFrameLocked
4.1 WMS.scheduleAnimationLocked
[-> WindowManagerService.java]
void scheduleAnimationLocked() {
if (!mAnimationScheduled) {
mAnimationScheduled = true;
//【见小节4.2】
mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
}
}
只有当mAnimationScheduled=false时,才会执行postFrameCallback(),其中参数为mAnimator对象的 成员变量mAnimationFrameCallback,该对象的初始化过程:
4.1.1 创建WMS
private WindowManagerService(
...
mAnimator = new WindowAnimator(this); //【见小节4.1.2】
...
}
4.1.2 创建WindowAnimator
[-> WindowAnimator.java]
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
mAnimationFrameCallback = new Choreographer.FrameCallback() {
public void doFrame(long frameTimeNs) {
synchronized (mService.mWindowMap) {
mService.mAnimationScheduled = false;
animateLocked(frameTimeNs);
}
}
};
}
mAnimationFrameCallback的数据类型为Choreographer.FrameCallback。
4.2 postFrameCallback
[-> Choreographer.java]
public void postFrameCallback(FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
...
//【见小节4.3】
postCallbackDelayedInternal(CALLBACK_ANIMATION,
callback, FRAME_CALLBACK_TOKEN, delayMillis);
}
4.3 postCallbackDelayedInternal
[-> Choreographer.java]
// callbackType为动画,action为mAnimationFrameCallback
// token为FRAME_CALLBACK_TOKEN,delayMillis=0
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
//添加到mCallbackQueues队列
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
//发送消息MSG_DO_SCHEDULE_CALLBACK
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
发送MSG_DO_SCHEDULE_CALLBACK消息后,主线程接收后进入FrameHandler的handleMessage()操作,如下方法。
4.4 MSG_DO_SCHEDULE_CALLBACK
[-> Choreographer.java ::FrameHandler]
private final class FrameHandler extends Handler {
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); //【见小节4.5】
break;
}
}
}
4.5 doScheduleCallback
[-> Choreographer.java]
void doScheduleCallback(int callbackType) {
synchronized (mLock) {
if (!mFrameScheduled) {
final long now = SystemClock.uptimeMillis();
if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
scheduleFrameLocked(now); //【见小节4.6】
}
}
}
}
4.6 scheduleFrameLocked
[-> Choreographer.java]
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (isRunningOnLooperThreadLocked()) {
//当运行在Looper线程,则立刻调度vsync
scheduleVsyncLocked();
} else {
//否则,发送消息到UI线程
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);
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
该方法的功能:
- 当运行在Looper线程,则立刻调度scheduleVsyncLocked();
- 当运行在其他线程,则通过发送一个消息到Looper线程,然后再执行scheduleVsyncLocked();
4.7 scheduleVsyncLocked
[-> Choreographer.java]
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync(); //【见小节4.8】
}
mDisplayEventReceiver对象是在【小节2.2】Choreographer的实例化过程所创建的。
4.8 scheduleVsync
[-> DisplayEventReceiver.java]
public void scheduleVsync() {
if (mReceiverPtr == 0) {
...
} else {
nativeScheduleVsync(mReceiverPtr);
}
}
4.9 nativeScheduleVsync
[-> android_view_DisplayEventReceiver.cpp]
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp<NativeDisplayEventReceiver> receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
status_t status = receiver->scheduleVsync();
...
}
4.10 scheduleVsync
[-> android_view_DisplayEventReceiver.cpp]
status_t NativeDisplayEventReceiver::scheduleVsync() {
if (!mWaitingForVsync) {
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
//【见小节4.11】
status_t status = mReceiver.requestNextVsync();
...
mWaitingForVsync = true;
}
return OK;
}
4.11 requestNextVsync
[-> DisplayEventReceiver.cpp]
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != NULL) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return NO_INIT;
}
该方法的作用请求下一次Vsync信息处理,当Vsync信号到来,由于mFrameScheduled=true,则继续【小节3.6】CallbackRecord.run()方法。
五、总结
- 尽量避免在执行动画渲染的前后在主线程放入耗时操作,否则会造成卡顿感,影响用户体验;
- 可通过Choreographer.getInstance().postFrameCallback()来监听帧率情况;
- 每调用一次scheduleFrameLocked(),则mFrameScheduled=true,可进入doFrame()方法体内部,执行完doFrame()并设置mFrameScheduled=false;
- doCallbacks回调方法有4个类别:INPUT(输入事件),ANIMATION(动画),TRAVERSAL(窗口刷新),COMMIT(完成后的提交操作)。
微信公众号 Gityuan | 微博 weibo.com/gityuan | 博客 留言区交流