本文主要分享Android应用耗电量的统计分析方法和工具。html
众所周知,Android系统内置了应用的耗电量统计分析功能,可是并无提供相应的API和文档,只是能够查看耗电量排行榜前10的应用的耗电百分比。此外,随着Android系统版本的迭代,各个版本耗电量统计的方式略有不一样,但庆幸的是其统计模型并无什么大变化。本文在前人的研究基础上总结Android平台的耗电量统计相关的计算方法和辅助工具。java
(1)Android系统是如何进行应用的耗电量统计的?python
若是想了解Android系统是如何对应用进行耗电量统计计算的话建议先阅读:Android耗电统计算法这篇文章,做者是小米的MIUI系统工程师Gityuan(若是你想了解Android系统中常见模块的实现细节的话,很是推荐阅读这位开发者的博客,他的博客文章的质量都很是高),此文从Android 6.0系统源码的角度详细分析了应用的耗电量的计算方法。阅读上文可知,耗电量计算包括软件耗电量计算和硬件耗电量计算,而且有各自的计算方法。linux
下图是软件的耗电量统计项以及它的功耗计算公式:android
下图是硬件的功耗计算公式:git
其余文章推荐:
1.深刻浅出Android App耗电量统计
该文是耗电量统计方面最先的文章,分析的是Android 4.3系统源码中的应用耗电量统计
2.Android应用的耗电量统计
该文是在上面的文章2的基础上作的分析,分析的是Android 5.1系统源码
3.Android性能专项测试之耗电量统计API
该文是以Android 6.0系统源码来分析应用耗电量统计github
下面是从源码的分析得出的对于电量统计的通俗介绍:面试
耗电量计算的方法颇有趣,有点象在超市购物:有一张“价格表”,记录每种硬件1秒钟耗多少电。有一张“购物清单”,记录apk使用了哪几种硬件,每种硬件用了多长时间。假设某个应用累计使用了60秒的cpu,cpu1秒钟耗1mAh,那这个应用就消耗了60mAh的电,实际的算法比这个例子复杂不少。算法
从这里能够看出,Android自带的耗电量统计的准确性,受两个大方面的因素影响:docker
一是那张“价格表”,由PowerProfile
类提供,它用于获取各个组件的电流数值,而power_profile.xml
是一个可配置的功耗数据文件。手机的硬件是各不相同的,因此每一款手机都会有一张本身的“价格表”。这张表的准确性由手机厂商负责,因此,尽可能用大厂的机子,而且只使用该厂商提供的Android系统。
二是那张“购物清单”,这是Android的BatteryStatsService
类提供的。前面那篇文章提到过,BatteryStatsHelper
类使用AIDL调用BatteryStatsService
类的getStatisticsStream
方法获取相关数据。
下面是其中几个模块的耗电量计算方式
WIFI模块的耗电量和应用流进流出的流量总量、wifi扫描时间、wifi模块运行时间有关
Sensor模块的耗电量与sensor的使用时间成正比
从上面几篇文章中能够看出,各个Android版本的系统源码中耗电量统计的方式虽略有不一样,可是大体的统计模型是不变的,并且统计的方式愈来愈科学可靠。Google官方对耗电量的统计给出的解释都是不能表明真实数据,只能做为参考值,由于受power_profile.xml的干扰太大,若是手机厂商没有严格设置这个文件,那可想而知出来的值多是不合理的。
(2)普通的应用开发者能够怎么统计应用的耗电量?
因为权限的限制,普通的应用开发者并不太容易统计应用的耗电量。前面的推荐文章3中也提到过获取应用耗电量的权限控制,内容以下:Android4.4之前的版本,未对耗电量统计的代码作权限限制,只须要使用java反射等手段,就能够调用相关的内部类和隐藏接口。自Android4.4开始,Android严格限制了权限,普通应用即便在AndroidManifest.xml中申明使用android.permission.BATTERY_STATS
,也获取不到相关的统计数据。
统计应用耗电量的工具:
1.GT的Powerstat (腾讯开发的应用耗电量统计工具)
项目地址:http://gt.tencent.com/
Powerstat的功能很强大,可是要求手机是root过的。
Powerstat用户手册中有说明:Android 电量测试工具 Powerstat V1.x 版本支持 Android4.1~4.4的系统(4.4及以上系统上须要系统签名,在已获取root权限的状况下,可将apk包置于/system/priv-app/
目录下,做为系统应用运行)。工具的 V1.x2 版本在V1.x 版本的基础上进行开发,细分耗电项,增长定时自动保存功能,适配Android5.0。一样,在 Android4.4 及以上系统也须要root权限才能安装使用。
Powerstat的应用耗电量计算方法基本上和系统的应用耗电量计算方法是同样的,它是经过各类方式包括反射的方法来获取应用在一段时间内的数据(例如占用的CPU时间、流进流出的数据量等),而后利用系统的统计类BatteryStatsHelper
作些修改来计算应用的耗电量。比较有意思的是其中有个用来计算应用的屏幕耗电量的类。为啥屏幕耗电量计算这么麻烦呢?由于在测试的过程当中测试应用并不是一直在前台,为了计算的应用耗电量准确些,须要将屏幕的总耗电量按照应用在前台的时间进行分配。计算方法就是根据屏幕总耗电量和全部应用的forground cpu time总和来计算每一个forground cpu time消耗的电量,并根据每一个应用占用的forground cpu time来计算其对应的屏幕耗电量。这个就相似统计一个应用占用的内存时咱们经常关注PSS,而不是USS的道理是同样的,共享库占用的内存要均摊到使用了它的每一个应用中。
2.Battery Historian (Google官方出品)
项目地址:https://github.com/google/battery-historian
Battery Historian是Google提供的针对Android 5.0及以上系统使用的分析电量相关信息的工具。
Battery Historian is a tool to inspect battery related information and events on an Android device running Android 5.0 Lollipop (API level 21) and later, while the device was not plugged in. It allows application developers to visualize system and application level events on a timeline with panning and zooming functionality, easily see various aggregated statistics since the device was last fully charged, and select an application and inspect the metrics that impact battery specific to the chosen application. It also allows an A/B comparison of two bugreports, highlighting differences in key battery related metrics.
目前BatteryHistorian工具备两个版本:
2.1 Battery Historian 1.x
第一个版本是python语言写的,只有一个Python脚本文件 historian.py,这个文件能够从初版本的最后一次提交记录中下载(https://github.com/google/battery-historian/tree/b711e0a8345147f449fd017e21913a8a6b8bd638) ,初版本的使用步骤以下:
$ adb shell dumpsys batterystats > xxx.txt //获得整个设备的电量消耗信息 $ adb shell dumpsys batterystats > com.package.name > xxx.txt //获得指定app相关的电量消耗信息
获得了原始的电量消耗数据以后,咱们须要经过 historian.py 脚本把数据信息转换成可读性更好的html文件
$ python historian.py xxx.txt > xxx.html
打开这个转换事后的html文件,能够看到相似TraceView生成的列表数据,其中的数据信息量很大
旧版本的详细使用流程以及分析过程能够参考Batterystats & Battery Historian Walkthrough 和 Battery Historian Charts,其中有些术语可能不太好理解,这里有个简略的中文的解释版本
下图很重要,它对不一样类别的电量消耗进行了解释
2.2 Battery Historian 2.x
第二个版本是go语言写的,代码不少,功能也更加完善,可是环境配置也更加复杂!
首先,咱们须要将Battery Historian工具在本地跑起来,要跑起来能够选择使用docker,也能够选择编译源码。
(1)若是是使用Mac或Linux平台的话,推荐直接经过docker运行Battery Historian来完成
docker -- run -p <port>:9999 gcr.io/android-battery-historian:2.1 --port 9999
以后在浏览器中输入 http://localhost: 就能够看到效果,而后上传bugreport文件进行分析了。
(2)若是是使用Windows平台的话,也可使用docker,可是机子要在BIOS中开启虚拟化,因此这里我选择源码编译方式,主要流程:
1.首先下载配置Java环境 (要配置PATH)
2.接着下载配置Git环境 (要配置PATH)
3.接着下载配置Python 2.7环境 (要配置PATH)
4.接着下载配置Go环境 (要配置PATH和GOPATH以及GOBIN)
5.前面的配置其实很快就能完成,接下来就是下载Battery Historian的源码来进行编译了
$ go get -d -u github.com/google/battery-historian/…
下载完成以后,代码会下载到配置的GOPATH中,能够去检查下
$ cd $GOPATH/src/github.com/google/battery-historian
切换到那个目录,而后执行setup.go开始编译源码
go run setup.go
若是遇到下面的问题的话别担忧,按照提示将对应url的文件下载下来放在要求的目录便可
上面的步骤都完成以后就能够启动Battery Historian了,默认端口是9999
$ go run cmd/battery-historian/battery-historian.go
待控制台输出listening on port:9999
的时候,能够打开浏览器输入 http://localhost:9999 就能够看到
其次,这个版本的输入是bugreport文件,根据系统版本不一样它的获取方式略有差异:
若是是Android 7.0及以上版本的话能够经过 adb bugreport bugreport.zip
来获取bugreport
若是是Android 6.0及如下版本的话能够经过 adb bugreport > bugreport.txt
来获取bugreport
获取到bugreport文件以后,咱们就能够将其上传到Battery Historian上进行分析,下面是它的输出结果
在页面的下方咱们能够查看这段时间内系统的状态system stats,也能够选择某个应用查看应用的状态app stats
其中咱们能够看到Device estimated power use
中显示了估算的应用耗电量值为 0.18%
Battery Historian还有个比较功能,在首页选择 Switch to Bugreport Comparisor,而后就能够上传两个不一样的bugreport文件,submit以后就能够看到它们的对比结果了,这个功能用来分析同一个应用的两个不一样版本先后的耗电量很是有用。
须要注意的是,通常开始统计数据以前须要使用下面的命令将之前的累积数据清空
adb shell dumpsys batterystats --reset
By default, Android does not record timestamps for application-specific userspace wakelock transitions even though aggregate statistics are maintained on a running basis. If you want Historian to display detailed information about each individual wakelock on the timeline, you should enable full wakelock reporting using the following command before starting your experiment:
adb shell dumpsys batterystats --enable full-wake-history
关于bugreport相关的知识推荐阅读Android adb bugreport工具分析和使用这篇文章,做者简单地从源码角度分析了adb bugreport
命令的运行原理,结论是bugreport实际上是启动了dumpstate服务来输出数据,其中数据来源包括:
1.系统属性
2./proc和/sys节点文件
3.执行shell命令得到相关输出
4.logcat输出
5.Android Framework Services信息基本使用dumpsys命令经过binder调用服务中的dump函数得到信息
下面是其余的几篇关于battery-historian使用的文章可供参考
(1)Android性能专项测试之battery-historian使用
(2)Android性能专项测试之Batterystats
(3)Battery Historian 2.0 for windows环境搭建
3.关于电量方面的Android性能优化
电量方面的性能优化能够参考 性能优化典范中的Android性能优化之电量篇
主要有如下两点:
(1)为了减小电量的消耗,在蜂窝移动网络下,最好作到批量执行网络请求,尽可能避免频繁的间隔网络请求
(2)使用Job Scheduler,应用须要作的事情就是判断哪些任务是不紧急的,能够交给Job Scheduler来处理,Job Scheduler集中处理收到的任务,选择合适的时间,合适的网络,再一块儿执行
Hujiawei is a mobile developer Guangdong, China https://hujiaweibujidao.github.io/本博客全部文章均为原创,请勿随意转载,如需转载请联系我 (hujiawei090807 AT gmail.com)我在小专栏有个移动开发技术专栏,不按期分享移动开发的核心技术,总结移动开发的实战经验
全部文章皆为原创,内容制做精良,保证干货满满,欢迎订阅 (https://xiaozhuanlan.com/u/javayhu)
>>> 我最近在Android面试指南小专栏里面写了一篇稿子 [Android面试——算法面试心得] ,欢迎阅读!<<<