Matrix-FrameTracer源码阅读

参考
Choreographer原理
View、Window、WindowManager---VSYNC信号

运行Matrix demo时, 进入到TestTraceMainActivity界面以后会展示当前的fps相关新, fps展示View是通过FrameDecorator来完成, 所以在阅读Matrix-FrameTracer模块的代码时, 围绕着FrameDecorator来进行.

FrameDecorator相关信息

// 展示fps信息
private FloatFrameView view;
/**
 * 何时被回调?
 * visibleScene: 当前Activity名
 * taskCost: 整个任务耗时
 * frameCostMs: 该帧耗时
 * droppedFrames: 消耗帧数
 * isContainsFrame: 是否属于帧刷新
 */
public void doFrameAsync(String visibleScene, 
                         long taskCost, 
                         long frameCostMs, 
                         int droppedFrames, 
                         boolean isContainsFrame);

涉及到的主要method:

1. new Matrix: Matric初始化
   -> 1.1 Plugin.init: 插件初始化 
1.1 Plugin.init: 插件初始化
   -> 1.1.1 new AnrTracer
   -> 1.1.2 new FrameTracer
   -> 1.1.3 new EvilMethodTracer
   -> 1.1.4 new StartupTracer
2. TracePlugin.start: 启动TracePlugin插件
   -> 2.1 UIThreadMonitor.getMonitor().init: UIThreadMonitor初始化
   -> 2.2 UIThreadMonitor.getMonitor().onStart()
   -> 2.3 frameTracer.onStartTrace()
2.1 UIThreadMonitor.init: UIThreadMonitor初始化
   -> 2.1.1 LooperMonitor初始化
   -> (1) 获取Choreographer实例
   -> (2) 反射获取Choreographer.mLock
   -> (3) 返回获取Choreographer.mCallbackQueues
   -> (4) 反射获取addInputQueue = Choreographer.callbackQueues[0]
   -> (5) 反射获取addAnimationQueue = Choreographer.callbackQueues[1]
   -> (6) 反射获取addTraversalQueue = Choreographer.callbackQueues[2]
   -> (7) 返回获取Choreographer.mFrameIntervalNanos
   -> 2.1.2 LooperMonitor.register注册Message事件分发的监听
2.1.1 LooperMonitor初始化
   -> 2.1.1.1 LooperMonitor.resetPrinter: hook Looper中的Printer
   -> 2.1.1.2 LooperMonitor.dispatch: Message事件分发
   -> 2.1.2.3 UIThreadMonitor.dispatchBegin: Message事件开始分发
   -> 2.1.3.4 UIThreadMonitor.dispatchEnd: Message事件结束分发
2.2 UIThreadMonitor.onStart
   -> (1) callbackExist = new boolean[CALLBACK_LAST + 1]
   -> (2) queueStatus = new int[CALLBACK_LAST + 1]
   -> (3) queueCost = new long[CALLBACK_LAST + 1]
   -> 2.2.1 UIThreadMonitor.addFrameCallback
   -> 2.2.2 UIThreadMonitor.run
   -> 2.2.3 UIThreadMonitor.doFrameBegin
   -> 2.2.4 UIThreadMonitor.doQueueBegin
   -> 2.2.5 UIThreadMonitor.doQueueEnd
2.3 frameTracer.onStartTrace
   -> 2.3.1 onAlive -> UIThreadMonitor.getMonitor().addObserver(this);
3. 帧刷新回调, Message事件回调
   -> 3.1 FrameTracer.dispatchBegin
   -> 3.2 FrameTracer.doFrame
   -> 3.3 FrameTracer.dispatchEnd
3.3 FrameTracer.doFrame
   -> 3.3.1 FrameTracer.notifyListener
   -> 3.3.2 FPSCollector.doFrameAsync

接下来围绕这些方法进行分析

1. Matrix初始化

private Matrix(Application app, PluginListener listener, HashSet plugins) {
    this.application = app;
    this.pluginListener = listener;
    this.plugins = plugins;
    AppActiveMatrixDelegate.INSTANCE.init(application);
    for (Plugin plugin : plugins) {
        // 各自插件的初始化, 这里主要分析TracePlugin.init的初始化
        plugin.init(application, pluginListener);
        pluginListener.onInit(plugin);
    }
}
  • 1.Matrix构造函数会对所有插件Plugin进行初始化, 这些插件就是MAtrix-demo在Application.onCreate中添加的Plugin
  • 2.这里主要分析FrameTracer, 而FrameTracer又与TracePlugin相关, 所以这里只分析TracePlugin.init方法
