乐趣区

腾讯视频国际版(Android)电量测试方法研究与总结

本文由云 + 社区发表作者:腾讯移动品质中心 TMQ

1、研究背景:
在 2017 年 Google I/ O 大会上,Google 发布了 Google Play 管理中心的新功能:Android vitals。当 app 在大量设备上运行时,Android vitals 会收集与应用性能相关的各种匿名数据,比如:与 app 稳定性相关的数据、app 启动时间、电量使用情况、渲染时间以及权限遭拒等等,这些数据会被分析整理后展示在 Google Play 管理中心的 Android vitals dashboard 中。Android vitals 中需要开发者重点关注的核心指标有:crash 率、ANR 率、excessive wakeups(过渡唤醒)、stuck wake locks(唤醒锁定卡住)。其他指标,需根据应用类型选择性关注(Android vitals 中的指标总览见图 1 -1)。若 app 某些指标表现很差,会影响用户体验,并且会导致应用在 Google Play 商店中的等级很低、排名靠后(APP 指标异常示例图见图 1 -2)。开发者可以通过分析 Android vitals 中提供的一些参照指标,采取相应的措施来优化 app。

图 1 -1 Android vitals 平台检测指标总览

图 1 -2 某 APP 指标异常示例图
2、核心指标详细信息:
要对 APP 的指标进行监控,首先要明确该指标在 Android vitals 中是如何进行统计的,这一节主要介绍电量相关核心指标的基本概念和计算方式。
2.1 Stuck partial wake locks(部分唤醒锁定卡住)
A.WakeLock(唤醒锁)基本概念:
Android 系统本身为了优化电量的使用,会在没有操作时进入休眠状态, 来节省电量。为了便于开发(很多应用不可避免的希望在灭屏后还能运行一些事儿,或是要保持屏幕一直亮着 – 比如播放视频),Android 提供了一个 PowerManager.WakeLock 的东西。我们可以用 WakeLock 来保持 CPU 运行,或是防止屏幕变暗 / 关闭,让手机可以在用户不操作时依然可以做一些事儿。然而,获取 WakeLock 很容易,释放不好就会成为难题,消耗电量。
例如我们获取了一个 WakeLock 来保持 CPU 运转,做一个复杂运算并将数据上传到后台服务器, 然后释放该 WakeLock。然而这个过程可能并不像我们想象的那么快,可能因为比如服务器挂掉,计算出了异常等等 WakeLock 没有释放。问题就来了,CPU 会一直得不到休眠,而大大增加耗电。
唤醒锁可划分为并识别四种用户唤醒锁:

自 API 等级 17 开始,FULL_WAKE_LOCK 将被弃用。应用应使用 FLAG_KEEP_SCREEN_ON。
相关链接:https://developer.android.com…
B.Partial wake locks(部分唤醒锁):
部分唤醒锁可确保 CPU 正常运行,但屏幕和键盘背光可以关闭。如果运行在后台的 APP 长时间持有某个部分唤醒锁,就导致部分唤醒锁卡住。这种情况十分消耗设备电量,因为它会阻止设备进入低电量状态。Android vitals 重点关注了 stuck partial wake locks 这项指标,当你的 APP 存在唤醒锁定卡住的现象时,它会通过 Play 管理中心给出告警(APP 出现部分唤醒锁定卡住示例图见图 2 -1),并从各个维度给出相关的详细统计图(如图 2 - 2 中给出每个工作时段后台 wake lock 最长持续时间分布图)。当出现以下情况时,Android vitals 会报告唤醒锁定卡住:

至少 70% 以上的 battery sessions 发生过至少一次、长达一小时以上的部分唤醒锁定。
当只在后台运行时,至少 10% 以上的 battery sessions 发生过至少一次、长达一小时以上的部分唤醒锁定。

(ps:battery session 指两次电池充满电之间的时间间隔,Android vitals 展示的 battery sessions 是所有 app 测试用户的 battery session 合计。)
相关链接:https://developer.android.goo…

图 2 -1 某 APP 出现部分唤醒锁定卡住(后台)示例图

