如何通过Battery Historian分析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下。

1.1、软件耗电统计

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

2.1、概述

Battery Historian ,是谷歌出品的耗电分析器。通过 Battery Historian,可将导出的 bugreport 文件可视化。在第一代的 Battery Historian 中,google 使用了 python 作为数据解析工具。拿到 bugreport 文件后,通过终端执行 python 来生成可视化的 html 文件。这种方法使用起来较为麻烦,而且无法部署到服务器。因此在第二代 Battery Historian,google 选择了使用 docker 容器。现在完全不推荐使用第一代 Battery Historian,已经许久没有维护了,而且功能过于简陋。

需要注意的是 battery-historian 在使用时候不能在充电,同时确保设备运行的 Android 版本是 5.0 及以上。

通过上面的描述,对battery-historian 的功能有个大概的了解,下面进入到实战。

2.2、获取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

2.3、数据分析

获取到数据后,接下去就是对数据进行分析了。

如图所示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 的电量,网络等情况。

2.4、bugreport 文件分析

前面是通过Battery History 对bugreport 的文件进行了分析,那如果我们想自己分析呢?因此,在这里有必要了解下bugreport 的文件内容。

电量统计信息起始,包含 reset 时间,进程信息等

下面是距离上次充电后的数据统计:

每个 APP 电量使用情况,通过 Uid 来标识APP

可以通过关键字下面的关键字来寻找相关信息。

DUMP OF SERVICE 

通过该关键字可以查到 wifi, 网络, activities 等等的信息。