1.1 TracePlugin.init初始化
@Override
public void init(Application app, PluginListener listener) {
    super.init(app, listener);
    // 1.获取AnrTracer
    anrTracer = new AnrTracer(traceConfig);
    // 2.获取FrameTracer
    frameTracer = new FrameTracer(traceConfig);
    // 3.获取EvilMethodTracer
    evilMethodTracer = new EvilMethodTracer(traceConfig);
    // 4.获取StartupTracer
    startupTracer = new StartupTracer(traceConfig);
}
1.1.2 FrameTracer初始化
public FrameTracer(TraceConfig config) {
    this.config = config;
    // 一帧的耗时16ms
    this.frameIntervalMs = TimeUnit.MILLISECONDS.convert(UIThreadMonitor.getMonitor().getFrameIntervalNanos(), TimeUnit.NANOSECONDS) + 1;
    // fps上报时间阈值
    this.timeSliceMs = config.getTimeSliceMs();
    // fps监控是否打开
    this.isFPSEnable = config.isFPSEnable();
    // 一秒钟掉帧数量: 42帧为FROZEN
    this.frozenThreshold = config.getFrozenThreshold();
    // 一秒钟掉帧数量: 24帧为HIGH
    this.highThreshold = config.getHighThreshold();
    // 一秒钟掉帧数量: 3帧为NORMAL
    this.normalThreshold = config.getNormalThreshold();
    // 一秒钟掉帧数量: 9帧为MIDDLE
    this.middleThreshold = config.getMiddleThreshold();
    MatrixLog.i(TAG, "[init] frameIntervalMs:%s isFPSEnable:%s", frameIntervalMs, isFPSEnable);
    if (isFPSEnable) {
        // 添加FPS收集器
        addListener(new FPSCollector());
    }
}

TracePlugin与FrameTracer初始化完成之后, 接下来执行Application.onCreate调用的tracePlugin.start方法

2. TracePlugin.start
@Override
public void start() {
    super.start();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (!UIThreadMonitor.getMonitor().isInit()) {
                // 1.初始化UIThreadMonitor
                UIThreadMonitor.getMonitor().init(traceConfig);
            } 
            AppMethodBeat.getInstance().onStart();
            // 2.启动UIThreadMonitor
            UIThreadMonitor.getMonitor().onStart();
            anrTracer.onStartTrace();
            // 3.启动FrameTracer
            frameTracer.onStartTrace();
            evilMethodTracer.onStartTrace();
            startupTracer.onStartTrace();
        }
    };
    if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
        runnable.run();
    } else {
        MatrixHandlerThread.getDefaultMainHandler().post(runnable);
    }
}
2.1 UIThreadMonitor.init初始化
public void init(TraceConfig config) {
    if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
        throw new AssertionError("must be init in main thread!");
    }
    this.config = config;
    // 1.获取主线程的Choreographer
    choreographer = Choreographer.getInstance();
    // 2.反射获取Choreographer mLock变量
    callbackQueueLock = reflectObject(choreographer, "mLock");
    // 3.反射获取Choreographer mCallbackQueues变量
    callbackQueues = reflectObject(choreographer, "mCallbackQueues");
    // 4.反射获取处理input事件的CallbackQueue的addCallbackLocked方法
    addInputQueue = reflectChoreographerMethod(callbackQueues[CALLBACK_INPUT], ADD_CALLBACK, long.class, Object.class, Object.class);
    // 5.反射获取处理animation的CallbackQueue的addCallbackLocked方法
    addAnimationQueue = reflectChoreographerMethod(callbackQueues[CALLBACK_ANIMATION], ADD_CALLBACK, long.class, Object.class, Object.class);
    // 6.反射获取处理UI刷新的CallbackQueue的addCallbackLocked方法
    addTraversalQueue = reflectChoreographerMethod(callbackQueues[CALLBACK_TRAVERSAL], ADD_CALLBACK, long.class, Object.class, Object.class);
    // 7.反射获取frameIntervalNanos变量
    frameIntervalNanos = reflectObject(choreographer, "mFrameIntervalNanos");
    // 8.注册监听Message事件分发的回调
    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;
}

UIThreadMonitor初始化时会对其持有的静态变量LooperMonitor进行初始化.