图 2 -2 每个工作时段后台 wake lock 最长持续时间的分布图
2.2 Excessive wakeups(过渡唤醒)
A.Wakeups 基本概念
Wakeups 是 AlarmManager API 中的一种机制,开发者可以设置一个 alarm 在特定的时间来唤醒设备。当某个唤醒 alarm 触发,设备会走出低电量模式,在执行 alarm 的 onRecieve()或 onAlarm()方法的时候,Alarm Manager 会持有一个部分唤醒锁。如果 wake alarms 频繁触发,会耗尽设备电量。Android vitals 中展示了 app 的过渡唤醒次数。
Alarm 有以下四种类型:
1)RTC_WAKEUP
在指定的时刻(设置 Alarm 的时候),唤醒设备来触发 Intent。
2)RTC
在一个显式的时间触发 Intent,但不唤醒设备。
3)ELAPSED_REALTIME
从设备启动后,如果流逝的时间达到总时间,那么触发 Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。
4)ELAPSED_REALTIME_WAKEUP
从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发 Intent。
在 Android vitals 中只列出了 RTC_WAKEUP 和 ELAPSED_REALTIME_WAKEUP 两种类型的唤醒数据,Google 会统计每小时发生 10 次以上 wakeup 的电池工作时段百分比(APP 发生过渡唤醒示例见图 2 -3)。分别从应用版本、wakeup 标记、设备、Android 版本等几个维度统计每小时的 Alarm Manager wakeup 次数(每个工作时段中每小时的 wackup 分布图见图 2 -4)。

图 2 -3 某 APP 发生过渡唤醒示例图

图 2 -4 每个工作时段每小时 wakeup 次数分布图
3、测试方法研究
3.1 传统电量测试方法回顾
我们之前也对腾讯视频主线版本进行过电量测试,之前关注的重点在于 APP 在各场景中耗电量是否正常,是从比较宏观的角度去进行测试的,采取的测试方法主要是物理仪器测试法和 GT 测试法。
A. 物理仪器测试法(电流表等)
在保持电压恒定的情况下,获取各场景平均电流值来统计系统耗电情况,通过此方法可以从大体上看出 APP 电量消耗是否正常,若仪器精度大,此方法测出的电量值是最准确的。
缺陷:此方法只能测试整个手机的电流,不能区分 APP,受影响的因素多,如屏幕亮度大小、音量大小等等,要保证每次测试的环境完全一致是不可能的。

图 3 -1 物理仪器测电量
B.GT 测试法
GT(随身调)是由 MIG 专项测试组自主研发的 APP 随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE, Integrated Debug Environment)。利用 GT,仅凭一部手机,无需连接电脑,您即可对 APP 进行快速的性能测试(CPU、内存、流量、电量、帧率 / 流畅度等等)、开发日志的查看、Crash 日志查看、网络数据包的抓取、APP 内部参数的调试、真机代码耗时统计等。
通过 GT,可以采集手机耗电量相关数据:电流、电压、电量、温度等,通过分析这些数据,可以对整个手机的电量使用情况进行分析。

缺点:和物理仪器测试方法一样,采用 GT 测试也只能获取到整个手机的电量数据,无法只关注单独 APP,且受各种因素影响较大。
3.2 国际版电量测试方法预研
由于国际版 APP 在 Google Play 上发布,我们做电量测试不仅仅需要关注整个 APP 的电量使用情况是否正常,还需要关注 APP 持有 wack lock 和使用 alarm 的情况。因此,传统的电量测试方法已经无法满足我们的需求,我们需要在此基础上增加额外的测试方法。
A.Batterystats/ bugreport
Android5.0 后,电量数据可通过 dumpsys batterystats 获取。Android 系统统计耗电量的基本公式是 W =UIt。在手机中,U 一般恒定不变,因此可以单独通过 Q(电容量)=I* t 来表示电量。核心类 BatterStatsImpl 提供 App 各部件运行时间、PowerProfile 提供部件电流数值。Android 部件电流信息存于:power_profile.xml 文件中,每个 OEM 厂商都有私有的 power_profile.xml 文件,PowerProfile 通过读取该文件获取访问部件电流数值(图 3 - 3 是 samsung 某型号的 power_profile.xml)。Android 系统以 uid 为单位,依次统计每个 apk 的使用 cpu 使用耗电量、wake lock 耗电量、移动数据耗电量、wifi 数据耗电量、wifi 维持耗电量、wifi 扫描耗电量、各传感器耗电量。其中 wake lock 消耗的电量只统计了持有 Partial wake lock 的耗电量,正好是我们需要关注的唤醒类型,因此我们可以通过分析 batterystats 获得的电量数据来测试 app 持有 Partial wake lock 情况。
Android 为了方便开发人员分析整个系统平台和某个 app 在运行一段时间之内的所有信息,专门开发了 bugreport 工具。bugreport 文件中记录了系统允许过程中的各种 log 信息,其中也包括了耗电量信息。通过分析 bugreport 中的电量相关数据也能获取 APP 持有 Partial wake lock 的信息。
ps:Uid 与 App 关系:2 个 App 签名和 sharedUserId 相同,则在运行时,他们拥有相同 Uid。就是说 processAppUsage 统计的可能是多个 App 的耗电量数据,对于普通 App,出现这种情况的几率较少,而对于 Android 系统应用则较为常见。

