[TOC]

文章参考:https://www.androidperformance.com/2019/10/22/Android-Choreographer/

一.概述

前面两篇文章介绍了SurfaceFlinger原理,讲述了SurfaceFlinger的启动过程,绘制过程,以及Vsync处理过程。 本文再介绍一下Choreographer的启动与Vsync处理过程。

要学习Choreographer的的原理,我们先来看一段日志。

1
2
I/Choreographer: Skipped 85 frames!  The application may be doing too much work on its main thread.
I/Choreographer: Skipped 56 frames! The application may be doing too much work on its main thread.

这个日志,我想我们已经很熟悉了。我们如果应用比较卡顿掉帧的时候,控制台就会有这样的日志打印。

1
2
3
private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt(
"debug.choreographer.skipwarning", 30);

默认只会打印掉帧 >=30 帧的信息,已 ROOT 的手机可以修改此条件。

1
2
3
getprop debug.choreographer.skipwarning      //读取
setprop debug.choreographer.skipwarning 5 //修改
setprop ctl.restart surfaceflinger; setprop ctl.restart zygote //重启

二. Choreographer的原理

硬件每 16 毫秒产一个 VSync 信号,App 要想实现垂直同步,就是要收到 VSync
只有调用 DisplayEventReceiver 的 nativeScheduleVsync 方法后,才能收到下一个 VSync
请求 VSync(即调用 nativeScheduleVsync)只是单次有效,并不是一劳永逸
请求 VSync → 收到 VSync → 请求 VSync → 收到 VSync
如果没有再次请求 VSync,则无法收到 VSync。

我们将 Choreographer 工作过程分为 2 部分来分析:请求 VSync 和 收到 VSync

三. Choreographer启动流程

下面,我们基于上面的流程图,来学习理解Choreographer工作过程,有助于分析代码调用过程、进行帧率统计、分析 Systrace。

在Activity启动过程,执行完onResume后,会调用Activity.makeVisible(),然后再调用到addView(), 层层调用会进入如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@VisibleForTesting
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
String reason) {

if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {

r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
//
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}

r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 调用Activity的makeViasion
*/
void makeVisible() {
if (!mWindowAdded) {
// 获取当前的mWindowManager
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
// 设置让Decor俩设置进行电视
mDecor.setVisibility(View.VISIBLE);
}

在ViewRootImpl的构造函数中的获取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
27
public ViewRootImpl(Context context, Display display) {

// 获取Choreographer的实例
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
}


@UnsupportedAppUsage
void scheduleTraversals() {
//1、注意这个标志位,多次调用 requestLayout,要这个标志位false才有效
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 2. 同步屏障
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 3. 向 Choreographer 提交一个任务
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
//绘制前发一个通知
notifyRendererOfFramePending();
//这个是释放锁,先不管
pokeDrawLockIfNeeded();
}
}
1
2
3
4
public static Choreographer getInstance() {
// 获取Choreographer的单例对象
return sThreadInstance.get();
}

在ThreadLocal中进行实例化Choreographer对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Thread local storage for the choreographer.
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
//获取当前线程的Looper
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;
}
};

当前所在线程为UI线程,也就是常说的主线程。

创建Choreographer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
// 创建序列帧的Handler对象
mHandler = new FrameHandler(looper);
//创建用于接收VSync信号的对象
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
// mLastFrameTimeNanos:是指上一次帧绘制时间点;
mLastFrameTimeNanos = Long.MIN_VALUE;
// mFrameIntervalNanos:帧间时长,一般等于16.7ms.
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
//创建回调对象
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
// b/68769804: For low FPS experiments.
setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}

创建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;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@TestApi
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}

@TestApi
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
if (action == null) {
throw new IllegalArgumentException("action must not be null");
}
if (callbackType < 0 || callbackType > CALLBACK_LAST) {
throw new IllegalArgumentException("callbackType is invalid");
}

postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}
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
/**
* 最终都是调用的这里的方法
*/
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
if (DEBUG_FRAMES) {
Log.d(TAG, "PostCallback: type=" + callbackType
+ ", action=" + action + ", token=" + token
+ ", delayMillis=" + delayMillis);
}

synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
// 将任务添加到队列,不会马上执行,后面会用到。
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
// scheduleFrameLocked,正常的情况下delayMillis是0,走这里,看下面分析。
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
// 3. 什么时候会有延时,绘制超时,等下一个vsync?
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}

把任务都放在 mCallbackQueues[callbackType] 队列中

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
private void scheduleFrameLocked(long now) {
//标志位,避免不必要的多次调用
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}

// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
//1 如果当前线程是UI线程,直接执行scheduleFrameLocked,否则通过Handler处理
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
// mLastFrameTimeNanos 主要作用于当 USE_VSYNC = false 的时候,设置 doFrame 的时间
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
1
2
3
4
@UnsupportedAppUsage
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}