zoukankan      html  css  js  c++  java
  • 深入浅出Android App耗电量统计

    前言

        在Android统计App耗电量比较麻烦,直至Android 4.4,它仍没公开“电量统计”API或文档……额,是的,仅没有公开,并不是没有。平时在手机“设置- 电量”看到的数据

        Image

        就是系统调用内部API的统计结果。

     

    基础概念

        1. 手机由众多“部件”组成,所谓“部件”是指:CPU,WIFI,GPS....所以,Android App消耗总电量为 App运行过程中,涉及各部件的消耗电量的总和。
        2. 假设运行App导致CPU运行,时间:t,CPU单位时间消耗电量:w,则App的CPU耗电量为:W = w*t,而有物理公式 W = U*I*t(U:电压值,I:电流值),在手机中,一般U恒定不变,所以,可以单独通过 Q(电容量,单位: mAh)= I * t 表示电量
     
    系统源码分析

        核心源码/packages/apps/Settings/src/com/android/settings/fuelgauge/PowerUsageSummary.java

        核心类

            - BatteryStatsImpl:提供App各部件运行时间。

            - PowerProfile:提供部件电流数值。

        问题

            - Android怎样存储与读取App耗电量信息(即:BatteryStatsImpl数据怎么来的?)

            - Android怎么存储部件电流数值(即:PowerProfile数据怎么来的?)

            - Android具体耗电量计算方法

     

        1. Android怎样存储与读取App耗电量信息

            (1)先看下PowerUsageSummary.java如何获取BatteryStatsImpl?

             Image(1)

            Image(2)

            Image(3)

            可见 BatteryStatsImpl 通过 系统服务“batteryinfo”获得。

         

            (2)系统服务“batteryinfo”是什么玩意呢?(见:BatteryStatsService.java

            Image(4)

            系统服务“batteryinfo”其实就是BatteryStatsService,而BatteryStatsService“唯一的”构造函数提供了一个很重要的信息:filename!

          

            (3)BatteryStatsService在哪里创建?filename是什么?(见:ActivityManagerService.java

            Image(5)

            filename文件是:/data/system/batterystats.bin,关于batterystats.bin,之前民间很多文章说它用作电池校正,但Android工程师Dianne Hackborn在google+上明确:

            Image(6)

            betterystats.bin文件仅仅是一个记录不同app使用电量的一个文件。

     

            (4)再看看 BatteryStatsImpl(String filename) 构造函数(见:BatteryStatsImpl.java

            Image(7)

            这里只做了些基本的初始化。真正载入betterystats.bin数据是在(ActivityManagerService.java)mBatteryStatsService.getActiveStatistics().readLocked();

            Image(8)

            Image(9)

     

            至此,Android怎样存储与读取App耗电量信息分析结束。

            总结:

            (1)ActivityManagerService 创建并初始化 BatteryStatsService,并传入耗电量记录文件batterystats.bin;

            (2)BatteryStatsService 在内部创建 BatteryStatsImpl 实例,并传入耗电记录文件batterystats.bin;

            (3)ActivityManagerService 执行 mBatteryStatsService.getActiveStatistics().readLocked();导致 BatteryStatsService 的 BatteryStatsImpl 加载batterystats.bin数据;

            (4)在PowerUsageSummary计算App耗电量时,PowerUsageSummary从BatteryStatsService 中获取BatteryStatsImpl 实例,从而获得App的相关数据。

     

        2. Android怎么存储部件电流数值

            (1)比较简单,见 PowerProfile.java

            Image(10)

            PowerProfile读取资源 com.android.internal.R.xml.power_profile,并把数据加载到sPowerMap。

     

            (2)com.android.internal.R.xml.power_profile在哪里?

            在官方文档《Power Profiles for Android》明确了power_profile.xml位置:device///frameworks/base/core/res/res/xml/power_profile.xml。

            下面是一个samsung的power_profile.xml

            Image(11)

            字段含义见《Power Profiles for Android》。

     

            (3)每个OEM厂商有自己独立的power_profile.xml配置

            官方文档表明:OEM厂商应该有自己的power_profile.xml,因为部件(如:cpu, wifi…)耗电量应与具体硬件相关,这个只有OEM厂商清楚……

            Image(12)

      

            (4)PowerProfile关键API:

            - public double getAveragePower(String type):返回type的电流值(mA),type表示power_profile.xml中的某关键字(如:gps.on)。

            - public double getAveragePower(String type, int level) :返回type的电流值(mA),level表示xml中array的第几个value。

     

            至此,Android怎么存储部件电流数值分析结束。

            总结:

            (1)Android部件电流信息存于:power_profile.xml

            (2)每个OEM厂商有私有power_profile.xml

            (2)PowerProfile读取power_profile.xml,并提供API访问部件电流数值。

     

        3. Android具体耗电量计算方法

            App耗电量统计:processAppUsage()  

            硬件耗电量统计:processMiscUsage()

     

            processAppUsage()分析

                【1】processAppUsage耗电量统计的 时间段 是?

                Image(13)

                Image(14)

                关于统计的 时间段,BatteryStats有4个选项:

                Image(15)

                可见,processAppUsage 是 上一次拔掉设备后 ~ 至今 的App耗电量统计。

              

                【2】processAppUsage 的统计对象真的是App?

                Image(16)

                具体的 统计流程 都在for循环里,额……所以processAppUsage真实统计粒度是Uid。

                Uid与App关系:2个App签名和sharedUserId相同,则在运行时,他们拥有相同Uid。就是说processAppUsage统计的可能是多个App的耗电量数据,对于普通App,出现这种情况的几率较少,而对于Android系统应用则较为常见。

     

                【3】耗电量计算公式 - 部分1:计算Uid属下每个Process的耗电量数据,并求和。

                Uid_Power1 = (Process1_Power + … + ProcessN_Power);

                Process_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);

                Image(17)

     

                【4】耗电量计算公式 - 部分2:计算Uid的wake lock耗电量

                这里,Android只计算了partial wake lock的耗电量。

                Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE

                Image(18)

     

                【5】耗电量计算公式 - 部分3:计算Uid的数据流量(data traffic)耗电量

                Uid_Power3 = ( tcpBytesReceived + tcpBytesSent ) * averageCostPerByte

                Image(19)

                Image(20)

     

                【6】耗电量计算公式 - 部分4:计算Uid WIFI耗电量。

                Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON

                Image(21)

     

                【7】耗电量计算公式 - 部分5:计算Uid其他传感器耗电量。

                Uid_Power5 = (Sensor1_Power + … + SensorN_Power)

                Sensor_Power = Sensor_Time * Power_Sensor

     

                至此,App耗电量计算方法分析结束。硬件耗电量统计(processMiscUsage())亦类似。

                总结App耗电量计算公式:

                    Uid_Power(App耗电量,单位:mAh) = Uid_Power1 + Uid_Power2 + Uid_Power3 + Uid_Power4 + Uid_Power5

                        Uid_Power1 = (Process1_Power + … + ProcessN_Power);

                            - Process_Power = (CPUSpeed_Time * POWER_CPU_ACTIVE);

                        Uid_Power2 = PartialWakeLock_Time * POWER_CPU_WAKE              

                        Uid_Power3 = ( tcpBytesReceived + tcpBytesSent ) * averageCostPerByte

                        Uid_Power4 = wifiRunningTimeMs * POWER_WIFI_ON

                        Uid_Power5 = (Sensor1_Power + … + SensorN_Power)

                            - Sensor_Power = Sensor_Time * Power_Sensor

     
                说这么多,来一发……不,来一个统计耗电量的App吧,其实,之前已有人把这段Android系统代码抠出来,做了一个App,可以到 这里下载
     
    --------------我是一个分割线--------------
     
                有一个好消息是:android5.0后,获取电量数据不用这么痛苦了,dumpsys batterystats数据中。包含:Estimated power use (mAh):,下面就是每个uid的耗电量,只要把app下所有uid耗电量加起来即可!
     
  • 相关阅读:
    js函数的Json写法
    Bootstrap3和Bootstrap4区别
    Unicode编码是什么
    保留字是什么
    范仁义js课程---5、js字面量和变量
    什么是脚本语言
    ECMAScript 版本
    TortoiseGit上传代码到GitHub
    Android Studio快捷键
    Android 适配
  • 原文地址:https://www.cnblogs.com/hyddd/p/4402621.html
Copyright © 2011-2022 走看看