移动性能测试 [小记] Android 获取详细功耗

剪烛 for 平安科技 · 2017年09月13日 · 最后由 剪烛 回复于 2021年04月28日 · 9343 次阅读
本帖已被设为精华帖!

Android 系统 >= 5.0

清空耗电数据

adb shell dumpsys batterystats --reset

获取电量数据

adb shell dumpsys batterystats >battery.txt

battery.txt 各个数值的意义参考 https://developer.android.com/studio/profile/battery-historian-charts.html#FilteringBatterystats

其中关键词 Estimated power use(估算电量)下有具体 uid 的耗电,uid 根据文本头部通过进程名可以筛选到。

另外,根据 uid,还可以找到流量数据,alarm 和唤醒次数,等等。

比如:
第一行 70.0 为微信的耗电

Estimated power use (mAh):
    Capacity: 3900, Computed drain: 439, actual drain: 117-156
    Uid u0a166: 70.0 ( cpu=1.66 wake=1.69 radio=66.1 sensor=0.540 )
    Idle: 45.5
    Uid u0a84: 43.4 ( cpu=0.732 wake=0.000292 radio=1.02 gps=0.304 sensor=41.3 )
    Uid u0a15: 42.5 ( cpu=0.118 wake=0.120 radio=42.2 )
    Uid 0: 42.2 ( cpu=8.27 wake=7.58 radio=26.4 )
    Uid 1000: 26.8 ( cpu=8.09 wake=1.24 radio=16.8 gps=0.534 sensor=0.118 )
    Uid u0a298: 10.9 ( cpu=3.11 wake=4.49 radio=2.74 sensor=0.560 )

具体统计:

u0a166:
  Mobile network: 181.22KB received, 79.26KB sent (packets 488 received, 617 sent)
  Mobile radio active: 22m 2s 198ms (29.1%) 76x @ 1197 mspp
  Wake lock *alarm*: 2s 75ms partial (48 times) realtime
  Wake lock WakerLock:overflow: 2m 51s 280ms partial (220 times) realtime
  TOTAL wake: 2m 53s 355ms partial realtime
  Sensor 17: 2h 20m 58s 990ms realtime (0 times)
  Background for: 7h 33m 26s 672ms 
  Total running: 7h 33m 26s 672ms 

一段提取耗电量的脚本:

pkgName = "com.xx.xx"
ps = subprocess.Popen("adb shell dumpsys batterystats", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

uid = ""
uid_tag = False
power_tag = False
uid_re = '=(.+?):"{}"'.format(pkgName)
while True:
    line = ps.stdout.readline()
    if line:
        if "Battery History" in line:
            uid_tag = True
        if "Estimated power use (mAh):" in line:
            power_tag = True
    else:
        break

    if uid_tag:
        temp = re.findall('=(.+?):"{}"'.format(pkgName), line)
        if len(temp) > 0:
            uid = temp[0]
            print uid
            uid_tag = False
    if power_tag:
        temp = re.findall("Uid {}: (.+?) ".format(uid), line)
        if len(temp) > 0:
            print temp[0]
            power_tag = False

battery-historian

更详细的图表需要battery-historian下的/script/historian.py 生成图表。

python historian.py -a battery.txt > battery.html

这里生产的网页查看需要 ***,因为请求了一些 google 的 js 和 css,这里把需要的资料放网盘了。(这样本地化也方便集成到其他系统)

百度网盘

一共需要替换两个地方

  1. 资源中 jsapi 最后两行 writeLoadTag 方法中 load 资源的路径,改成自己的路径
oogle.loader.writeLoadTag("css", google.loader.ServiceBase + "/api/visualization/1.0/40ff64b1d9d6b3213524485974f36cc0/ui+zh_CN.css", false);
google.loader.writeLoadTag("script", google.loader.ServiceBase + "/api/visualization/1.0/40ff64b1d9d6b3213524485974f36cc0/dygraph,format+zh_CN,default+zh_CN,ui+zh_CN,timeline+zh_CN.I.js", false);
  1. battery-historian 生成的 html 文件,需要导入所有的资源(两个 css,两个 js,一个 jsapi)

比如:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['timeline']}]}"></script>

替换成:

<link href="/static/dataProcess/js/battery/tooltip.css" rel="stylesheet" type="text/css">
      <script src="/static/dataProcess/js/battery/jquery.min.js"></script>
      <script type="text/javascript" src="/static/dataProcess/js/battery/jsapi"></script>
      <link href="/static/dataProcess/js/battery/ui+zh_CN.css" type="text/css" rel="stylesheet">
      <script src="/static/dataProcess/js/battery/dygraph,format+zh_CN,default+zh_CN,ui+zh_CN,timeline+zh_CN.I.js" type="text/javascript"></script>