图 3 -2 wack lock 耗电量计算源代码

图 3 -3 sumsung 某型号 power_profile.xml
数据准备:
先断开 adb 服务,然后开启 adb 服务。
(1)adb kill-server
(2)adb start-server
由于开发时做电量记录时会打开很多可能造成冲突的东西,为了保险起见,重启 adb 命令。
重置电池数据、收集数据
(3) adb shell dumpsys batterystats –enable full-wake-history
(4) adb shell dumpsys batterystats –reset
(5) adb shell logcat -c
通过以上命令来打开电池数据的获取以及重置,清除干扰的数据,清除历史日志。
获取电量报告
把数据线拔掉,防止数据线造成充放电数据干扰。然后做一些测试的 case,经过一段时间后,重新连接手机确认 adb 连上了,运行以下命令来将 bugreport 的信息保存到 txt 文件中。
(6) adb bugreport >D:/bugreport.txt
或者用下面的命令也可以,官网上记述的内容,经实践,无法被读取…
(7) adb shell dumpsys batterystats > batterystats.txt
(8) adb shell dumpsys batterystats > com.example.app(包名) >batterystats.txt
ps:在此注意一定要等到该条命令执行完 (稍微会有些慢) 后,再打开 bugreport.txt 文件,之前遇到过没有导出完,就点开,信息缺失的情况,导致无法成功生成图表。
B.battery historian
生成的 bugreport 文件有的时候异常庞大,能够达到 15M+,想一想对于一个 txt 文本格式的文件内容长度达到了 15M+ 是一个什么概念,如果使用文本工具打开查看将是一个噩梦。因此 google 针对 android 5.0(api 21)以上的系统开发了一个叫做 battery historian 的分析工具,这个工具就是用来解析这个 txt 文本文件,然后使用 web 图形的形式展现出来,这样出来的效果更加人性化,更加可读。我们可以使用该工具对 bugreport 文件进行解析,更轻松的获取电量相关数据。
battery historian 的安装可以参考以下链接:
https://github.com/google/bat…
https://developer.android.com…
也可以直接使用在线版本:
https://bathist.ef.lc/
数据分析:
(1)选择腾讯视频 app

(2)Wacklocks 表格中展示 app 持有的 wacklock,持有时间及数量,通过这个表格我们可以看到我们 APP 是否有持有一小时以上的 wack_lock。

(3)Wakeup alarm info 表格中展示了 APP 运行过程中触发的 wakeup alarm 名字和个数,通过该分析工具也可以统计 app 的闹钟唤醒次数。

C.QAPM
QAPM 是 SNG 开发的致力于解放专项测试人员的工具平台,该平台带有电量监控功能,在电量个例菜单中会统计前台 30 分钟、后台 5 分钟两个场景下的 wacklock 持有信息。该平台上的数据可以作为我们电量测试的参考对象,具体的统计方法还需后续深入了解。

D.dumpsys 命令
Android 提供的 dumpsys 工具能够用于查看感兴趣的系统服务信息与状态,手机连接电脑后能够直接命令行运行 adb shell dumpsys 查看电池、电量相关信息。
adb shell dumpsys power

通过该条命令可以看到手机中所有的 wack_lock 持有信息
adb shell dumpsys alarm

此命令会提供设备上的 alarm 系统服务相关信息。其中 Alarm Stats 列出了应用设置 alarm 的情况,其中有系统被该应用所有 alarm 消耗的时间以及被闹钟唤醒的次数。可以通过获取一小时内的电量数据来分析用户在每小时的唤醒次数。
相关链接:https://blog.csdn.net/memoryj…
该方法与通过 burgreport 文件统计电量信息类似,都是通过 Android 系统中提供的工具来输出电量的消耗情况,且该种方式输出的报告也比较复杂,可读性查,可在测试过程中作为参考。
4、国际版电量测试方法总结与实践
4.1 测试方法总结

