前置条件
python调试环境 Eclipse(Version: Luna Release (4.4.0))+pydev(3.7.0)
UiAutomator 准备一个用于滑动被测试APP的UiAutomator用例并且此用例需要保证滑动时间大于10秒还需要在运行fps.py之前运行
手机需要root 第一步执行adb shell 第二步执行 su看到$变成#即可
谷歌提供的python类库地址:https://github.com/ChromiumWebApps/chromium/tree/master/build/android/pylib
运行效果以及关键代码的修改
运行效果
SurfaceStatsCollector.py需要修改的地方
把所有类似'dumpsys SurfaceFlinger --latency xxxx'的字符串改成您自己的比如下面com.s.xy/com.s.xy.mainacticity要换成你要测试的Activity。
results = self._adb.RunShellCommand(
'dumpsys SurfaceFlinger --latency com.s.xy/com.s.xy.mainacticity')
return not len(results)
原理分析
此图中的
数据的单位是纳秒,时间是以开机时间为起始点。
每一次的命令都会得到128行的帧相关的数据。
第一行数据,表示刷新的时间间隔refresh_period,我的机器打印出来的间隔期是:
16666666/1000/1000 = 16.67ms(毫秒)
那么剩下来127行的数据分为3部分,每一行的数据的每一列都代表一部分。
第一部分
这一部分的数据表示应用程序绘制图像的时间点。
第二部分
在SF(软件)将帧提交给H/W(硬件)绘制之前的垂直同步时间。
第三部分
在SF将帧提交给H/W的时间点,算是H/W接受完SF发来数据的时间点,绘制完成的时间点。
那么可以看出第一部分和第三部分类似,那么差异在于哪里?差异在于帧有延迟时间,从准备好绘制完成绘制的时间间隔就是帧延迟。
何为jank,即掉帧 。每一行都可以通过下面的公式得到一个值,该值是一个标准,我们称为jankflag,如果当前行的jankflag与上一行的jankflag发生改变,那么就叫掉帧
ceil((C - A) / refresh-period)
所以掉帧是一个状态。
此图中的
Result: Parcel(00069f3a ':...') 00069f3a位置的数值是不断变化的
总结
从上面的分析可知,要想获得获取fps值,需要3步:
1.adb shell dumpsys SurfaceFlinger --latency命令产生fps数据
2.通过service call SurfaceFlinger 1013 来得到当前帧的索引以及时间戳,设置为A = {indexA,timeA}
3.公式:
设上一次的数据为B = {indexB,timeB}
FPS = (indexA-indexB)/(timeA-timeB)
具体实现代码请参考
https://github.com/ChromiumWebApps/chromium/blob/master/build/android/pylib/perf/surface_stats_collector.py