一切都可以写成 python 脚本~美滋滋(historian.py 中有很多可以拿来现成用的代码,建议可以看看)

目前刚开始做,准备集成到性能测试的自动化脚本中,求喷求建议

坑:
记录一个坑,在连接 usb 数据线的情况下,数据不会更新,数据不会更新,数据不会更新。必须拔掉数据线,才会开始记录。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 31 条回复 时间 点赞

剪烛进平安了?

哇噢,美滋滋

我这边也是这么处理的耗电量。dumpsys 的数据感觉不 reset 就不更新了。

思寒_seveniruby 将本帖设为了精华贴 09月14日 17:52

我记得我被这个工具坑过一次 忘记是什么原因了 貌似还不是 *** 查了半天才解决

剪烛 #31 · 2017年09月14日 Author

找到一个坑,连接 usb 数据线时,数据不会更新,必须拔线才能测功耗。இAஇ

陈恒捷 回复

இAஇ 是的是的是的

君河 回复

இAஇ感觉连着数据线就不更新

bauul 回复

இAஇ 还需要一些工作

这个必须马,回头试试

连着数据线出于充电状态 你可以通过命令关闭充电 只做连接再试试 不行的话就走 wifi 吧

最近也在看这个,这个就是要断开USB连接,连接时,不会被认为在消耗设备的电量

看 google 的文档也是要让断掉电源的

组里游戏测电量的现在是用的电流仪测试 iOS 的电量。这种方法测试来的电量是否要比电流仪要好一些?实践中的效果如何?

实践个人觉得还是电流仪更加接近用户真实耗电情况,一般 APP 运行都会或多或少的使用 wifi、数据业务喇叭传感器等等。单一抓某进程的耗电量 是否具有很好的参考性?

剪烛 #21 · 2017年09月18日 Author
卡斯 回复

இAஇ 貌似并不行

剪烛 #17 · 2017年09月18日 Author
codeskyblue 回复

இAஇ 这个只能测试 Android。觉得看需求吧。这种方法可以获取单独 app 的消耗,排除其他系统应用和屏幕的影响,而且操作比较简单。如果需要测试整机,并且需求更精确,还是上仪器吧。

剪烛 #18 · 2017年09月18日 Author
Zhhh 回复

估算的电量已经包含了 wifi,alarm,radio,这一些了。屏蔽的好像只有屏幕耗电。用仪器的话,确实更加接近用户的真实耗电,但是这个方法更加接近 app 的真实耗电。我觉得看测试的需求吧。

不是可以用命令屏蔽 USB 充电嘛

chen 回复

这个屏蔽充电的咋玩

求问这个 70.0 的单位是什么

niky 回复

mAh

codeskyblue 回复

用电流仪测试电量时是需要把 iOS 手机的后盖撬了,直接连接手机的电池线?

赞,学习了

清空耗电量记录,断 usb 设备,然后放置一段时间,用自带手机管家查看……这样比较靠谱

codeskyblue [该话题已被删除] 中提及了此贴 12月09日 16:17
codeskyblue 通过电池电量评测安卓 App 的耗电水平 中提及了此贴 12月09日 19:39

有个参数写错了

清空耗电数据
adb shell dumpsys batterystats --rest(reset)

剪烛 #25 · 2018年09月29日 Author
哄哄 回复

多谢,已改

谢谢剪烛,最近正在解读 bugreport,帮我找到了解决电量统计的地方。
我发现,bugreport 难的不是各种信息的解读,难的是找到关键字,因为 bugreport 文件实在是太大了

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

请问怎么知道 “Uid u0a166: 70.0 ( cpu=1.66 wake=1.69 radio=66.1 sensor=0.540 )” 这一行是微信的,Uid u0a166 怎么确定是微信啊

python2.7 historian.py -a battery.txt > battery.html
Traceback (most recent call last):
File "historian.py", line 1598, in
main()
File "historian.py", line 1347, in main
time_delta_s = parse_time(line_time, fmt) + time_offset
File "historian.py", line 107, in parse_time
d = match.groupdict()
AttributeError: 'NoneType' object has no attribute 'groupdict'

大佬,有没有办法在连接 usb 时更新电量数据

剪烛 #36 · 2021年04月28日 Author
huangwang 回复

听说可以在连接 USB 时,修改手机状态为不充电,来实现。但是没有尝试过,验证过,谨慎

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册