该系列文章总纲链接:专题分纲目录 Android Framework 窗口子系统
导图是不断迭代的,该图主要关注➕思维导图中左上:Choreographer机制 部分即可,主要说明Choreographer机制的对外接口,这里做了简单的源码分析,对其原理有一定的了解。放大 Choreographer机制 的局部图,效果如下:
Choreographer机制说明:该机制是android 4.2之后 推出的API,和handler的post机制类似,区别在于Choreographer的处理时机是 屏幕的垂直同步Vsync事件到来之时,其处理回调的过程被当作渲染下一帧工作的一部分。
对于动画而言,Choreographer对外接口说明如下:
后面会通过源码进行深入的说明。接下来开始进入Choreographer源码解读
1 Choreographer分析
在Activity启动过程,执行完onResume后,层层调用后会到addView(),再到ViewRootImpl构造器,代码如下:
public ViewRootImpl(Context context, Display display) {
//...
mChoreographer = Choreographer.getInstance();
//...
}
继续分析getInstance,代码如下:
public static Choreographer getInstance() {
return sThreadInstance.get();
}
继续分析sThreadInstance.get,代码如下:
private static final ThreadLocal sThreadInstance =
new ThreadLocal() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();//获取当前线程looper
//...
return new Choreographer(looper);
}
};
当前线程为UI线程,因此get获得的就是Choreographer(looper);继续分析Choreographer构造器,代码如下:
private Choreographer(Looper looper) {
mLooper = looper;
mHandler = new FrameHandler(looper);//handler对象
//用于接收VSync信号
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
//是指上一次帧绘制时间点;
mLastFrameTimeNanos = Long.MIN_VALUE;
//帧间时长,一般等于16.7ms
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
//创建回调对象
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
}
接下来我们关注两个变量:FrameHandler和FrameDisplayEventReceiver。
1.1 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;
}
}
}
这里可知:handler可以处理三种消息,帧消息,VSYNC,CALLBACK。
1.2 FrameDisplayEventReceiver创建
代码如下:
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper) {
super(looper);
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
scheduleVsync();
return;
}
long now = System.nanoTime();
if (timestampNanos > now) {
timestampNanos = now;
}
if (mHavePendingVsync) {
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
这里当有Vsync信号上报时会回调onVSync方法,它使用handler发送消息给主线程Looper,消息自带callback,内容为FrameDisplayEventReceiver。 当主线程Looper执行到该消息时调用FrameDisplayEventReceiver.run()方法。这里沿着run方法,继续分析doFrame,代码如下:
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
frameTimeNanos = startNanos - lastFrameOffset;
}
if (frameTimeNanos < mLastFrameTimeNanos) {
scheduleVsyncLocked();
return;
}
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
}
这里继续分析doCallbacks,代码如下:
void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);
mCallbacksRunning = true;
}
try {
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos);
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
}
}
这段代码总结如下:
接下来我们继续分析下CallbackRecord类,代码如下:
private static final class CallbackRecord {
public CallbackRecord next;
public long dueTime;
public Object action; // Runnable or FrameCallback
public Object token;
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}
这里的回调run()有两种情况:
2 动画显示过程
WMS是通过调用scheduleAnimationLocked()方法来设置mFrameScheduled=true来触发动画, 下面分析动画控制的过程。代码如下:
void scheduleAnimationLocked() {
if (!mAnimationScheduled) {
mAnimationScheduled = true;
mChoreographer.postCallback(
Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
}
}
只有当mAnimationScheduled=false时,才会执行postCallback(),其中参数为mAnimator.mAnimationFrameCallback。
2.1 这里对参数mAnimator.mAnimationFrameCallback进行分析
mAnimator该对象类型为WindowAnimator,在WMS中定义:
private WindowManagerService(
//...
mAnimator = new WindowAnimator(this);
//...
}
WindowAnimator的构造器如下:
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
mAnimationRunnable = new Runnable() {
@Override
public void run() {
synchronized (mService.mWindowMap) {
mService.mAnimationScheduled = false;
animateLocked();
}
}
};
}
分析到这里,如果下一个VSync到来,将会执行到animateLocked方法。
2.2 对mChoreographer.postCallback进行分析
postCallback代码实现如下:
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
继续分析postCallbackDelayed,代码如下:
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
//容错处理...
postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}
继续分析postCallbackDelayedInternal,代码如下:
// 参数说明:
/*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,handler收到后处理如前面所示:
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);
break;
}
}
}
这里继续分析doScheduleCallback,代码如下所示:
void doScheduleCallback(int callbackType) {
synchronized (mLock) {
if (!mFrameScheduled) {
final long now = SystemClock.uptimeMillis();
if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
scheduleFrameLocked(now);
}
}
}
}
继续分析scheduleFrameLocked,代码实现如下:
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();//当运行在Looper线程,则立刻调度vsync
} else {
//发送给UI线程
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
//...
}
}
}
这里注意,当运行在其他线程时,通过发送一个消息到Looper线程,然后通过handler处理消息执行scheduleVsyncLocked();
接下来分析scheduleVsyncLocked的核心实现,代码如下:
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
继续分析mDisplayEventReceiver的scheduleVsync实现,代码如下:
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);
}
}
这里nativeScheduleVsync函数的实现,代码如下:
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
sp receiver =
reinterpret_cast(receiverPtr);
status_t status = receiver->scheduleVsync();
//容错处理...
}
这里继续分析receiver->scheduleVsync();,代码实现如下:
status_t NativeDisplayEventReceiver::scheduleVsync() {
if (!mWaitingForVsync) {
// Drain all pending events.
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
//清除所有的pending事件,只保留最后一次vsync
processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
status_t status = mReceiver.requestNextVsync();
mWaitingForVsync = true;
}
return OK;
}
这里关注mReceiver.requestNextVsync();代码实现如下:
status_t DisplayEventReceiver::requestNextVsync() {
if (mEventConnection != NULL) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
return NO_INIT;
}
该方法的作用请求下一次Vsync信息处理,当Vsync信号到来,由于mFrameScheduled = true,则继续执行第1部分中最后部分中的CallbackRecord.run()方法。
使用说明:避免在执行动画渲染的前后在主线程放入耗时操作,否则会造成卡顿感,影响用户体验。