2.1.1 LooperMonitor初始化
public LooperMonitor(Looper looper) {
    // 1.主线程的Looper
    this.looper = looper;
    // 2.向Looper中注入LooperPrinter, 获取事件执行的开始与结束的监听
    resetPrinter();
    // 3.添加IdleHandler
    addIdleHandler(looper);
}
2.1.1.1 LooperPrinter监听Message事件的开始与结束
public void println(String x) {
    if (null != origin) {
        origin.println(x);
    }
    if (!isHasChecked) {
        isValid = x.charAt(0) == '>' || x.charAt(0) == '<';
        isHasChecked = true;
        if (!isValid) {
            MatrixLog.e(TAG, "[println] Printer is inValid! x:%s", x);
        }
    }
    if (isValid) {
        // 利用Looper.loop方法中日志的打印, >开头表示事件开始进行, <开头表示结束
        dispatch(x.charAt(0) == '>', x);
    }
}

public class Looper {
    public static void loop() {
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
        }
        ...
        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }
    }
}

当Message事件开始和结束时会分别回调Printer.println方法, 并带上开始/结束的标识, 这里最终会调用到LooperMonitor.dispatch方法

2.1.1.2 LooperMonitor.dispatch事件分发
// isBegin: true: 事件开始, false: 事件结束
private void dispatch(boolean isBegin, String log) {
    for (LooperDispatchListener listener : listeners) {
        if (listener.isValid()) {
            if (isBegin) {
                if (!listener.isHasDispatchStart) {
                    // 分发开始
                    listener.onDispatchStart(log);
                }
            } else {
                if (listener.isHasDispatchStart) {
                    // 分发结束
                    listener.onDispatchEnd(log);
                }
            }
        } else if (!isBegin && listener.isHasDispatchStart) {
            listener.dispatchEnd();
        }
    }
}

当Message事件开始执行时, 会回调到LooperMonitor.dispatch方法, 这里的listener指向的就是在UIThreadMonitor.init中通过LooperMonitor.register注册的回调, 因此这里最终是会触发到UIThreadMonitor的dispatchBegindispatchEnd方法

2.1.1.3 UIThreadMonitor.dispatchBegin Message事件分发开始
private void dispatchBegin() {
    // 1.从开机到现在的毫秒数
    token = dispatchTimeMs[0] = SystemClock.uptimeMillis();
    // 2.当前线程运行的毫秒数
    dispatchTimeMs[2] = SystemClock.currentThreadTimeMillis();
    AppMethodBeat.i(AppMethodBeat.METHOD_ID_DISPATCH);
    synchronized (observers) {
        for (LooperObserver observer : observers) {
            if (!observer.isDispatchBegin()) {
                // 这里的observer指向的就是在FrameTracer.onStartTrace中通过addObserver
                // 注册回调事件
                observer.dispatchBegin(dispatchTimeMs[0], dispatchTimeMs[2], token);
            }
        }
    }
}
  • 1.Message执行之前, 记录了从开机到现在的毫秒数, 当前线程运行的毫秒数, 并将该参数通过observer.dispatchBegin回调时传入
  • 2.通过UIThreadMonitor.addObserver添加LooperObserver, 方法调用链可知FrameTracer.onStart时会向UITHreadMonitor注册一个LooperObserver.
  • 3.这里回调到FrameTracer.dispatchBegin暂不作分析.
2.1.1.4 UIThreadMonitor.dispatchEnd Message事件分发结束
private void dispatchEnd() {
    // 1.帧开始刷新
    if (isBelongFrame) {
        doFrameEnd(token);
    }
    // 2.start: 开机到Message开始执行之前的时间(毫秒数)
    long start = token;
    // 3.end: 从开机到Message执行结束的时间(毫秒数)
    long end = SystemClock.uptimeMillis();
    synchronized (observers) {
        for (LooperObserver observer : observers) {
            if (observer.isDispatchBegin()) {
                /**
                 * 4.具体到LooperMonitor.doFrame先不作分析, 这里只记录每个参数的含义:
                 * (1)token: 在dispatchBegin中被赋值, 记录的是开机到Message开始执行时的时长
                 * (2)SystemClock.uptimeMillis: 开机到Message执行结束的时间(毫秒数)
                 * (3)isBelongFrame: 这里只是一个标志位的作用
                 * (4)end-start: 对应一次Message消耗的时间
                 */
                observer.doFrame(AppMethodBeat.getVisibleScene(), token, SystemClock.uptimeMillis(), isBelongFrame ? end - start : 0, queueCost[CALLBACK_INPUT], queueCost[CALLBACK_ANIMATION], queueCost[CALLBACK_TRAVERSAL]);
            }
        }
    }
    // 5.当前线程执行的时间 
    dispatchTimeMs[3] = SystemClock.currentThreadTimeMillis();
    // 6.从开机到当前Message执行完毕的时间
    dispatchTimeMs[1] = SystemClock.uptimeMillis();
    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, isBelongFrame);
            }
        }
    }
}