以上就是如何通过Battery Historian分析Android APP耗电情况的详细内容,更多关于Battery Historian Android APP耗电情况的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android优化之电量优化的实现

    Android 5.0 后用 Battery Historian 工具分析电量. 耗电因素 移动网络请求 手机通过内置的射频模块和基站联系,从而链接上网的,而这个射频模块(radio)是非常耗电的,为了控制这个射频模块的耗电,硬件驱动及 Android RIL 层做了很多处理.例如可以单独关闭 radio(飞行模式),间歇性假休眠 radio(有数据发生时才上电,保持一个频率的与基站交互)等等.如今的 App 都是移动互联网 App,不可避免的会有大量的网络请求,会导致 radio 一直处于活跃

  • Android编程之电池电量信息更新的方法(基于BatteryService实现)

    本文实例讲述了Android编程之电池电量信息更新的方法.分享给大家供大家参考,具体如下: 电池的信息,电压,温度,充电状态等等,都是由BatteryService来提供的.BatteryService是跑在system_process当中,在系统初始化的时候启动,如下 在SystemServer.java中可以看到启动BatteryService的代码: Log.i(TAG, "Starting Battery Service."); BatteryService battery =

  • Android开发教程之电源管理详解

    本文实例讲述了Android电源管理.分享给大家供大家参考,具体如下: 一. 相关概念 1. 出于节电的需要,一般应用在用户一段时间无操作的情况下屏幕变暗,然后进入休眠状态 2. 用户只能在"设置->声音和显示"中设置所有应用默认的屏幕亮度和进行待机的时间 3. 电源管理的实现分内核应用两部分,通过下面介绍的接口,我们可以设置应用程序的电源管理,以控制与其休眠相关的状态(是否需要进入休眠,调整cpu频率,键盘灯的开关,屏幕的亮暗等) 二. 设置电源管理常用的几种状态 PARTIA

  • Android4.4开发之电池低电量告警提示原理与实现方法分析

    本文实例讲述了Android4.4电池低电量告警提示原理与实现方法.分享给大家供大家参考,具体如下: 之前版本的电池电量低是通过发送 intent ACTION_BATTERY_LOW来实现的,而在android4.4中,通过发送intent ACTION_BATTERY_CHANGED,也就是电池电量只要变化就检查是否需要低电量告警,并且实现挪到了PowerUI中. 路径: frameworks/base/packages/SystemUI/src/com/android/systemui/p

  • android电源信息查看(电量、温度、电压)实例代码

    本文实例讲述了android电源信息查看方法.分享给大家供大家参考.具体如下: 1. PowerTestActivity: import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os

  • Android电池电量跳变

    问题情形: 1.电量跳变到50% 2.电池ID脚接地 3.温度脚来判断电池是否在位 推测原因: 判断电池在位的方法: qpnp-linear-charger.c enum bpd_type{ BPD_TYPE_BAT_ID="bpd_id", BPD_TYPE_BAT_THM="bpd_thm", BPD_TYPE_BAT_THE_BAT_ID="bpd_thm_id", } 先在设备树查找bpd是否有值 of_property_read_str

  • Android省电的秘密之JobScheduler

    JobScheduler是Android L版本新引入的API,JobScheduler,顾名思义,是用来调度工作.工作被调度的条件包括网络变化,充电插拔,周期执行等.使用场景包括wifi条件下数据下载上传等等.谷歌为什么要引入这个新的API呢?是为了省电而制定的一种规范.想想如果每个开发者都利用这个API进行wifi网络下数据上传,数据上传的操作将会被统一到同一个时间点,批量处理,这样比许多应用单独唤醒要省电的多. 下面展示一个小例子 主MainActivity builder.setRequ

  • Android实现显示电量的控件代码

    下面介绍了Android实现显示电量的控件代码,具体代码如下: 1.目录结构,本人是使用安卓死丢丢. 2.运行界面,输入框中输入数值,点击刷新,会再电池中显示出相应的电量 3.绘制自定义电池控件,首先,新建一个类BatteryState继承View private Context mContext; private float width; private float height; private Paint mPaint; private float powerQuantity=0.5f;/

  • Android编程实现检测当前电源状态的方法

    本文实例讲述了Android编程实现检测当前电源状态的方法.分享给大家供大家参考,具体如下: 检测到现在在电源状态: IntentFilter mIntentFilter = new IntentFilter(); mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); registerReceiver(mIntentReceiver, mIntentFilter); //声明消息处理过程 private BroadcastReceiver

  • 如何通过Battery Historian分析Android APP耗电情况

    一.电量统计模块概述 耗电信息在设置 -> 电量中能够非常直观的看到.注意,Android 所有功耗统计都是通过代码估算,没有集成电路参与汇报.准确度取决于厂商 ROM 所提供的power_profile.xml文件.由于不同厂商power_profile.xml准确度及源码有差异,因此不同手机.不同版本的数据可能有较大差异. power_profile.xml直接影响统计的准确度,并且此文件无法通过应用修改.再次强调,Android 耗电估算没有硬件的参与,全靠代码估算. power_prof

  • 分析Android App中内置换肤功能的实现方式

    Android平台api没有特意为换肤提供一套简便的机制,这可能是外国的软件更注重功能和易用,不流行换肤.系统不提供直接支持,只能自行研究. 换肤,可以认为是动态替换资源(文字.颜色.字体大小.图片.布局文件--).这个使用编程语言来动态设置是可以做到的,例如使用View的setBackgroundResource.setTextSize.setTextColor等函数.但我们不可能在每个activity里对页面里的所有控件都通过调用这些函数来换肤,这样的程序代码难以维护.扩展,也违背了UI和代

  • Android APP性能优化分析

    本文通过Android APP性能优化的四个方面做了详细分析,并对原理和重点做了详细解释,以下是全部内容: 说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才感觉运行速度稍微提高了点,就算手机在各种性能跑分软件面前分数遥遥领先,还是感觉无论有多大的内存空间都远远不够用.相信每个使用 Android 系统的用户都有过以上类似经历,确实,Android

  • Android APP启动方式、启动流程及启动优化分析

    本文章向大家介绍Android app应用启动的一些相关知识,包括app启动方式.app启动流程和app启动优化等知识!  app应用启动方式 1.冷启动 当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动.冷启动因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量.布局.绘制),最后显示在界面上. 2.热启动 当启动应用时,后台已有该应用的进程(例:按

  • 亲自动手实现Android App插件化

    Android插件化目前国内已经有很多开源的工程了,不过如果不实际开发一遍,很难掌握的很好. 下面是自己从0开始,结合目前开源的项目和博客,动手开发插件化方案. 按照需要插件化主要解决下面的几种问题: 1. 代码的加载 (1) 要解决纯Java代码的加载 (2) Android组件加载,如Activity.Service.Broadcast Receiver.ContentProvider,因为它们是有生命周期的,所以要特殊处理 (3) Android Native代码的加载 (4) Andro

  • android app进行代码混淆实例详解

    接到一个新的任务,对现有项目进行代码混淆.之前对混淆有过一些了解,但是不够详细和完整,知道有些东西混淆起来还是比较棘手的.不过幸好目前的项目不是太复杂(针对混淆这块来说),提前完成--现总结之. 第一部分 介绍下操作流程(eclipse): 1.打开混淆器:找到项目根目录下的project.properties文件,将"#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt"

  • Android App开发中使用RecyclerView实现Gallery画廊的实例

    什么是RecyclerView         RecyclerView是Android 5.0 materials design中的组件之一,相应的还有CardView.Palette等.看名字我们就能看出一点端倪,没错,它主要的特点就是复用.我们知道,Listview中的Adapter中可以实现ViewHolder的复用.RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView.GridView以及瀑布流的效果. RecyclerVie

  • 深入解析Android App的LayoutInflate布局

    1. 题外话   相信大家对LayoutInflate都不陌生,特别在ListView的Adapter的getView方法中基本都会出现,使用inflate方法去加载一个布局,用于ListView的每个Item的布局.Inflate有三个参数,我在初学Android的时候这么理解的: (1)对于Inflate的三个参数(int resource, ViewGroup root, boolean attachToRoot): (2)如果inflate(layoutId, null )则layout

  • Android App内监听截图加二维码功能代码

    Android截屏功能是一个常用的功能,可以方便的用来分享或者发送给好友,本文介绍了如何实现app内截屏监控功能,当发现用户在我们的app内进行了截屏操作时,进行对图片的二次操作,例如添加二维码,公司logo等一系列*. 项目地址 测试截图: 截屏原理 android系统并没有提供截屏通知相关的API,需要我们自己利用系统能提供的相关特性变通实现.Android系统有一个媒体数据库,每拍一张照片,或使用系统截屏截取一张图片,都会把这张图片的详细信息加入到这个媒体数据库,并发出内容改变通知,我们可

  • Android App中实现图片异步加载的实例分享

    一.概述 一般大量图片的加载,比如GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等:那么异步消息处理可以用哪呢? 1.用于UI线程当Bitmap加载完成后更新ImageView 2.在图片加载类初始化时,我们会在一个子线程中维护一个Loop实例,当然子线程中也就有了MessageQueue,Looper会一直在那loop停着等待消息的到达,当有消息到达时,从任务队列按照队列调度的方式(FIFO,LIFO等),取出一个任务放入线程池中进行处理. 简易的一个流程:当

随机推荐