2021.8.1 Matrix 2.0 TraceCanary新增了以下功能
微信Android客户端的卡顿监控方案 https://mp.weixin.qq.com/s/3dubi2GVW_rVFZZztCpsKg
1.监控IdleHandler卡顿 IdleHandlerLagTracer已在Matrix开源,本文已经对其源码分析
2.监控TouchEvent卡顿 提供了思路,在Matrix里没有找到
3.监控SyncBarrier泄漏 提供了代码,在Matrix没有找到
IdleHandler相关知识:https://blog.youkuaiyun.com/plokmju88/article/details/104386173/
微信Android客户端的ANR监控方案
https://mp.weixin.qq.com/s/fWoXprt2TFL1tTapt7esYg
讲解了SignalAnrTracer,下面这篇文章讲解了源码分析
https://blog.youkuaiyun.com/stone_cold_cool/article/details/119464855
Android的离奇陷阱 — 设置线程优先级导致的微信卡顿惨案https://mp.weixin.qq.com/s/oLz_F7zhUN6-b-KaI8CMRw
讲解了 ThreadPriorityTracer,本文已经对其源码分析
1.TracePlugin 启动创建UIThreadMonitor,AppMethodBeat,AnrTracer,FrameTracer,EvilMethodTracer,StartupTracer
//ok
public class TracePlugin extends Plugin {
//region 参数
private static final String TAG = "Matrix.TracePlugin";
private final TraceConfig traceConfig;
private EvilMethodTracer evilMethodTracer;
private StartupTracer startupTracer;
private FrameTracer frameTracer;
private AnrTracer anrTracer;
//endregion
//初始化传入TraceConfig
public TracePlugin(TraceConfig config) {
this.traceConfig = config;
}
@Override
public void init(Application app, PluginListener listener) {
super.init(app, listener);
MatrixLog.i(TAG, "trace plugin init, trace config: %s", traceConfig.toString());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
MatrixLog.e(TAG, "[FrameBeat] API is low Build.VERSION_CODES.JELLY_BEAN(16), TracePlugin is not supported");
unSupportPlugin();
return;
}
//创建4个tracer
anrTracer = new AnrTracer(traceConfig);
frameTracer = new FrameTracer(traceConfig);
evilMethodTracer = new EvilMethodTracer(traceConfig);
startupTracer = new StartupTracer(traceConfig);
}
//step 1
@Override
public void start() {
super.start();
if (!isSupported()) {
MatrixLog.w(TAG, "[start] Plugin is unSupported!");
return;
}
MatrixLog.w(TAG, "start!");
Runnable runnable = new Runnable() {
@Override
public void run() {
//UIThreadMonitor 初始化
if (!UIThreadMonitor.getMonitor().isInit()) {
try {
UIThreadMonitor.getMonitor().init(traceConfig);
} catch (java.lang.RuntimeException e) {
MatrixLog.e(TAG, "[start] RuntimeException:%s", e);
return;
}
}
//AppMethodBeat 启动
AppMethodBeat.getInstance().onStart();
//UIThreadMonitor 启动
UIThreadMonitor.getMonitor().onStart();
//4个tracer启动
anrTracer.onStartTrace();
frameTracer.onStartTrace();
evilMethodTracer.onStartTrace();
startupTracer.onStartTrace();
}
};
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
runnable.run();
} else {
MatrixLog.w(TAG, "start TracePlugin in Thread[%s] but not in mainThread!", Thread.currentThread().getId());
MatrixHandlerThread.getDefaultMainHandler().post(runnable);
}
}
@Override
public void stop() {
super.stop();
if (!isSupported()) {
MatrixLog.w(TAG, "[stop] Plugin is unSupported!");
return;
}
MatrixLog.w(TAG, "stop!");
Runnable runnable = new Runnable() {
@Override
public void run() {
AppMethodBeat.getInstance().onStop();
UIThreadMonitor.getMonitor().onStop();
anrTracer.onCloseTrace();
frameTracer.onCloseTrace();
evilMethodTracer.onCloseTrace();
startupTracer.onCloseTrace();
}
};
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
runnable.run();
} else {
MatrixLog.w(TAG, "stop TracePlugin in Thread[%s] but not in mainThread!", Thread.currentThread().getId());
MatrixHandlerThread.getDefaultMainHandler().post(runnable);
}
}
@Override
public void onForeground(boolean isForeground) {
super.onForeground(isForeground);
if (!isSupported()) {
return;
}
if (frameTracer != null) {
frameTracer.onForeground(isForeground);
}
if (anrTracer != null) {
anrTracer.onForeground(isForeground);
}
if (evilMethodTracer != null) {
evilMethodTracer.onForeground(isForeground);
}
if (startupTracer != null) {
startupTracer.onForeground(isForeground);
}
}
@Override
public void destroy() {
super.destroy();
}
//region get方法
@Override
public String getTag() {
return SharePluginInfo.TAG_PLUGIN;
}
public FrameTracer getFrameTracer() {
return frameTracer;
}
public AppMethodBeat getAppMethodBeat() {
return AppMethodBeat.getInstance();
}
public AnrTracer getAnrTracer() {
return anrTracer;
}
public EvilMethodTracer getEvilMethodTracer() {
return evilMethodTracer;
}
public StartupTracer getStartupTracer() {
return startupTracer;
}
public UIThreadMonitor getUIThreadMonitor() {
if (UIThreadMonitor.getMonitor().isInit()) {
return UIThreadMonitor.getMonitor();
} else {
return null;
}
}
public TraceConfig getTraceConfig() {
return traceConfig;
}
//endregion
}
2.TraceConfig配置类,Constant类定义了各种阈值
public boolean defaultFpsEnable; //是否开启Fps监控
public boolean defaultMethodTraceEnable;//是否开启方法监控
public boolean defaultStartupEnable; //是否开启startup监控
public boolean defaultAnrEnable; //是否开启anr监控
public boolean isDebug; //是否debug
public boolean isDevEnv; //是否dev环境
public String splashActivities; //splash activity
public Set<String> splashActivitiesSet; //splash activity set
public boolean isHasActivity; //true
getSplashActivities
getEvilThresholdMs //evil方法,超时方法阈值 700ms
getTimeSliceMs //帧累计超时时间限制,超过10s上报
getColdStartupThresholdMs//10s 冷启动时间,超过10s上报
getWarmStartupThresholdMs//4s 热启动时间,超过4s上报
getFrozenThreshold //掉了42帧,特别严重的掉帧
getHighThreshold //掉了24帧,比较高的掉帧
getMiddleThreshold //9,中等掉帧
getNormalThreshold //3,一般掉帧
public class Constants {
public static final int BUFFER_SIZE = 100 * 10000; // 7.6M
public static final int TIME_UPDATE_CYCLE_MS = 5; //ok 通过一个线程,每五毫秒更新变量,每个方法调用前后只需读取该变量获取时间
//Matrix默认最多上传30个堆栈。如果堆栈调用超过30条,需要裁剪堆栈。裁剪策略如下:
//从后往前遍历先序遍历结果,如果堆栈大小大于30,则将执行时间小于5*整体遍历次数的节点剔除掉
//最多整体遍历60次,每次整体遍历,比较时间增加5ms
//如果遍历了60次,堆栈大小还是大于30,将后面多余的删除掉
public static final int TARGET_EVIL_METHOD_STACK = 30; //最多上传30个堆栈
public static final int FILTER_STACK_MAX_COUNT = 60; //stack裁剪次数
public static final float FILTER_STACK_KEY_ALL_PERCENT = .3F; //statck里key方法,时常超过一个帧的时常的30%的方法
public static final int DEFAULT_EVIL_METHOD_THRESHOLD_MS = 700; //邪恶方法,执行时间长的方法阈值
public static final int DEFAULT_FPS_TIME_SLICE_ALIVE_MS = 10 * 1000; //掉帧累计10s,就上报
public static final int TIME_MILLIS_TO_NANO = 1000000;
public static final int DEFAULT_ANR = 5 * 1000; //anr 5s
public static final int DEFAULT_NORMAL_LAG = 2 * 1000; //lag 消息 2s
public static final int DEFAULT_ANR_INVALID = 6 * 1000; //无效anr,anr倒计时线程,没有在5s唤醒
public static final long DEFAULT_FRAME_DURATION = 16666667L;//一帧时间
public static final int DEFAULT_DROPPED_NORMAL = 3; //ok 掉帧
public static final int DEFAULT_DROPPED_MIDDLE = 9; //ok 150ms
public static final int DEFAULT_DROPPED_HIGH = 24; //ok 384ms
public static final int DEFAULT_DROPPED_FROZEN = 42;//ok 672ms
public static final int DEFAULT_STARTUP_THRESHOLD_MS_WARM = 4 * 1000; //热启动4s阈值
public static final int DEFAULT_STARTUP_THRESHOLD_MS_COLD = 10 * 1000;//冷启动10s阈值
public static final int DEFAULT_RELEASE_BUFFER_DELAY = 15 * 1000;//15秒
public enum Type {
NORMAL, ANR, STARTUP, LAG
}
}
3.LooperMonitor Looper 的监控是由类 LooperMonitor 实现的,原理很简单,为主线程 Looper 设置一个 Printer 即可,LooperDispatchListener既可以知道消息开始,结束
但值得一提的是,LooperMonitor 不会直接设置 Printer,而是先获取旧对象,并创建代理对象,避免影响到其它用户设置的 Printer
/**
* 监听Looper 消息分发开始,结束
*/
public abstract static class LooperDispatchListener {
boolean isHasDispatchStart = false;
public boolean isValid() {
return false;
}
public void dispatchStart() {
}
@CallSuper
public void onDispatchStart(String x) {
this.isHasDispatchStart = true;
dispatchStart();
}
@CallSuper
public void onDispatchEnd(String x) {
this.isHasDispatchStart = false;
dispatchEnd();
}
public void dispatchEnd() {
}
}
4.UIThreadMonitor使用LooperMonitor监控每个消息开始结束的时间。vsync同步也是消息的一种(所以也监控每一帧)通过Choreographer编舞者,计算每一帧input/动画/绘制三个队列所花的时间。并通过LooperObserver接口通知各LooperObserver。
4.1使用LooperMonitor监控每个消息开始结束的时间。
4.2vsync同步也是消息的一种(所以也监控每一帧)通过Choreographer编舞者,计算每一帧input/动画/绘制三个队列所花的时间
4.3并通过LooperObserver接口通知各LooperObserver
/**
* 通过LooperMonitor监听ui线程的消息分发,vsync同步也是消息的一种,将结果通过LooperObserver分发出去
* 通过往编舞者Choreographer ALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL三种类型的CallbackQueue
* 里添加Runnable,即UIThreadMonitor,当UIThreadMonitor的run被调用了说明这个消息是vsync消息
*/
public class UIThreadMonitor implements BeatLifecycle, Runnable {
//region 参数
/**
* Callback type: Input callback. Runs first.
*
* @hide
*/
public static final int CALLBACK_INPUT = 0;
/**
* Callback type: Animation callback. Runs before traversals.
*
* @hide
*/
public static final int CALLBACK_ANIMATION = 1;
/**
* Callback type: Commit callback. Handles post-draw operations for the frame.
* Runs after traversal completes.
*
* @hide
*/
public static final int CALLBACK_TRAVERSAL = 2;
/**
* never do queue end code
*/
public static final int DO_QUEUE_END_ERROR = -100;
private static final String TAG = "Matrix.UIThreadMonitor";
// Choreographer 中一个内部类的方法,用于添加回调
private static final String ADD_CALLBACK = "addCallbackLocked";
// The time of the oldest input event,没有用到
private static final int OLDEST_INPUT_EVENT = 3;
// The time of the newest input event,没用到
private static final int NEWEST_INPUT_EVENT = 4;
private static final int CALLBACK_LAST = CALLBACK_TRAVERSAL;
// 回调类型,分别为输入事件、动画、View 绘制三种
private final static UIThreadMonitor sInstance = new UIThreadMonitor();
private static final int DO_QUEUE_DEFAULT = 0;
private static final int DO_QUEUE_BEGIN = 1;
private static final int DO_QUEUE_END = 2;
private final HashSet<LooperObserver> observers = new HashSet<>(); //用于通知帧状态
private final long[] dispatchTimeMs = new long[4];//dispatchTimeMs 0,2位置为开始时间,0为纳秒,2为毫秒,1,3为结束时间
private volatile boolean isAlive = false;
private volatile long token = 0L; //消息执行开始时间,也用做token
private boolean isVsyncFrame = false; //frame开始标记
private TraceConfig config;
private Object callbackQueueLock; //用于同步
private Object[] callbackQueues; //队列数组,保存
private Method addTraversalQueue; //往绘制队列添加callback的方法
private Method addInputQueue;
private Method addAnimationQueue;
private Choreographer choreographer;//Choreographer机制,用于同vsync机制配合,统一动画,输入,绘制时机。
private Object vsyncReceiver; //获取了一个getIntendedFrameTimeNs vsync开始的时间,校对时间
private long frameIntervalNanos = 16666666;
private int[] queueStatus = new int[CALLBACK_LAST + 1]; //队列状态
private boolean[] callbackExist = new boolean[CALLBACK_LAST + 1]; //用于标记callback是否添加
private long[] queueCost = new long[CALLBACK_LAST + 1]; //每个队列花费时间
private boolean isInit = false; //是否init
private long[] frameInfo = null;//没用到
//endregion
//region step 1 init
public void init(TraceConfig config) {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
throw new AssertionError("must be init in main thread!");
}
this.config = config;
choreographer = Choreographer.getInstance();
//private final Object mLock = new Object(); 这是个同步锁,addFrameCallback会用到
callbackQueueLock = ReflectUtils.reflectObject(choreographer, "mLock", new Object());
// 回调队列 private final CallbackQueue[] mCallbackQueues;
callbackQueues = ReflectUtils.reflectObject(choreographer, "mCallbackQueues", null);
if (null != callbackQueues) {
// 反射,找到在 Choreographer内部类 CallbackQueue 上添加回调的addCallbackLocked方法
// 反射获取Choreographer中CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL三种类型的CallbackQueue的addCallbackLocked方法的句柄。
addInputQueue = ReflectUtils.reflectMethod(callbackQueues[CALLBACK_INPUT], ADD_CALLBACK, long.class, Object.class, Object.class);
addAnimationQueue = ReflectUtils.reflectMethod(callbackQueues[CALLBACK_ANIMATION], ADD_CALLBACK, long.class, Object.class, Object.class);
addTraversalQueue = ReflectUtils.reflectMethod(callbackQueues[CALLBACK_TRAVERSAL], ADD_CALLBACK, long.class, Object.class, Object.class);
}
//这个Receiver用来获取屏幕lcd硬件显示vsync信息
vsyncReceiver = ReflectUtils.reflectObject(choreographer, "mDisplayEventReceiver", null);
//每一帧的时间16ms的纳秒值
frameIntervalNanos = ReflectUtils.reflectObject(choreographer, "mFrameIntervalNanos", Constants.DEFAULT_FRAME_DURATION);
//向LooperMonitor注册Message执行开始的回调、执行结束的回调。这里的Message是指主线程中发生的所有Message,
//包括App自己的以及Framework中的,Choreographer中的自然也可以捕获到。
LooperMonitor.register(new LooperMonitor.LooperDispatchListener() {
@Override
public boolean isValid() {
return isAlive;
}
@Override
public void dispatchStart() {
super.dispatchStart();
UIThreadMonitor.this.dispatchBegin();
}
@Override
public void dispatchEnd() {
super.dispatchEnd();
UIThreadMonitor.this.dispatchEnd();
}
});
this.isInit = true;
MatrixLog.i(TAG, "[UIThreadMonitor] %s %s %s %s %s %s frameIntervalNanos:%s", callbackQueueLock == null, callbackQueues == null,
addInputQueue == null, addTraversalQueue == null, addAnimationQueue == null, vsyncReceiver == null, frameIntervalNanos);
if (config.isDevEnv()) {
addObserver(new LooperObserver() {
@Override
public void doFrame(String focusedActivity, long startNs, long endNs, boolean isVsyncFrame, long intendedFrameTimeNs, long inputCostNs, long animationCostNs, long traversalCostNs) {
MatrixLog.i(TAG, "focusedActivity[%s] frame cost:%sms isVsyncFrame=%s intendedFrameTimeNs=%s [%s|%s|%s]ns",
focusedActivity, (endNs - startNs) / Constants.TIME_MILLIS_TO_NANO, isVsyncFrame, intendedFrameTimeNs, inputCostNs, animationCostNs, traversalCostNs);
}
});
}
}
//endregion
//region step 4 dispatchBegin
private void dispatchBegin() {
token = dispatchTimeMs[0] = System.nanoTime(); //记录时间,dispatchTimeMs 0,2位置为开始时间
dispatchTimeMs[2] = SystemClock.currentThreadTimeMillis(); //记录时间
AppMethodBeat.i(AppMethodBeat.METHOD_ID_DISPATCH); //打个点
synchronized (observers) {
for (LooperObserver observer : observers) {
if (!observer.isDispatchBegin()) {
observer.dispatchBegin(dispatchTimeMs[0], dispatchTimeMs[2], token);
}
}
}
if (config.isDevEnv()) {
MatrixLog.d(TAG, "[dispatchBegin#run] inner cost:%sns", System.nanoTime() - token);
}
}
private void dispatchEnd() {
long traceBegin = 0;//用于devenv记录时间打log用
if (config.isDevEnv()) {//用于devenv记录时间打log用
traceBegin = System.nanoTime();//用于devenv记录时间打log用
}
long startNs = token;
long intendedFrameTimeNs = startNs;
if (isVsyncFrame) {
doFrameEnd(token);
intendedFrameTimeNs = getIntendedFrameTimeNs(startNs);//如果是vsyncframe的话,intendedFrameTimeNs代表vsync 帧的校对时间
}
long endNs = System.nanoTime();
synchronized (observers) {
for (LooperObserver observer : observers) {
if (observer.isDispatchBegin()) {
observer.doFrame(AppMethodBeat.getVisibleScene(), startNs, endNs, isVsyncFrame, intendedFrameTimeNs, queueCost[CALLBACK_INPUT], queueCost[CALLBACK_ANIMATION], queueCost[CALLBACK_TRAVERSAL]);
}
}
}
dispatchTimeMs[3] = SystemClock.currentThreadTimeMillis();
dispatchTimeMs[1] = System.nanoTime();
AppMethodBeat.o(AppMethodBeat.METHOD_ID_DISPATCH);
synchronized (observers) {
for (LooperObserver observer : observers) {
if (observer.isDispatchBegin()) {
observer.dispatchEnd(dispatchTimeMs[0], dispatchTimeMs[2], dispatchTimeMs[1], dispatchTimeMs[3], token, isVsyncFrame);
}
}
}
this.isVsyncFrame = false;
if (config.isDevEnv()) {//用于devenv记录时间打log用
MatrixLog.d(TAG, "[dispatchEnd#run] inner cost:%sns", System.nanoTime() - traceBegin);//用于devenv记录时间打log用
}
}
//endregion
//region step 2 onStart,初始化callbackExist,queueStatus,queueCost三个值,然后调用addFrameCallback CALLBACK_INPUT
// 归根结底就是向Choreograpger注册了一个回调(即UIThreadMonitor自身),这样下次Vsync信号来到时,
// 就会触发这个callback(即会执行UIThreadMonitor的 run方法 *****很重要*****,执行这个run即表明是vsync帧)。
@Override
public synchronized void onStart() {
if (!isInit) {
MatrixLog.e(TAG, "[onStart] is never init.");
return;
}
if (!isAlive) {
this.isAlive = true;
synchronized (this) {
MatrixLog.i(TAG, "[onStart] callbackExist:%s %s", Arrays.toString(callbackExist), Utils.getStack());
callbackExist = new boolean[CALLBACK_LAST + 1];//记录是否已经向该类型的CallbackQueue添加了Runnable,避免重复添加
}
//记录CallbackQueue中添加的Runnable的运行状态,分为默认状态(DO_QUEUE_DEFAULT)、已经添加的状态
// (DO_QUEUE_BEGIN)、运行结束的状态(DO_QUEUE_END)
queueStatus = new int[CALLBACK_LAST + 1];
//记录上面某种类型的Runnable的执行起始的耗时,这可以反映出当前这一次执行CallbackQueue里面的任务耗时有多久。
queueCost = new long[CALLBACK_LAST + 1];
// 这里首先会判断某种type类型的callback是否已经添加,UIThreadMonitor是否已经启动等等检查,
// 然后根据type取得需要invoke的方法句柄,然后调用该方法并设置callbackExist标志位。
addFrameCallback(CALLBACK_INPUT, this, true);
}
}
//endregion
//region step 3 addFrameCallback run
// addFrameCallback方法将一个Runnable(自己)插到了INPUT类型的CallbackQueue的头部。
// CallbackQueue是一个单链表组织起来的队列,里面按照时间从小到大进行组织。
private synchronized void addFrameCallback(int type, Runnable callback, boolean isAddHeader) {
if (callbackExist[type]) {
MatrixLog.w(TAG, "[addFrameCallback] this type %s callback has exist! isAddHeader:%s", type, isAddHeader);
return;
}
if (!isAlive && type == CALLBACK_INPUT) {
MatrixLog.w(TAG, "[addFrameCallback] UIThreadMonitor is not alive!");
return;
}
try {
synchronized (callbackQueueLock) {
Method method = null;
switch (type) {
case CALLBACK_INPUT:
method = addInputQueue;
break;
case CALLBACK_ANIMATION:
method = addAnimationQueue;
break;
case CALLBACK_TRAVERSAL:
method = addTraversalQueue;
break;
}
if (null != method) {
method.invoke(callbackQueues[type], !isAddHeader ? SystemClock.uptimeMillis() : -1, callback, null);
callbackExist[type] = true;
}
}
} catch (Exception e) {
MatrixLog.e(TAG, e.toString());
}
}
//执行run方法,代表这个消息是vsync frame消息
@Override
public void run() {
final long start = System.nanoTime();
try {
//执行run方法,代表这个消息是vsync frame消息
doFrameBegin(token);
doQueueBegin(CALLBACK_INPUT);
addFrameCallback(CALLBACK_ANIMATION, new Runnable() {
@Override
public void run() {
doQueueEnd(CALLBACK_INPUT);
doQueueBegin(CALLBACK_ANIMATION);
}
}, true);
addFrameCallback(CALLBACK_TRAVERSAL, new Runnable() {
@Override
public void run() {
doQueueEnd(CALLBACK_ANIMATION);
doQueueBegin(CALLBACK_TRAVERSAL);
}
}, true);
} finally {
if (config.isDevEnv()) {
MatrixLog.d(TAG, "[UIThreadMonitor#run] inner cost:%sns", System.nanoTime() - start);
}
}
}
private void doQueueBegin(int type) {
queueStatus[type] = DO_QUEUE_BEGIN;//设置queueStatus[type]状态为begin
queueCost[type] = System.nanoTime();//记录初始值时间
}
private void doQueueEnd(int type) {
queueStatus[type] = DO_QUEUE_END;//设置queueStatus[type]状态为end
queueCost[type] = System.nanoTime() - queueCost[type];//记录消耗的时间
synchronized (this) {
callbackExist[type] = false;//重置状态
}
}
//endregion
//region vsync相关的开始doFrameBegin doFrameEnd
private void doFrameBegin(long token) {
this.isVsyncFrame = true;
}
private void doFrameEnd(long token) {
doQueueEnd(CALLBACK_TRAVERSAL);
for (int i : queueStatus) {
if (i != DO_QUEUE_END) {
queueCost[i] = DO_QUEUE_END_ERROR;
if (config.isDevEnv) {
throw new RuntimeException(String.format("UIThreadMonitor happens type[%s] != DO_QUEUE_END", i));
}
}
}
queueStatus = new int[CALLBACK_LAST + 1];
addFrameCallback(CALLBACK_INPUT, this, true);
}
//endregion
//vsync开始的时间,校对时间
private long getIntendedFrameTimeNs(long defaultValue) {
try {
return ReflectUtils.reflectObject(vsyncReceiver, "mTimestampNanos", defaultValue);
} catch (Exception e) {
e.printStackTrace();
MatrixLog.e(TAG, e.toString());
}
return defaultValue;
}
}
5.LooperObserver 它是 Looper 的观察者,在 Looper 分发消息、刷新 UI、分发结束时回调,这几个回调方法也是 ANR、慢方法等模块的判断依据
//它是 Looper 的观察者,在 Looper 分发消息、刷新 UI 、vsync时回调,这几个回调方法也是 ANR、慢方法等模块的判断依据
public abstract class LooperObserver {
private boolean isDispatchBegin = false;
/**
* 消息分发前回调
*
* @param beginNs 开始纳秒单位的时间
* @param cp