美团技术专栏: 关注MAYOU18
美团测试团队负责App的质量保证工做,平常除了App的功能测试之外,还会重点关注App的性能测试。如今你们对手机愈来愈依赖,而上面各App的耗电量,直接影响了手机的待机时间,是用户很是关心的一点。本文主要经过一个典型案例,介绍App性能测试中的电量测试,并总结了咱们由此引起的一些思考。html
短视频做为已被市场验证的新内容传播载体,能有效增长用户停留时长。大众点评App从9.3版本开始推出短视频相关内容,在各页面新增了短视频模块。在短视频功能测试中,咱们发现若是在视频列表页中播放视频,手机很快就会发烫。针对这种现象,咱们立刻拉取数据进行了分析,测试数据代表,视频列表页耗电量居然是详情页的11倍。这是怎么回事儿呢?
目前行业内有不少电量测试的方法,咱们采用的是Battery Historian,这是Google推出的一款Android系统电量分析工具,支持5.0(API 21)及以上系统手机的电量分析。java
短视频主要包括三个核心页面:视频列表页、视频详情页、做者页,本次的测试对象就是这三个页面。算法
![]() |
![]() |
![]() |
测试机型:华为Mate 9 Android 7.0
电池容量:4000mAh
播放的视频时长:1min15s
测试场景设计:WiFi环境下,打开App,播放视频,经过点击“从新播放”,连续播放10次
对比场景:停在App首页20min,手机不灭屏
注意:测试过程不充电,每次测试环境一致小程序
以下是Battery Historian测试结果部分截图:微信小程序
视频列表页微信
视频详情页ide
对测试结果数据进行汇总整理:函数
消耗电量:系统总电量的占比
从测试结果能够看到,短视频列表页耗电量特别高,是视频详情页的11倍。工具
视频列表页消耗电量太高,从测试数据能够很明显的看出来,视频列表页CPU占用时间高不少。从播放器布局来看,列表页和做者页比视频详情页只是多出了动画音符。以下图,红框中圈出的视频左下角的音符。布局
电量消耗差别这么大,是否跟动画音符有关呢。为了排除这个问题,从新编译了一个去掉动画音符的APK进行测试。测试结果:
从测试结果来看,CPU和耗电量很明显都降低了不少,所以肯定是动画音符引发的。打开GPU视图更新的开关,查看三个页面的绘制状况。打开视频列表页,能够看到,动画音符每波动一次,会致使整个页面都在不停的绘制。以下是视频列表页绘制的状况:
从动图能够很明显看出该页面绘制十分异常,动画音符每波动一次,会致使整个页面都从新绘制一遍。
因此,到这里就明白了问题的缘由,由于页面上动画音符的实现方式有问题,动画音符波动时,致使整个页面会跟着一块儿不停的从新绘制。而页面的重复绘制,会使App CPU占用比正常状况下高出不少,进而致使耗电量高。
定位到缘由以后,开发针对性的进行了修复。动画音符柱状图的实现,以前设计由多个可变化的单柱形View组成,单个柱形View重写了onMeasure & OnDraw方法,从外部柱状图View中初始化单个柱子的高度,而后自动根据一个函数式来变化高度。由于每次都须要层层调用Measure和对应的Layout,因此形成外层控件的屡次layout,进而形成CPU占用率增大。修复以后,使用另外一种方式实现,只重写了View的OnDraw方法,每次使用Canvas画出全部柱状图,使用ValueAnimator来计算变化柱状图高度,也再也不影响父控件的Layout。以下是修复先后的核心代码:
修复以后动画音符波动时的绘制区域:
修复以后,从新使用Battery Historian进行验证,测试结果:
从上面的测试结果,能够看到,视频列表页和做者页,耗电状况获得明显的优化。
总结一下,短视频耗电量的问题,是因为错误的绘制方法,致使CPU占用太高,进而致使耗电量高。那么由于动画音符致使耗电量异常的问题到这里就完美的解决了。CPU负载高,会致使耗电量高是显而易见的。可是还想深刻探索一下,在手机系统各App耗电量排行榜中,耗电量是怎么计算的?还有哪些因素会影响耗电量呢?带着这些疑问,咱们来看看系统计算耗电量的原理。
根据物理学中的知识,功=电压*电流*时间,可是一部手机中,电压值U正常来讲是不会变的,因此能够忽略,只经过电流和时间就能够表示电量。模块电量(mAh)=模块电流(mA)*模块耗时(h)。模块耗时比较容易理解,可是模块电流怎样获取呢,不一样厂商的手机,硬件不一样,是否会影响模块的电流呢。看一下系统提供的接口:./frameworks/base/core/java/com/Android/internal/os/PowerProfile.java
该类提供了public double getAveragePower(String type)接口,type可取PowerProfile中定义的常量值,包括POWER_CPU_IDLE(CPU空闲时),POWER_CPU_ACTIVE(CPU处于活动时),POWER_WIFI_ON(WiFi开启时)等各类状态。而且从接口能够看出来,每一个模块的电流值,是从power_profile.xml文件取的值。PowerProfile.java只是用于读取power_profile.xml的接口而已,后者才是存储系统耗电信息的核心文件。power_profile.xml文件的存放路径是/system/framework/framework-res.apk。
以Nexus 6P为例,在该路径获取到framework-res.apk文件。使用apktool,对framework-res.apk进行反解析,获取到手机里面的power_profile.xml文件,内容以下所示:
<?xml version="1.0" encoding="utf-8"?> <device name="Android"> <item name="none">0</item> <item name="screen.on">169.4278765</item> <item name="screen.full">79.09344216</item> <item name="bluetooth.active">25.2</item> <item name="bluetooth.on">1.7</item> <item name="wifi.on">21.21733311</item> <item name="wifi.active">98.04989804</item> <item name="wifi.scan">129.8951166</item> <item name="dsp.audio">26.5</item> <item name="dsp.video">242.0</item> <item name="gps.on">5.661105191</item> <item name="radio.active">64.8918361</item> <item name="radio.scanning">19.13559783</item> <array name="radio.on"> <value>17.52231575</value> <value>5.902211798</value> <value>6.454893079</value> <value>6.771166916</value> <value>6.725541238</value> </array> <array name="cpu.speeds.cluster0"> <value>384000</value> <value>460800</value> <value>600000</value> <value>672000</value> <value>768000</value> <value>864000</value> <value>960000</value> <value>1248000</value> <value>1344000</value> <value>1478400</value> <value>1555200</value> </array> <array name="cpu.speeds.cluster1"> <value>384000</value> <value>480000</value> <value>633600</value> <value>768000</value> <value>864000</value> <value>960000</value> <value>1248000</value> <value>1344000</value> <value>1440000</value> <value>1536000</value> <value>1632000</value> <value>1728000</value> <value>1824000</value> <value>1958400</value> </array> <item name="cpu.idle">0.144925583</item> <item name="cpu.awake">9.488210416</item> <array name="cpu.active.cluster0"> <value>202.17</value> <value>211.34</value> <value>224.22</value> <value>238.72</value> <value>251.89</value> <value>263.07</value> <value>276.33</value> <value>314.40</value> <value>328.12</value> <value>369.63</value> <value>391.05</value> </array> <array name="cpu.active.cluster1"> <value>354.95</value> <value>387.15</value> <value>442.86</value> <value>510.20</value> <value>582.65</value> <value>631.99</value> <value>812.02</value> <value>858.84</value> <value>943.23</value> <value>992.45</value> <value>1086.32</value> <value>1151.96</value> <value>1253.80</value> <value>1397.67</value> </array> <array name="cpu.clusters.cores"> <value>4</value> <value>4</value> </array> <item name="battery.capacity">3450</item> <array name="wifi.batchedscan"> <value>.0003</value> <value>.003</value> <value>.03</value> <value>.3</value> <value>3</value> </array> </device>
从文件内容中能够看到,power_profile.xml文件中,定义了消耗电量的各模块。以下图所示:
文件中定义了该手机各耗电模块在不一样状态下的电流值。刚刚提到,电量只跟电流值和时间相关,因此经过这个文件,再加上模块的耗时,就能够计算出App消耗的电量,App电量=∑App模块电量。划重点,手机系统里面的电量排行,也是根据这个原理计算的。
了解原理对于日常在App耗电量的测试有很大的帮助。由于获取到手机power_profile.xml文件,就能够清楚的知道这个手机上,哪些模块会耗电,以及哪些模块在什么状态下耗电量最高。那么测试的时候,应该重点关注调用了这些模块的地方。好比App在哪些地方使用WiFi、蓝牙、GPS等等。
例如最近对比测试其余App发现,在一些特定的场景下,该App置于前台20min内,扫描了WiFi 50次,这种异常会致使App耗电量大大增长。而且反过来,当有case报App耗电量异常时,也能够从这些点去考虑,帮助定位问题。
如上,列出的一些经常使用的电量测试方法。综合各方法的优缺点,在定制个性化电量测试工具以前,目前采用的方法是Battery Historian。目前行业内,App耗电测试有不少种方案,若是仅仅测试出一个总体的电量值,对于定位问题是远远不够的。借助Battery Historian,能够查看自设备上次充满电以来各类汇总统计信息,而且能够选择一个App查看详细信息。因此QA的测试结果反馈从“这个版本App耗电量”高,变成“这个版本CPU占用高”“这个版本WiFi扫描异常”,能够帮助更快的定位到问题缘由及解决问题。
固然,除了测试方法和测试工具,测试场景设计也很是重要。若是是在App内毫无规律的浏览,即便发现页面有问题,有很难定位到是哪一个模块的问题。因此要针对性的设计场景,而且进行一些场景的对比,找出差别的地方。
本文主要经过一个案例,介绍关于App电量测试中使用的一些基本方法和思路。电量测试采用的Battery Historian方法,虽然能初步解决问题,可是在实际的应用场景中还存在不少不足。目前美团云测平台,已经集成了电量测试方法,经过自动化操做,获取电量测试文件并进行解析,极大的提升了测试效率。目前每一个版本发布以前,咱们都会进行专门的电量测试,保障用户的使用体验。在电量测试方面,美团测试团队还在持续的实践和优化中。
倩云,美团客户端测试开发工程师,2015年加入美团,主要负责大众点评App基础功能及Android专项测试工做。
点评平台技术部-平台质量中心,Base上海,主要负责大众点评平台入口和基础功能的质量保障。平台包括大众点评App、大众点评微信小程序、PC站:www.dianping.com、M站:m.dianping.com;主要业务涵盖:帐号、POI、评价、视频、文章、会员社区、问答、运营活动、搜索推荐、通讯链路、运营活动等基础业务。热忱期待各位QA、开发、算法人才加入点评平台技术部。联系邮箱:wanxia.wang#dianping.com。