PowerUsageSummary.java源码分析
在在线网站http://androidxref.com/上对Android版本6.0.1_r10源码进行分析
官方手机的应用耗电排行具体实现位置在:/packages/apps/Settings/src/com/android/settings/fuelgauge/PowerUsageSummary.java
PowerUsageSummary
类的作用是筛选耗电量最多的前十个应用并且展示
开始的一部分的UI界面的创建和一些常量的定义,比如:
USE_FAKE_DATA
,定义是否要使用假数据;private BatteryHistoryPreference mHistPref;
BatteryHistoryPreference类获取耗电量历史数据(读取sp文件)
sp文件数据来自power_usage_summary.xml
文件
PreferenceGroup
类:统计所有APP耗电量
主要目光放在refreshStats
方法里
跟进父类方法
BatteryStats.STATS_SINCE_CHARGED
传入的是我们的计算规则
- STATS_SINCE_CHARGED 上次充满电后数据
- STATS_SINCE_UNPLUGGED 拔掉USB线后的数据
mUm.getUserProfiles()
是传入的多用户
这也是由Android的安全机制导致的,即多用户下的多应用
mStatsHelper.refreshStats
方法现在我们只要知道是刷新当前的电量统计的就行
然后是一些UI的刷新,该部分略过
可以看到mStatsHelper
无处不在,实际上电量统计的核心实现就是该部分实现的
mStatsHelper.getPowerProfile()
获取电源的配置信息,浅跟进一下
初始化是在这里
持续跟进
可以看到这里有一段注释: Read the XML file for the given profile (normally only one perdevice
跟进readPowerValuesFromXml
方法,其实这个方法就是用来解析power_profile.xml
文件的,该文件在源码中的位置为 /frameworks/base/core/res/res/xml/power_profile.xml
,power_profile.xml
是一个可配置的功耗数据文件
在这里需要提一下Android中对于应用和硬件的耗电量计算方式:
有一张“价格表”,记录每种硬件1秒钟耗多少电。有一张“购物清单”,记录apk使用了哪几种硬件,每种硬件用了多长时间。假设某个应用累计使用了60秒的cpu,cpu1秒钟耗1mAh,那这个应用就消耗了60mAh的电
这里的价格表就是我们找到的power_profile.xml
文件,手机的硬件是各不相同的,所以每一款手机都会有一张自己的"价格表",这张表的准确性由手机厂商负责。
这也是为什么我们碰到读取xml文件的时候注释里面会有normally only one perdevice
如果我们想要看自己手机的power_profile.xml文件咋办,它会存储在手机的/system/framework/framework-res.apk
路径中,我们可以将它pull出来,通过反编译的手法获得power_profile.xml
文件
mStatsHelper.getStats()
返回BatteryStats
对象,跟进可以发现实际上返回的是BatteryStatsImpl
,它描述了所有与电量消耗有关的信息
见名知意,获取设备的平均耗电量,用于与阈值进行对比
这部分看上去是界面和主题的显示
检查消耗的电量是否大于阈值,以及是否使用假数据,否则不显示应用耗电量
根据UID进行合并分组
其中getCoalescedUsageList
方法对UID进行分组
getFakeStats()
方法返回一堆假数据
mStatsHelper.getUsageList()
返回BatterySipper数组,每个BatterySipper代表一个应用(uid)的消耗的电量信息
在BatteryStatsHelper.java
中的refreshStats
方法中对mUsageList
进行了赋值,这部分的具体操作在分析BatteryStatsHelper.java
的时候再提
这里的mStatsType
值为
这里我们前面提过,含义是
- STATS_SINCE_CHARGED 上次充满电后数据
- STATS_SINCE_UNPLUGGED 拔掉USB线后的数据
所以这段的含义是获取上次充满电之后的电量消耗
接下来遍历BatterySipper,对每一个UID代表的APP的耗电量进行过滤
如果耗电功率小于阈值则不进行显示
获取设备总耗电量
计算占用总耗电量的百分比
如果比例小于0.5,则不进行下一步操作
对某些情况进行过滤
进行UI界面的更新,其中也包含了获取应用的icon图标
获取当前应用的最大百分比,以及占总数的百分比
UI更新
其中这里对显示的数量进行了限制
MAX_ITEMS_TO_LIST
的赋值
循环外有对addedSome
的判断
实际上就是判断是不是有符合要求的耗电应用,如果没有的话,就显示一条提示信息
这部分就是PowerUsageSummary.java
文件获取Settings电池中显示的应用耗电量信息,根据我们上面的分析,实际上控制上面的continue就能获取全部已安装应用的耗电量。在Android的不同API版本中,会有一些适配的工作量
关于申请权限,普通应用是没有办法获取到应用耗电量信息的,系统会抛出异常
java.lang.SecurityException: uid 10089 does not have android.permission.BATTERY_STATS.
如果想要进行相关API的调用,首先应用需要配置android.uid.system
成为系统应用,并且进行系统签名,才能够拥有相关权限,本地编译的话需要调用Android的internal
接口,我使用的是替换本地android.jar才可以正常打包出apk文件
本地编写了一个获取Android应用耗电量的demo,运行截图如下
END
建了一个微信的安全交流群,欢迎添加我微信备注进群
,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 😃
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/17044945.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2020-01-11 espcms代码审计第一弹