通过 Battery Historian 工具分析 Android APP 耗电情况
电量统计模块概述
Android 从两个层面统计电量的消耗,分别为 软件排行榜 及 硬件排行榜。它们各有自己的耗电榜单,软件排行榜为机器中每个 App 的耗电榜单,硬件排行榜则为各个硬件的耗电榜单。这两个排行榜的统计是互为独立,互不干扰的。
具体的说,耗电信息在 设置 -> 电量
中能够非常直观的看到。注意,Android 所有功耗统计都是通过代码估算,没有集成电路参与汇报。准确度取决于厂商 ROM 所提供的 power_profile.xml
文件。由于不同厂商 power_profile.xml
准确度及源码有差异,因此不同手机、不同版本的数据可能有较大差异。
power_profile.xml
直接影响统计的准确度,并且此文件无法通过应用修改。再次强调,Android 耗电估算没有硬件的参与,全靠代码估算。
power_profile.xml
文件位于源码下的 /framework/base/core/res/res/xml/power_profile.xml
,部分内容展示如下:
- <item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
- <item name="gps.on">0.1</item> <!-- ~50mA -->
- <!-- Current consumed by the radio at different signal strengths, when paging -->
- <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
- <value>0.2</value> <!-- ~2mA -->
- <value>0.1</value> <!-- ~1mA -->
- </array>
- </array>
- <!-- Different CPU speeds as reported in
- /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
- <array name="cpu.speeds">
- <value>400000</value> <!-- 400 MHz CPU speed -->
- </array>
- <!-- Current when CPU is idle -->
- <item name="cpu.idle">0.1</item>
- <!-- Current at each CPU speed, as per 'cpu.speeds' -->
- <array name="cpu.active">
- <value>0.1</value> <!-- ~100mA -->
- </array>
- <array name="wifi.batchedscan"> <!-- mA -->
- <value>.0002</value> <!-- 1-8/hr -->
- <value>.002</value> <!-- 9-64/hr -->
- <value>.02</value> <!-- 65-512/hr -->
- <value>.2</value> <!-- 513-4,096/hr -->
- <value>2</value> <!-- 4097-/hr -->
- </array>
这就是在硬件层面统计时,直接参与运算的参数。无论是软件耗电统计还是硬件耗电统计,都通过 BatteryStatsHelper
来进行汇总。BatteryStatsHelper
位于 /framework/base/core/java/com/andorid/internal/os/BatteryStatsHelper.java
下。
软件耗电统计
在 BatteryStatsHelper.java
中,有这么一个方法:
- private void processAppUsage(SparseArray<UserHandle> asUsers) {
- final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null);
- mStatsPeriod = mTypeBatteryRealtime;
- BatterySipper osSipper = null;
- final SparseArray<? extends Uid> uidStats = mStats.getUidStats();
- final int NU = uidStats.size();
- for (int iu = 0; iu < NU; iu++) {
- final Uid u = uidStats.valueAt(iu);
- final BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, u, 0);
- mCpuPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mWakelockPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mMobileRadioPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mWifiPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mBluetoothPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mSensorPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mCameraPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
- final double totalPower = app.sumPower();
- if (DEBUG && totalPower != 0) {
- Log.d(TAG, String.format("UID %d: total power=%s", u.getUid(),
- makemAh(totalPower)));
- }
- }
- ... // code
- }
processAppUsage()
方法中,一个应用的总功耗在这里体现出来了:
cpu
Wakelock(保持唤醒锁)
无线电(2G/3G/4G)
WIFI
蓝牙
传感器
相机
闪光灯
这些数据,将决定着你的应用在耗电排行榜中的位置,以及是否给予用户警告高耗电。这些警告对于应用来说可能是致命的,用户可能因此而卸载应用。
应用总功耗是上述八个统计值的和。这八个统计器同继承自 PowerCalculator.java
具体来说,这八个耗电计算器的算法分别如下:
耗电统计概述就如上所述。总的来说并不复杂,通过聚合八种不同方式的消耗,来得出总的耗电量,并给予用户展示。
battery-historian
概述
bugreport
文件可视化。在第一代的 Battery Historian 中,google 使用了 python 作为数据解析工具。拿到 bugreport
文件后,通过终端执行 python 来生成可视化的 html 文件。这种方法使用起来较为麻烦,而且无法部署到服务器。因此在第二代 Battery Historian,google 选择了使用 docker 容器。现在完全不推荐使用第一代 Battery Historian,已经许久没有维护了,而且功能过于简陋。需要注意的是 battery-historian 在使用时候不能在充电,同时确保设备运行的 Android 版本是 5.0 及以上。
通过上面的描述,对 battery-historian 的功能有个大概的了解,下面进入到实战。
获取 bugreports
battery-historian 虽然功能强大,但是也是需要先提供数据的,其数据的获取需要我们手动操作。下面介绍如何获取 bugreports。
- 1. 电脑连接上手机,断开adb服务,adb作为一种连接的方式,有可能被其他的程序占用,所以我们做电量记录时要避免打开很多可能冲突的东西
- adb kill-server
- 2. 重启adb服务
- adb devices || adb start-server
3. Android也不记录特定于应用程序的用户空间wakelock转换的时间戳。如果您希望Historian在时间线上显示关于每个单独唤醒锁的详细信息,则应在开始实验之前使用以下命令启用完整唤醒锁报告:
- adb shell dumpsys batterystats --enable full-wake-history
4. 采集报告前将battery统计状态重置,重置命令结束后断开usb,测试结束后用获取报告命令导出统计文件包
- adb shell dumpsys batterystats --reset
- 5. 导出电量,对于 7.0 系统以上的设备运用:
- adb bugreport bugreport.zip
- adb bugreport > $HOME/Documents/bugreport.zip // 指定到对应目录下,具体分机型,可能会有些不一样
6.0 或更低版本:
- adb bugreport > bugreport.txt
数据分析
获取到数据后,接下去就是对数据进行分析了。
使用 battery-historian 是需要搭建环境的,由于搭建环境比较复杂, 可以借用别人搭好的线上环境:https://bathist.ef.lc/,点击打开后,上传数据,就会得到详细的结果。
如图所示Battery Historian图表的一个例子:
其中标号的意义是:
标号1:从下拉列表中添加其他指标;
标号2:将鼠标悬停在信息图标上可以查看有关每个指标的详细信息,包括图表中使用的不同颜色代表意义的介绍;
标号3:将鼠标悬停在某个条目上可以查看该指标的更多详细信息,以及时间线上特定点的耗电量信息;
这是整个手机状态图,包括手机电量,CPU 使用时长,wifi 信号的强度,手机温度变化等等,都在上面详细的用图表展示出来了。
Battery Historian除了能够提供宏观的系统层面的信息,还能够提供针对指定App的可视化数据和表格信息,这表格主要信息包括:
Device estimated power use等基本信息
Networks Information:app网络信息
Wakelocks:唤醒锁信息,一般和业务强相关
Services:服务信息,查看App开启的services信息
Process info:进程信息
Battery Historian图表下为数据分析,包括三个Tab,如下图所示,可以查看App更多信息:
其中,标号所代表的意义是:
标号1:System Stats 分组包含系统级别的数据,比如屏幕亮度等。这一栏显示了系统发生的总体情况,可以用来测试是否存在外部影响事件;
标号2:App Stats分组包含针对指定APP的详细信息;
标号3:可以根据不同的分类标准对APP进行排序;
标号4:在下拉列表中选择指定的APP后可在App Stats中查看具体信息,App Stats所展示的都是所选定App产生的数据,不会受到外部因素的影响;
下面看看具体某个手机的数据,比如百度APP应用的数据,在右边选择对应的 APP,左边就会展示当前 APP 的电量,网络等情况。
bugreport 文件分析
前面是通过 Battery History 对 bugreport 的文件进行了分析,那如果我们想自己分析呢?因此,在这里有必要了解下 bugreport 的文件内容。
- 电量统计信息起始,包含 reset 时间,进程信息等
- 下面是距离上次充电后的数据统计:
- 每个 APP 电量使用情况,通过 Uid 来标识APP
可以通过关键字下面的关键字来寻找相关信息。
- DUMP OF SERVICE
通过该关键字可以查到 wifi, 网络, activities 等等的信息。
参考文章
1、开发者大杀器 —— Battery Historian,刨根问底,揪出 Android App 耗电的元凶代码
2、Android耗电量 - bugreport & Battery Historian
通过 Battery Historian 工具分析 Android APP 耗电情况的更多相关文章
- Reveal UI 分析工具分析手机 App
上篇文章介绍了: Reveal UI 分析工具简单使用 这里介绍如何使用 Reveal UI 分析工具来进行手机 App UI 界面的分析. 前提准备: (1)已安装 Reveal 的 Mac (2) ...
- 转载----开发者大杀器 —— 刨根问底,揪出 Android App 耗电的元凶代码
转载文章地址:http://www.jianshu.com/p/27ba2759b221
- 【官网翻译】性能篇(四)为电池寿命做优化——使用Battery Historian分析电源使用情况
前言 本文翻译自“为电池寿命做优化”系列文档中的其中一篇,用于介绍如何使用Battery Historian分析电源使用情况. 中国版官网原文地址为:https://developer.android ...
- Android app启动耗时分析
前言 app启动耗时过长的话,无论你的app里面的内容多么丰富有趣,作为一个用户,首先是没有耐心去等待的,如果我是一个用户,我会这样想:这是什么垃圾公司出的什么烂app,再等2s不进来就卸载,黑人问号 ...
- Battery historian安装及使用
在介绍Battery historian之前首先来介绍一下 Android adb bugreport 工具,bugreport是什么,怎么用? android系统想要成为一个功能完备,生态繁荣的操作 ...
- Android 性能优化(26)*性能工具之「Batterystats,Battery Historian」Batterystats & Battery Historian Walkthrough
Batterystats & Battery Historian Walkthrough Working with Batterystats & Battery Historian B ...
- 电量分析工具 Battery Historian 的配置及使用
1.Building from source code(通过各种配置后从源码构建) 官方流程看似很麻烦,但一上手,很快就搞定,让我情何以堪. ps:以下均是参考官方及网友做的 copy https:/ ...
- Android APP性能分析方法及工具
近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...
- Android APP压力测试(一)之Monkey工具介绍
Android APP压力测试(一) 之Monkey工具介绍 前言 本文主要介绍Monkey工具.Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕.滑动. ...
随机推荐
- JavaScript事件:事件处理模型(冒泡、捕获)、取消冒泡、阻止默认事件
(一)事件处理模型---事件冒泡.捕获 (1)事件冒泡 24 <body> 25 <div class="warpper"> 26 <div clas ...
- hdu2333-贪心,如何去后效性,背包太大怎么办,如何最大化最小值,从无序序列中发掘有序性质
补充一下我理解的中文题意.. 你要重新组装电脑..电脑有一些部件..你的预算有b,b(1~1e9),有n个部件..每个部件有类型和名称以及价钱和质量现在你要在不超过预算b的情况下..每个类型都买一个部 ...
- Apple Screen Recorder All In One
Apple Screen Recorder All In One Apple macOS 自带录屏 QuickTime Player https://support.apple.com/zh-cn/g ...
- HTTPS in depth
HTTPS in depth HTTPS Hypertext Transfer Protocol Secure How does HTTPS work? https://www.cloudflare. ...
- CSS3 & gradient & color & background
CSS3 & gradient & color & background css background https://developer.mozilla.org/en-US/ ...
- 全网算力总量暴增,SPC能否成为币圈新宠?
据最新数据显示,在经历了本周初(1月11日)的下跌之后,比特币市场在本周四(1月14日)终于出现了反弹并试图突破4万美元,重新向4万美元上方发起挑战. 这也让加密市场的生态建设者重拾信心,重新对数字货 ...
- 【PY从0到1】 一文掌握Pandas量化基础
# 2[PY从0到1] 一文掌握Pandas量化基础 # Numpy和pandas是什么关系呢? # 在我看来,np偏向于数据细节处理,pd更偏向于表格整体的处理. # 要记住的pd内部的数据结构采用 ...
- npm与package.json快速入门
本文转载自npm与package.json快速入门 导语 npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解了一些,这次结合官方文章总结一下,加深下理解吧! 读完本 ...
- 微信小程序:picker组件实现下拉框效果
一.wxml中代码 <view class="in_order_Param"> <text>状态:</text> ...
- Vim的基本命令
Vi vi的两种模式 ①commad命令模式:无法输入任何东西,需要按下i进入编辑模式 ②edit编辑模式:按下esc退出到命令模式,在命令模式下按下wq [文件名] 可以退出并且成功的保存 //一些 ...