dispatchTimeMs[0]: 从开机到Message执行开始的时间
dispatchTimeMs[1]: 从开机到Message执行完毕的时间
dispatchTimeMs[2]: Message执行开始时当前线程消耗的时间
dispatchTimeMs[3]: Message执行结束时当前线程消耗的时间

2.2 UIThreadMonitor.onStart 启动UIThreadMonitor
@Override
public synchronized void onStart() {
    if (!isAlive) {
        this.isAlive = true;
        synchronized (this) {
            callbackExist = new boolean[CALLBACK_LAST + 1];
        }
        // 1.开始/结束的标识
        queueStatus = new int[CALLBACK_LAST + 1];
        // 2.type对应的执行时间
        queueCost = new long[CALLBACK_LAST + 1];
        addFrameCallback(CALLBACK_INPUT, this, true);
    }
}
  • 1.这里分别定义三个参数, 应该是对应了input(输入事件)、animation(动画)、TRAVERSAL(窗口刷新)三个回调事件
2.2.1 UIThreadMonitor.addFrameCallback
private synchronized void addFrameCallback(int type, Runnable callback, boolean isAddHeader) {
    if (!isAlive && type == CALLBACK_INPUT) {
        return;
    }
    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) {
            // 1.method对应CallbackQueue.addCallbackLocked方法
            // 2.将callback(这里对应的是UIThreadMonitor)添加到CallbackRecord队列中
            method.invoke(callbackQueues[type], !isAddHeader ? SystemClock.uptimeMillis() : -1, callback, null);
                callbackExist[type] = true;
        }
    }
}
  • 1.这里涉及到的Choreographer, 关于Choreographer的篇幅比较大, 这里暂时只引用一点关于Choreographer的概念:
  • 2.当vsync信号由SurfaceFlinger中创建HWC触发, 唤醒DispSyncThread线程, 再到EventThread线程, 然后再通过BitTube直接传递到目标进程所对应的目标线程, 执行handleEvent方法
  • 3.经过一系列的调用, 最后会调用到CallbackRecord.run方法
  • 4.结合Matrix-FrameTracer模块的代码, 这里的CallbackRecord指向的是UIThreadMonitor, 因此当有vsync信号时, UITHreadMonitor.run方法会被触发
2.2.2 UIThreadMonitor.run
@Override
public void run() {
    final long start = System.nanoTime();
    // 1.帧刷新开始, isBelongFrame被置为true
    doFrameBegin(token);
    // 2.设置事件开始的状态
    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);
}
2.2.3 UIThreadMonitor.doFrameBegin
private void doFrameBegin(long token) {
    // 所以这里是一个标志位, 表示帧开始刷新
    this.isBelongFrame = true;
}
2.2.4 UIThreadMonitor.doQueueBegin
 private void doQueueBegin(int type) {
    // 1.设置事件type(input, animation, traversal)的状态
    queueStatus[type] = DO_QUEUE_BEGIN;
    // 2.设置事件开始时的时间
    queueCost[type] = System.nanoTime();
 }
2.2.5 UIThreadMonitor.doQueueEnd
private void doQueueEnd(int type) {
    // 1.记录事件结束的状态
    queueStatus[type] = DO_QUEUE_END;
    // 2.记录Message事件结束时花费的时间
    queueCost[type] = System.nanoTime() - queueCost[type];
    synchronized (this) {
        // 3.当前事件被移除
        callbackExist[type] = false;
    }
}
  • doQueueEnd执行完之后, 会将callbackExist[type]置为false, 这个是因为回收callbacks,加入对象池mCallbackPool,就是说callback一旦执行完成,则会被回收。
2.3 FrameTracer.onStartTrace FrameTracer启动
@Override
final synchronized public void onStartTrace() {
    if (!isAlive) {
        this.isAlive = true;
        onAlive();
    }
}

@Override
public void onAlive() {
    super.onAlive();
    // 添加监听, UIThreadMonitor.dispatchBegin、doFrame、dispatchEnd分别触发
    // FrameTracer: dispatchBegin、doFrame、dispatchEnd三个方法
    UIThreadMonitor.getMonitor().addObserver(this);
}