根据上一节的测试方法研究,我们打算首先用 GT 测试各个场景中 APP 电量消耗是否有异常。
接下来采用 battery historian 分析工具对手机里获取的 bugreport 文件进行分析,统计 app 中持有超过一小时的 wack_lock 和一小时内发生的 wackup 数。
QAPM 中采集到的数据作为我们的辅助分析数据,我们可以比较两份数据,看我们通过 battery historian 统计的 wack_lock 数据是否准确。
我们也可以通过使用 dumpsys 命令,查看 app 电量相关信息作为测试辅助方法。

4.2 测试方法实践
腾讯视频国际版 1.0.0 已经发布,我们已经使用该方法对其进行了一次电量测试,具体测试过程如下:
A.GT 测试:
测试场景:启动 - 播放 - 前台静置
测试机器:nexus
测试结果分析:

从以下电流趋势变化图中可以看出,播放过程和前台静置过程,电流曲线平稳,无较大波动,无明显异常。
从播放到退出播放前台静置,使用电流明显变小,符合预期。

B.Battery Historian 测试:
测试场景:

app 前台静置 2 小时
app 后台静置 2 小时
全屏播放 2 小时

测试型号:

Y7 Pro 2018(LDN-LX2)
OPPO F7(CPH1819)

测试结果分析:
三个场景中,仅播放场景下会持有 WindowManager 这个 wakelock 超过 1 小时以上。而 Android Vitals 中关注的是 app 运行在后台时,长时间持有部分唤醒锁的情况,播放这个场景可以排除在外,因此得出结论,国际版 APP 持有唤醒锁情况正常。

场景
机型
持有 1 小时以上的 wack lock

app 前台
华为 Y7 Pro 2018(LDN-LX2)

OPPO F7(CPH1819)

app 后台
华为 Y7 Pro 2018(LDN-LX2)

OPPO F7(CPH1819)

全屏播放
华为 Y7 Pro 2018(LDN-LX2)
WindowManager

OPPO F7(CPH1819)
WindowManager

2. 测试过程中没有统计到 alarm 数据,说明国际版 APP 暂时没有使用到 AlarmManager 定时任务。
C. 测试结论:
GT 电流测试显示国际版 APP 各应用场景电量使用情况正常。

场景
启动 APP
播放
退出播放,前台静置

结论
启动过程需加载图片等资源,电流较大,正常
播放过程电流平稳无异常
退出播放电流变小,静置过程平稳无异常

2. Battery Historian 分析电量数据得出,前台静置、后台静置、播放三个场景中仅播放场景会持有 wack lock1 小时以上,不属于 Android Vitals 统计范畴,不会影响到国际版 APP 在 Google Play 商店的排名。

场景
机型
stuck wake locks
excessive wakeups
结论

前台静置
华为 Y7 Pro
无唤醒锁定卡住
无过渡唤醒
正常

OPPO F7
无唤醒锁定卡住
无过渡唤醒
正常

后台静置
华为 Y7 Pro
无唤醒锁定卡住
无过渡唤醒
正常

OPPO F7
无唤醒锁定卡住
无过渡唤醒
正常

播放
华为 Y7 Pro
持有唤醒锁 1 小时以上
无过渡唤醒
正常

OPPO F7
持有唤醒锁 1 小时以上
无过渡唤醒
正常

5、总结与展望
由于腾讯视频国际版目前功能比较少,用到 wack_lock 和 alarm 的情况比较少,我们只测试了前台静置、后台静置、播放三个场景,电量测试的结果也显示 APP 电量使用情况正常,无部分唤醒锁定卡住和过渡唤醒的情况出现,后续国际版功能会日渐丰富,可能需要补充 push、下载等测试场景,持有 wack_lock 和 alarm 的情况也会更加复杂,因此我们会根据实际情况不断改进和完善我们的电量测试方法。
此文已由腾讯云 + 社区在各渠道发布
获取更多新鲜技术干货,可以关注我们腾讯云技术社区 - 云加社区官方号及知乎机构号

退出移动版