功耗优化 · 入门篇 · 浅析Android耗电量优化(2)

本文涉及的产品
应用实时监控服务-应用监控,每月50GB免费额度
简介: 功耗优化 · 入门篇 · 浅析Android耗电量优化

五. APM 耗电监控建设

影响App电量的因素有: 有屏幕, GPS,CPU,Radio,Video/Audio,Wifi 或蓝牙等

  • 那么我们该如何计算耗电量呢?
  • 怎么监控多进程,前后台等不同方式监测耗电情况呢?

手机系统耗电这块我们可以根据 /system/framework/framework-res.apk 的 power_profile.xml--文件进行耗电估算,里面的 value 值代表着不同类型设备发送不同动作的耗电系数: 如下图所示:

image.png

包括: BlueTooth , Wifi, Radio ,CPU 等

手机的系统耗电量 = CPU 毫秒数* 系数 1 + 流量 Bytes*系数 2 +....,当然不同类型参数是不一样的,应用也无法获取电量的具体细节

image.png

我们可以看一下 com.android.internal.os.BatteryStatsHelper 的关键方法 processAppUsage 里面按照 不同类型分别估算了不同服务耗电情况


  private void processAppUsage(SparseArray<UserHandle> asUsers) {
        final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null);
        mStatsPeriod = mTypeBatteryRealtimeUs;
        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, mRawRealtimeUs, mRawUptimeUs, mStatsType);
            mWakelockPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
            mMobileRadioPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs,
                    mStatsType);
            mWifiPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
            mBluetoothPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs,
                    mStatsType);
            mSensorPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
            mCameraPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, mStatsType);
            mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs,
                    mStatsType);
            mMediaPowerCalculator.calculateApp(app, u, mRawRealtimeUs, mRawUptimeUs, 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------
    }

至此: 我们也总结出影响 App 耗电的模块有如下几种情况

image.png

APM 耗电监控的关键就是需要定义全局参数估算 Location 时间, Alarm 次数,Net 访问量,wake_lock 持有时间,CPU 耗电情况等等~

耗电监控最大的难度在于:怎样通过 Hook wake_lock 持有长和 alarm 阀值 来预判 alarm 是否在做定时的重复任务,怎样通过 Hook 代理 LOCATION_SERVICE 实现 GPS 监控 ;


怎样通过 Hook 传感器的 SENSOR_SERVICE 中的“mSensorListeners”,拿到部分信息,最后才是通过埋点方案,在申请资源的时候将堆栈信息保存起来。当我们触发某个规则上报问题的时候,可以将收集到的堆栈信息、电池是否充电、电池的健康状态,CPU 信息、应用前后台时间等辅助信息也一起带上实现

整个耗电监控架构图如下: 利用多进程收集信息然后再传递给主进程,然后对耗电进行评估,最后再决定是否上报

image.png

那么我们怎么去监测手机的电量变化情况呢?

最核心的是通过广播来实现,在 BatterMannager 有六个比较核心的字段

字段 含义
STATUS_CHARGING 表示充电状态
STATUS_DISCHARGING 放电中
STATUS_NOT_CHARGING 未充电
STATUS_FULL 电池满
BATTERY_PLUGGED_AC 表示充电类型
BATTERY_PLUGGED_USB 表示 USB

电池的健康状态 也有一些七个比较核心的参数,他们返回一个 code, 这里我们也可以看一下:

字段 含义
BATTERY_HEALTH_UNKNOWN 未知
BATTERY_HEALTH_GOOD 良好
BATTERY_HEALTH_OVERHEA 过热
BATTERY_HEALTH_DEAD 没电
BATTERY_HEALTH_OVER_VOLTAGE 过电压
BATTERY_HEALTH_UNSPECIFIED_FAILURE 未知错误
BATTERY_HEALTH_COLD 过冷


基于这几点我们可以大胆预设做一套符合企业规则的耗电 APM 体系,