3. 事件回调

3.1 FrameTracer.dispatchBegin
public void dispatchBegin(long beginMs, long cpuBeginMs, long token) {
    // Message事件开始
    isDispatchBegin = true;
}
3.2 FrameTracer.dispatchEnd
public void dispatchEnd(long beginMs, long cpuBeginMs, long endMs, long cpuEndMs, long token, boolean isBelongFrame) {
    // Message事件结束
    isDispatchBegin = false;
}
3.3 FrameTracer.doFrame
/**
 * focusedActivityName: 当前Activity
 * start: 从开机到Message开始执行时的时间(毫秒数)
 * end: 从开机到Message执行结束的时间(毫秒数)
 * frameCostMs: end - start: 一帧消耗的时间
 * inputCostNs: 一帧input事件消耗的时间
 * animationCostNs: 一帧animation消耗的时间
 * traversalCostNs: 一帧traversal消耗的时间
 */
public void doFrame(String focusedActivityName, long start, long end, long frameCostMs, long inputCostNs, long animationCostNs, long traversalCostNs) {
    if (isForeground()) {
        notifyListener(focusedActivityName, end - start, frameCostMs, frameCostMs >= 0);
    }
}
3.3.1 FrameTracer.notifyListener
/**
 * 1.taskCostMs: 一次Message事件消耗的时间
 * 2.frameCostMs: 一帧消耗的时间
 * 3.是否为帧刷新: 结合UIThreadMonitor.doFrame可知, 如果是帧刷新, frameCostMs > 0,
 *               即isContainsFrame = true
 */
private void notifyListener(final String visibleScene, final long taskCostMs, final long frameCostMs, final boolean isContainsFrame) {
    long start = System.currentTimeMillis();
    synchronized (listeners) {
        for (final IDoFrameListener listener : listeners) {
            if (config.isDevEnv()) {
                listener.time = SystemClock.uptimeMillis();
            }
            // 1.一次Message消耗的时间, 理论上一帧需要的时间16ms, 因此这里的dropFrame是指
            //   一次Message事件消耗的帧数.
            final int dropFrame = (int) (taskCostMs / frameIntervalMs);
            listener.doFrameSync(visibleScene, taskCostMs, frameCostMs, dropFrame, isContainsFrame);
            if (null != listener.getExecutor()) {
                listener.getExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        // 2.这里只分析FPSCollector.doFrameAsync
                        listener.doFrameAsync(visibleScene, taskCostMs, frameCostMs, dropFrame, isContainsFrame);
                    }
                });
            }
        }
    }
}

dropFrame: 理论上一次Message需要的时间与一帧的时间相同为16ms, 因此dropFrame理论上取值应该为1, 因此dropFrame的值越大, 表明Message花费的时间越多, 掉帧也就越多.

3.3.2 FPSCollector.doFrameAsync
/**
 * droppedFrames: 一次Message事件消耗的帧数
 */
public void doFrameAsync(String visibleScene, long taskCost, long frameCostMs, int droppedFrames, boolean isContainsFrame) {
    super.doFrameAsync(visibleScene, taskCost, frameCostMs, droppedFrames, isContainsFrame);
    FrameCollectItem item = map.get(visibleScene);
    if (null == item) {
        item = new FrameCollectItem(visibleScene);
        map.put(visibleScene, item);
    }
    // 1.收集当前Activity消耗的时间
    item.collect(droppedFrames, isContainsFrame);
    if (item.sumFrameCost >= timeSliceMs) { // report
        // 2.上报之前通过remove对FrameCollectionItem进行重置
        map.remove(visibleScene);
        // 3.上报数据
        item.report();
    }
}
3.3.3 FrameCollectItem.collect
void collect(int droppedFrames, boolean isContainsFrame) {
    // 1.一帧需要的时间16.7ms
    long frameIntervalCost = UIThreadMonitor.getMonitor().getFrameIntervalNanos();
    // 2.总消耗时间
    sumFrameCost += (droppedFrames + 1) * frameIntervalCost / Constants.TIME_MILLIS_TO_NANO;
    // 3.总丢帧率
    sumDroppedFrames += droppedFrames;
    // 4.doFrameAsync回调次数, 回调一次表示一帧刷新结束
    sumFrame++;
    if (!isContainsFrame) {
        // 除过刷新帧事件外, 其他事件数
        sumTaskFrame++;
    }
    if (droppedFrames >= frozenThreshold) {
        dropLevel[DropStatus.DROPPED_FROZEN.index]++;
        dropSum[DropStatus.DROPPED_FROZEN.index] += droppedFrames;
    } else if (droppedFrames >= highThreshold) {
        dropLevel[DropStatus.DROPPED_HIGH.index]++;
        dropSum[DropStatus.DROPPED_HIGH.index] += droppedFrames;
    } else if (droppedFrames >= middleThreshold) {
        dropLevel[DropStatus.DROPPED_MIDDLE.index]++;
        dropSum[DropStatus.DROPPED_MIDDLE.index] += droppedFrames;
    } else if (droppedFrames >= normalThreshold) {
        dropLevel[DropStatus.DROPPED_NORMAL.index]++;
        dropSum[DropStatus.DROPPED_NORMAL.index] += droppedFrames;
    } else {
        dropLevel[DropStatus.DROPPED_BEST.index]++;
        dropSum[DropStatus.DROPPED_BEST.index] += (droppedFrames < 0 ? 0 : droppedFrames);
    }
}
3.3.4 FrameCollectItem.report 上报数据