监控耗电本身也会带来更多耗电,那么我们该如何持续监控电池电量变化,其实我们真实环境是我们得找到低电量状态,如果手机电量过低自动关机,电池温度异常状态下监控并将数据上报,APM 管理系统可进行统计分析后,再通知手机做出电量补救措施,那么怎么看手机充电状态呢?可以参考以下代码

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatusIntent = registerReceiver(null, ifilter);
//如果设备正在充电,可以提取当前的充电状态和充电方式(无论是通过 USB 还是交流充电器),如下所示:
// Are we charging / charged?
int status = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
        status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
    if (usbCharge) {
        Toast.makeText(MainActivity.this, "手机正处于USB连接!", Toast.LENGTH_SHORT).show();
    } else if (acCharge) {
        Toast.makeText(MainActivity.this, "手机通过电源充电中!", Toast.LENGTH_SHORT).show();
    }
} else {
    Toast.makeText(MainActivity.this, "手机未连接USB线!", Toast.LENGTH_SHORT).show();
}

关于 Hook 方案就不多做介绍了,java 层一般使用动态代理加静态代理方案实现,其他插桩方式如: ASM,javasisit,AspectJ 亦可,native 可以考虑使用 weishu 的 arthoook 替换 native 方法,这个可以结合我的 Github 项目 BatteryCanary 进行代码分析

因为 在 Android P 之后,很多的 Hook 点都不支持了。 所以 APM 耗电监控变得异常艰辛曲折~

六. 总结

本文主要是通过我业余时间的技术调研,利用线下工具 Battery Historian 分析企业 app 电池发热问题,电池的信息电压温度充电状态,Device estimated power use 这几个指标是线下测试的关键指标


对于 Location 时间, Alarm 次数,Net 访问量,wake_lock 持有时间,CPU 耗电情况等等估算,我们可以埋点采集,指标采集核心思想还是 Hook 方案, APM 耗电建设是一个费力不讨好的工程,耗电监控相关代码我也从张绍文的 Matrix 仓库抽出来并进行源码分析注释,



相关实践学习
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
本场景将自定义告警信息同时分发至多个通知渠道的需求,例如短信、电子邮件及钉钉群组等。通过采用轻量消息队列(原 MNS)的主题模型的HTTP订阅方式,并结合应用实时监控服务提供的自定义集成能力,使得您能够以简便的配置方式实现上述多渠道同步通知的功能。
相关文章
|
2天前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
41 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
1月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
144 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
7月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
1583 77
|
5月前
|
缓存 编解码 Android开发
Android内存优化之图片优化
本文主要探讨Android开发中的图片优化问题,包括图片优化的重要性、OOM错误的成因及解决方法、Android支持的图片格式及其特点。同时介绍了图片储存优化的三种方式:尺寸优化、质量压缩和内存重用,并详细讲解了相关的实现方法与属性。此外,还分析了图片加载优化策略,如异步加载、缓存机制、懒加载等,并结合多级缓存流程提升性能。最后对比了几大主流图片加载框架(Universal ImageLoader、Picasso、Glide、Fresco)的特点与适用场景,重点推荐Fresco在处理大图、动图时的优异表现。这些内容为开发者提供了全面的图片优化解决方案。
204 1
|
11月前
|
XML 数据库 Android开发
探索Android开发:从入门到精通的旅程
在这篇文章中,我们将一起踏上一段激动人心的旅程,通过深入浅出的方式,解锁Android开发的秘密。无论你是编程新手还是有经验的开发者,本文都将为你提供宝贵的知识和技能,帮助你构建出色的Android应用。我们将从基础概念开始,逐步深入到高级技巧和最佳实践,最终实现从初学者到专家的转变。让我们开始吧!
229 3
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
180 20
Android经典面试题之图片Bitmap怎么做优化
|
12月前
|
存储 前端开发 测试技术
Android kotlin MVVM 架构简单示例入门
Android kotlin MVVM 架构简单示例入门
195 1
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
199 4
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
280 7
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
161 10