每个页面监控的总时间超过预设阈值就进行上报

void report() {
    // 1.1秒内帧数
    float fps = Math.min(60.f, 1000.f * sumFrame / sumFrameCost);
    MatrixLog.i(TAG, "[report] FPS:%s %s", fps, toString());
    try {
        TracePlugin plugin = Matrix.with().getPluginByClass(TracePlugin.class);
        if (null == plugin) {
            return;
        }
        // 2.记录卡顿级别以及出现的次数
        JSONObject dropLevelObject = new JSONObject();
        dropLevelObject.put(DropStatus.DROPPED_FROZEN.name(), dropLevel[DropStatus.DROPPED_FROZEN.index]);
        dropLevelObject.put(DropStatus.DROPPED_HIGH.name(), dropLevel[DropStatus.DROPPED_HIGH.index]);
        dropLevelObject.put(DropStatus.DROPPED_MIDDLE.name(), dropLevel[DropStatus.DROPPED_MIDDLE.index]);
        dropLevelObject.put(DropStatus.DROPPED_NORMAL.name(), dropLevel[DropStatus.DROPPED_NORMAL.index]);
        dropLevelObject.put(DropStatus.DROPPED_BEST.name(), dropLevel[DropStatus.DROPPED_BEST.index]);
        // 3.记录卡顿级别及掉帧总次数
        JSONObject dropSumObject = new JSONObject();
        dropSumObject.put(DropStatus.DROPPED_FROZEN.name(), dropSum[DropStatus.DROPPED_FROZEN.index]);
        dropSumObject.put(DropStatus.DROPPED_HIGH.name(), dropSum[DropStatus.DROPPED_HIGH.index]);
        dropSumObject.put(DropStatus.DROPPED_MIDDLE.name(), dropSum[DropStatus.DROPPED_MIDDLE.index]);
        dropSumObject.put(DropStatus.DROPPED_NORMAL.name(), dropSum[DropStatus.DROPPED_NORMAL.index]);
        dropSumObject.put(DropStatus.DROPPED_BEST.name(), dropSum[DropStatus.DROPPED_BEST.index]);

        JSONObject resultObject = new JSONObject();
        resultObject = DeviceUtil.getDeviceInfo(resultObject, plugin.getApplication());

        resultObject.put(SharePluginInfo.ISSUE_SCENE, visibleScene);
        resultObject.put(SharePluginInfo.ISSUE_DROP_LEVEL, dropLevelObject);
        resultObject.put(SharePluginInfo.ISSUE_DROP_SUM, dropSumObject);
        resultObject.put(SharePluginInfo.ISSUE_FPS, fps);
        resultObject.put(SharePluginInfo.ISSUE_SUM_TASK_FRAME, sumTaskFrame);

        Issue issue = new Issue();
        issue.setTag(SharePluginInfo.TAG_PLUGIN_FPS);
        issue.setContent(resultObject);
        plugin.onDetectIssue(issue);

    } catch (JSONException e) {
        MatrixLog.e(TAG, "json error", e);
    } finally {
        sumFrame = 0;
        sumDroppedFrames = 0;
        sumFrameCost = 0;
        sumTaskFrame = 0;
    }
}

你可能感兴趣的:(Matrix-FrameTracer源码阅读)