Android性能专项测试之耗电量统计API
2015-11-25 11:30
656 查看
目录(?)[+]
参考文章:Android应用的耗电量统计
深入浅出Android App耗电量统计
Battery stats - CPU total vs CPU foreground
深入浅出 Android App 耗电量统计
浅析Wakelock机制与Android电源管理
其中计算耗电量的方法为490行的
方法的参数是一个
然后判断该次计算是否针对所有用户,通过
然后给公共变量int类型的
这里面用到了
首先创建一个
然后
系统服务, 硬件类型,所以这个地方传入的是
列举了目前可计算耗电量的模块。
其中
这一部分我一会单独拿出来挨个解释,现在我们还是回到
然后根据是否是DEBUG版本打印信息,这个没啥可说的,然后会把刚才计算的电量值添加到列表中:
首先判断
如果我们的系统是单用户系统,且当前的
最后判断
主流程我们已经介绍完了,下面来看各个子模块耗电量的计算
Cpu的计算要用到PowerProfile类,该类主要是解析power_profile.xml:
这个里面存储了Cpu(cpu.speeds)的主频等级,以及每个主频每秒消耗的毫安(cpu.active),好,现在回到
第一步获得
首先得到
上面的代码就是将不同主频的消耗累加到一起,但是其中值得注意的是,他并不是用各个主频的消耗时间*主频单位时间内消耗的电量,而是用一个radio变量来计算得到各个主频段执行时间占总时间的百分比,然后用
上面统计同一
最后的最后,将耗电量用mAh单位来表示,所以在毫秒的基础上除以
总结:
从构造方法开始,
首先得到
首先获得
我们去
知道对应的xml的属性后我们直接看
这里的计算方式也是差不多,先根据Uid得到时间,然后乘以构造方法里对应的wifi类型单位时间内消耗电量值,没什么难点,就不一一分析,需要注意的是,这里面还计算了
但是还没有单独为App计算耗电量的,所以这个地方是空的。
摄像头的耗电量关注的是
计算方式如下:
先计算摄像头打开的时间
跟摄像头类似,也是先得到时间,然后乘积,不想说了,没意思。
关注的是
当无限量连接上时,根据信号强度不同,耗电量的计算是有区别的,所以在构造方法,当无线电的状态为on时,是要特殊处理的,其他两个状态(active和scan)就正常取值就可以了。
计算的方式分两种,以无线电处于
只关注一个属性:
计算方式如下:
当传感器的类型为GPS时,我们计算每个传感器的时间然后乘以耗电量,和所有的耗电量计算都是一样,不同的是,当传感器不是GPS时,这个时候计算就根据
参考文章:Android应用的耗电量统计
深入浅出Android App耗电量统计
Battery stats - CPU total vs CPU foreground
深入浅出 Android App 耗电量统计
浅析Wakelock机制与Android电源管理
耗电量API
Android系统中很早就有耗电量的
API,只不过一直都是隐藏的,
Android系统的
设置-电池功能就是调用的这个
API,该
API的核心部分是调用了
com.android.internal.os.BatteryStatsHelper类,利用
PowerProfile类,读取
power_profile.xml文件,我们一起来看看具体如何计算耗电量,首先从最新版本6.0开始看
6.0的API
源码
BatteryStatsHelper其中计算耗电量的方法为490行的
processAppUsage,下来一步一步来解释该方法。
App耗电量的计算探究
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">processAppUsage</span>(SparseArray<UserHandle> asUsers) {</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
方法的参数是一个
SparseArray数组,存储的对象是
UserHandle,官方文档给出的解释是,代表一个用户,可以理解为这个类里面存储了用户的相关信息.
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> forAllUsers = (asUsers.get(UserHandle.USER_ALL) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
然后判断该次计算是否针对所有用户,通过
UserHandle的
USER_ALL值来判断,该值为
-1,源码的地址在https://github.com/DoctorQ/platform_frameworks_base/blob/android-6.0.0_r1/core/java/android/os/UserHandle.java.
<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">mStatsPeriod </span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> mTypeBatteryRealtime;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
然后给公共变量int类型的
mStatsPeriod赋值,这个值
mTypeBatteryRealtime的计算过程又在320行的
refreshStats方法中:
<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">mTypeBatteryRealtime </span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> mStats.computeBatteryRealtime(rawRealtimeUs, mStatsType);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
这里面用到了
BatteryStats(mStats)类中的
computeBatteryRealtime方法,该方法计算出此次统计电量的时间间隔。好,歪楼了,回到
BatteryStatsHelper中。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">BatterySipper osSipper = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SparseArray<? extends Uid> uidStats = mStats.getUidStats(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> NU = uidStats.size();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
首先创建一个
BatterySipper对象
osSipper,该对象里面可以存储一些后续我们要计算的值,然后通过
BatteryStats类对象
mStats来得到一个包含
Uid的对象的
SparseArray组数,然后计算了一下这个数组的大小,保存在变量NU中。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> iu = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; iu < NU; iu++) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Uid u = uidStats.valueAt(iu); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BatterySipper app = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> BatterySipper(BatterySipper.DrainType.APP, u, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
然后
for循环计算每个
Uid代表的
App的耗电量,因为
BatterySipper可计算的类型有三种:应用,
系统服务, 硬件类型,所以这个地方传入的是
DrainType.APP,还有其他可选类型如下:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> DrainType { IDLE, CELL, PHONE, WIFI, BLUETOOTH, FLASHLIGHT, SCREEN, APP, USER, UNACCOUNTED, OVERCOUNTED, CAMERA }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
列举了目前可计算耗电量的模块。
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">mCpuPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mWakelockPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mMobileRadioPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mWifiPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mBluetoothPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mSensorPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mCameraPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mFlashlightPowerCalculator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.calculateApp</span>(app, u, mRawRealtime, mRawUptime, mStatsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
其中
mStatsType的值为
BatteryStats.STATS_SINCE_CHARGED,代表了我们的计算规则是从上次充满电后数据,还有一种规则是
STATS_SINCE_UNPLUGGED是拔掉USB线后的数据。而
mRawRealtime是当前时间,
mRawUptime是运行时间。6.0的对各个模块的消耗都交给了单独的类去计算,这些类都继承于
PowerCalculator抽象类:
<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">蓝牙耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:BluetoothPowerCalculator</span>.java 摄像头耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:CameraPowerCalculator</span>.java <span class="hljs-constant" style="box-sizing: border-box;">Cpu</span>耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:CpuPowerCalculator</span>.java 手电筒耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:FlashlightPowerCalculator</span>.java 无线电耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:MobileRadioPowerCalculator</span>.java 传感器耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:SensorPowerCalculator</span>.java <span class="hljs-constant" style="box-sizing: border-box;">Wakelock</span>耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:WakelockPowerCalculator</span>.java <span class="hljs-constant" style="box-sizing: border-box;">Wifi</span>耗电<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:WifiPowerCalculator</span>.java</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
这一部分我一会单独拿出来挨个解释,现在我们还是回到
BatteryStatsHelper继续往下走
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> totalPower = app.sumPower();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
BatterySipper#sumPower方法是统计总耗电量,方法详情如下,其中
usagePowerMah这个值有点特殊,其他的上面都讲过.
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Sum all the powers and store the value into `value`. *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> the sum of all the power in this BatterySipper. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-title" style="box-sizing: border-box;">sumPower</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> totalPowerMah = usagePowerMah + wifiPowerMah + gpsPowerMah + cpuPowerMah + sensorPowerMah + mobileRadioPowerMah + wakeLockPowerMah + cameraPowerMah + flashlightPowerMah; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
然后根据是否是DEBUG版本打印信息,这个没啥可说的,然后会把刚才计算的电量值添加到列表中:
<code class="hljs php has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Add the app to the list if it is consuming power.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (totalPower != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || u.getUid() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Add the app to the app list, WiFi, Bluetooth, etc, or into "Other Users" list.</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> int uid = app.getUid(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> int userId = UserHandle.getUserId(uid); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (uid == Process.WIFI_UID) { mWifiSippers.add(app); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (uid == Process.BLUETOOTH_UID) { mBluetoothSippers.add(app); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!forAllUsers && asUsers.get(userId) == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We are told to just report this user's apps as one large entry.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">List</span><BatterySipper> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">list</span> = mUserSippers.get(userId); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">list</span> == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">list</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<>(); mUserSippers.put(userId, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">list</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">list</span>.add(app); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { mUsageList.add(app); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (uid == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) { osSipper = app; } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
首先判断
totalPower的值和当前
uid号是否符合规则,规则为总耗电量不为0或者用户id为0.当
uid表明为WIFI或者蓝牙时,添加到下面对应的列表中,一般情况下正常的应用我们直接保存到下面的
mUsageList中就行就行,但是也有一些例外:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * List of apps using power. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> List<BatterySipper> mUsageList = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<>(); <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * List of apps using wifi power. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> List<BatterySipper> mWifiSippers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<>(); <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * List of apps using bluetooth power. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> List<BatterySipper> mBluetoothSippers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<>();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
如果我们的系统是单用户系统,且当前的
userId号不在我们的统计范围内,且其进程
id号是大于
Process.FIRST_APPLICATION_UID(10000,系统分配给普通应用的其实id号),我们就要将其存放到
mUserSippers数组中,定义如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SparseArray<List<BatterySipper>> mUserSippers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SparseArray<>();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
最后判断
uid为0的话,代表是
Android操作系统的耗电量,赋值给
osSipper(494行定义)就可以了,这样一个
app的计算就完成了,遍历部分就不说了,保存这个
osSipper是为了最后一步计算:
<code class="hljs coffeescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (osSipper != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) { <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> The device has probably been awake <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> longer than the screen <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">on</span> <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> time <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> application wake lock time would account <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>. Assign <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span> remainder to the OS, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> possible. mWakelockPowerCalculator.calculateRemaining(osSipper, mStats, mRawRealtime, mRawUptime, mStatsType); osSipper.sumPower(); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
主流程我们已经介绍完了,下面来看各个子模块耗电量的计算
Cpu耗电量
CpuPowerCalculator.javaCpu的计算要用到PowerProfile类,该类主要是解析power_profile.xml:
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">device</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"Android"</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Most values are the incremental current used by a feature, in mA (measured at nominal voltage). The default values are deliberately incorrect dummy values. OEM's must measure and provide actual values before shipping a device. Example real-world values are given in comments, but they are totally dependent on the platform and can vary significantly, so should be measured on the shipping platform with a power meter. --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"none"</span>></span>0<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"screen.on"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~200mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"screen.full"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~300mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"bluetooth.active"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Bluetooth data transfer, ~10mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"bluetooth.on"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Bluetooth on & connectable, but not connected, ~0.1mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wifi.on"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~3mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wifi.active"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- WIFI data transfer, ~200mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wifi.scan"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- WIFI network scanning, ~100mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"dsp.audio"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~10mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"dsp.video"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~50mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"camera.flashlight"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Avg. power for camera flash, ~160mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"camera.avg"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Avg. power use of camera in standard usecases, ~550mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"radio.active"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~200mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"radio.scanning"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- cellular radio scanning for signal, ~10mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"gps.on"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~50mA --></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Current consumed by the radio at different signal strengths, when paging --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"radio.on"</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Strength 0 to BINS-1 --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>0.2<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~2mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~1mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Different CPU speeds as reported in /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"cpu.speeds"</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>400000<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 400 MHz CPU speed --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Current when CPU is idle --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"cpu.idle"</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- Current at each CPU speed, as per 'cpu.speeds' --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"cpu.active"</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>0.1<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- ~100mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- This is the battery capacity in mAh (measured at nominal voltage) --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"battery.capacity"</span>></span>1000<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">item</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"wifi.batchedscan"</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- mA --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>.0002<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 1-8/hr --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>.002<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 9-64/hr --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>.02<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 65-512/hr --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>.2<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 513-4,096/hr --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span>2<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">value</span>></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 4097-/hr --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">array</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">device</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li></ul>
这个里面存储了Cpu(cpu.speeds)的主频等级,以及每个主频每秒消耗的毫安(cpu.active),好,现在回到
CpuPowerCalculator中,先来看构造方法
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">CpuPowerCalculator</span>(PowerProfile profile) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> speedSteps = profile.getNumSpeedSteps(); mPowerCpuNormal = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span>[speedSteps]; mSpeedStepTimes = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>[speedSteps]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; p < speedSteps; p++) { mPowerCpuNormal[p] = profile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
第一步获得
Cpu有几个主频等级,因为不同等级消耗的电量不一样,所以要区别对待,根据主频的个数,然后初始化
mPowerCpuNormal和
mSpeedStepTimes,前者用来保存不同等级的耗电速度,后者用来保存在不同等级上耗时,然后给
mPowerCpuNormal的每个元素附上值。构造方法就完成了其所有的工作,现在来计算方法
calculateApp,
<code class="hljs glsl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">final <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> speedSteps = mSpeedStepTimes.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">length</span>; long totalTimeAtSpeeds = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span> < speedSteps; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span>++) { mSpeedStepTimes[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span>] = u.getTimeAtCpuSpeed(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span>, statsType); totalTimeAtSpeeds += mSpeedStepTimes[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">step</span>]; } totalTimeAtSpeeds = Math.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">max</span>(totalTimeAtSpeeds, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
首先得到
Cpu主频等级个数,然后
BatteryStats.Uid得到不同主频上执行时间,计算
Cpu总耗时保存在
totalTimeAtSpeeds中,
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cpuTimeMs</span> = (u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getUserCpuTimeUs</span>(statsType) + u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getSystemCpuTimeUs</span>(statsType)) / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
Cpu的执行时间分很多部分,但是我们关注
User和
Kernal部分,也就是上面的
UserCpuTime和
SystemCpuTime。
<code class="hljs vbscript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">double cpuPowerMaMs = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span> < speedSteps; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span>++) { final double ratio = (double) mSpeedStepTimes[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span>] / totalTimeAtSpeeds; final double cpuSpeedStepPower = ratio * app.cpuTimeMs * mPowerCpuNormal[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span>]; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (DEBUG && ratio != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">Log</span>.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UID "</span> + u.getUid() + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">": CPU step #"</span> + <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">step</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" ratio="</span> + BatteryStatsHelper.makemAh(ratio) + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" power="</span> + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>))); } cpuPowerMaMs += cpuSpeedStepPower; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>
上面的代码就是将不同主频的消耗累加到一起,但是其中值得注意的是,他并不是用各个主频的消耗时间*主频单位时间内消耗的电量,而是用一个radio变量来计算得到各个主频段执行时间占总时间的百分比,然后用
cpuTimeMs来换算成各个主频的Cpu实际消耗时间,这比5.0的API多了这么一步,我估计是发现了计算的不严谨性,这也是
Android迟迟不放出统计电量方式的原因,其实google自己对这块也没有把握,所以才会造成不同
API计算方式的差异。好,计算完我们的总消耗后,是不是就算完事了?如果你只需要得到一个App的耗电总量,上面的讲解已经足够了,但是6.0的API计算了每个App的不同进程的耗电量,这个我们就只当看看就行,暂时没什么实际意义。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Keep track of the package with highest drain.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> highestDrain = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; app.cpuFgTimeMs = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> processStatsCount = processStats.size(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < processStatsCount; i++) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BatteryStats.Uid.Proc ps = processStats.valueAt(i); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String processName = processStats.keyAt(i); app.cpuFgTimeMs += ps.getForegroundTime(statsType); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType) + ps.getForegroundTime(statsType); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Each App can have multiple packages and with multiple running processes.</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Keep track of the package who's process has the highest drain.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (app.packageWithHighestDrain == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || app.packageWithHighestDrain.startsWith(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"*"</span>)) { highestDrain = costValue; app.packageWithHighestDrain = processName; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (highestDrain < costValue && !processName.startsWith(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"*"</span>)) { highestDrain = costValue; app.packageWithHighestDrain = processName; } } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Ensure that the CPU times make sense.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (app.cpuFgTimeMs > app.cpuTimeMs) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10000</span>) { Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WARNING! Cputime is more than 10 seconds behind Foreground time"</span>); } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Statistics may not have been gathered yet.</span> app.cpuTimeMs = app.cpuFgTimeMs; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>
上面统计同一
App下不同的进程的耗电量,得到消耗最大的进程名,保存到
BatterySipper对象中,然后得出
App的
Cpu的
foreground消耗时间,将
foreground时间与之前计算得到的
cpuTimeMs进行比较,如果
foreground时间比
cpuTimeMs还要大,那么就将
cpuTimeMs的时间改变为
foreground的值,但是这个值的变化对之前耗电总量的计算没有丝毫影响。
<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">// Convert the CPU power to mAh app.cpuPowerMah </span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> cpuPowerMaMs / (60 * 60 * 1000);</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
最后的最后,将耗电量用mAh单位来表示,所以在毫秒的基础上除以
60*60*1000。
总结:
Cpu耗电量的计算是要区分不同主频的,频率不同,单位时间内消耗的电量是有区分的,这一点要明白。还有一点就是不同主频上的执行时间不是通过
BatteryStats.Uid#getTimeAtCpuSpeed方法得到的,二十是通过百分比和
BatteryStats.Uid#getUserCpuTimeUs和
getSystemCpuTimeUs计算得到
cpuTimeMs乘积得到的。最后一点就是,
cpuTimeMs时间是会在计算完毕后进行比较,比较的对象是
CPU的
foreground时间。
WakeLock耗电量的计算
WakelockPowerCalculator.java从构造方法开始,
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">WakelockPowerCalculator</span>(PowerProfile profile) { mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_AWAKE); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
首先得到
power_profile.xml中
cpu.awake表示的值,保存在
mPowerWakelock变量中。构造方法只做了这么点事,下面进入
calculateApp方法。
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">@Override public void calculateApp(BatterySipper app, BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Uid</span> u, long rawRealtimeUs, long rawUptimeUs, int statsType) { long wakeLockTimeUs = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> final ArrayMap<String, ? extends BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Uid</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Wakelock</span>> wakelockStats = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWakelockStats</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> final int wakelockStatsCount = wakelockStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.size</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> for (int i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; i < wakelockStatsCount; i++) {</span> final BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Uid</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Wakelock</span> wakelock = wakelockStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.valueAt</span>(i)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> // Only care about partial wake locks since full wake locks // are canceled when the user turns the screen off. BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Timer</span> timer = wakelock<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWakeTime</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.WAKE</span>_TYPE_PARTIAL)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> if (timer != null) { wakeLockTimeUs += timer<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getTotalTimeLocked</span>(rawRealtimeUs, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } } app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockTimeMs</span> = wakeLockTimeUs / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; // convert to millis</span> mTotalAppWakelockTimeMs += app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockTimeMs</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> // <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Add</span> cost of holding a wake lock. app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockPowerMah</span> = (app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockTimeMs</span> * mPowerWakelock) / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> if (DEBUG && app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockPowerMah</span> != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) { Log<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.d</span>(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UID "</span> + u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getUid</span>() + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">": wake "</span> + app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockTimeMs</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" power="</span> + BatteryStatsHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.makemAh</span>(app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wakeLockPowerMah</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>
首先获得
Wakelock的数量,然后逐个遍历得到每个
Wakelock对象,得到该对象后,得到
BatteryStats.WAKE_TYPE_PARTIAL的唤醒时间,然后累加,其实
wakelock有4种,为什么只取
partial的时间,具体代码
waklock消耗电量相乘得到
Wakelock消耗的总电量。
Wifi耗电量的计算
首先来看构造方法,来了解一下WIFI的耗电量计算用到了power_profile.xml中的哪些属性:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">public WifiPowerCalculator(PowerProfile profile) { mIdleCurrentMa = profile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getAveragePower</span>(PowerProfile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.POWER</span>_WIFI_CONTROLLER_IDLE)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mTxCurrentMa = profile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getAveragePower</span>(PowerProfile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.POWER</span>_WIFI_CONTROLLER_TX)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mRxCurrentMa = profile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getAveragePower</span>(PowerProfile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.POWER</span>_WIFI_CONTROLLER_RX)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
我们去
PowerProfile.java找到上面三个常量代表的属性:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_WIFI_CONTROLLER_IDLE = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wifi.controller.idle"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_WIFI_CONTROLLER_RX = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wifi.controller.rx"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_WIFI_CONTROLLER_TX = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wifi.controller.tx"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
知道对应的xml的属性后我们直接看
calculateApp方法:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">@Override public void calculateApp(BatterySipper app, BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Uid</span> u, long rawRealtimeUs, long rawUptimeUs, int statsType) { final long idleTime = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWifiControllerActivity</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONTROLLER</span>_IDLE_TIME, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> final long txTime = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWifiControllerActivity</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONTROLLER</span>_TX_TIME, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> final long rxTime = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWifiControllerActivity</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONTROLLER</span>_RX_TIME, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiRunningTimeMs</span> = idleTime + rxTime + txTime<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiPowerMah</span> = ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa)) / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> mTotalAppPowerDrain += app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiPowerMah</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiRxPackets</span> = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getNetworkActivityPackets</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NETWORK</span>_WIFI_RX_DATA, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiTxPackets</span> = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getNetworkActivityPackets</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NETWORK</span>_WIFI_TX_DATA, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiRxBytes</span> = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getNetworkActivityBytes</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NETWORK</span>_WIFI_RX_DATA, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiTxBytes</span> = u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getNetworkActivityBytes</span>(BatteryStats<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NETWORK</span>_WIFI_TX_DATA, statsType)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> if (DEBUG && app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiPowerMah</span> != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) { Log<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.d</span>(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UID "</span> + u<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getUid</span>() + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">": idle="</span> + idleTime + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ms rx="</span> + rxTime + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ms tx="</span> + txTime + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ms power="</span> + BatteryStatsHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.makemAh</span>(app<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.wifiPowerMah</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
这里的计算方式也是差不多,先根据Uid得到时间,然后乘以构造方法里对应的wifi类型单位时间内消耗电量值,没什么难点,就不一一分析,需要注意的是,这里面还计算了
wifi传输的数据包的数量和字节数。
蓝牙耗电量的计算
蓝牙关注的power_profile.xml中的属性如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_BLUETOOTH_CONTROLLER_IDLE = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"bluetooth.controller.idle"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_BLUETOOTH_CONTROLLER_RX = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"bluetooth.controller.rx"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_BLUETOOTH_CONTROLLER_TX = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"bluetooth.controller.tx"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
但是还没有单独为App计算耗电量的,所以这个地方是空的。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">calculateApp</span>(BatterySipper app, BatteryStats.Uid u, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawRealtimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawUptimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> statsType) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// No per-app distribution yet.</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
摄像头耗电量的计算
CameraPowerCalculator.java摄像头的耗电量关注的是
power_profile.xml中
camera.avg属性代表的值,保存到
mCameraPowerOnAvg,
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_CAMERA = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"camera.avg"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
计算方式如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">calculateApp</span>(BatterySipper app, BatteryStats.Uid u, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawRealtimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawUptimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> statsType) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Calculate camera power usage. Right now, this is a (very) rough estimate based on the</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// average power usage for a typical camera application.</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BatteryStats.Timer timer = u.getCameraTurnedOnTimer(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (timer != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> totalTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>; app.cameraTimeMs = totalTime; app.cameraPowerMah = (totalTime * mCameraPowerOnAvg) / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { app.cameraTimeMs = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; app.cameraPowerMah = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
先计算摄像头打开的时间
totalTime,然后根据这个值乘以
mCameraPowerOnAvg得到摄像头的耗电量。
手电筒耗电量的计算
FlashlightPowerCalculator.java<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_FLASHLIGHT = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"camera.flashlight"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
跟摄像头类似,也是先得到时间,然后乘积,不想说了,没意思。
无线电耗电量的计算
MobileRadioPowerCalculator.java关注的是
power_profile.xml中如下三个属性:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when screen is on, not including the backlight power. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_SCREEN_ON = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"screen.on"</span>; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when cell radio is on but not on a call. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_RADIO_ON = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"radio.on"</span>; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when cell radio is hunting for a signal. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_RADIO_SCANNING = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"radio.scanning"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
当无限量连接上时,根据信号强度不同,耗电量的计算是有区别的,所以在构造方法,当无线电的状态为on时,是要特殊处理的,其他两个状态(active和scan)就正常取值就可以了。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when screen is on, not including the backlight power. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_SCREEN_ON = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"screen.on"</span>; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when cell radio is on but not on a call. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_RADIO_ON = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"radio.on"</span>; <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Power consumption when cell radio is hunting for a signal. */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_RADIO_SCANNING = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"radio.scanning"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
计算的方式分两种,以无线电处于
active状态的次数为区分,当
active大于0,我们用处于
active状态的时间来乘以它的单位耗时。另一种情况就要根据网络转化的数据包来计算耗电量了。
传感器耗电量的计算
SensorPowerCalculator.java只关注一个属性:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String POWER_GPS_ON = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"gps.on"</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
计算方式如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">calculateApp</span>(BatterySipper app, BatteryStats.Uid u, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawRealtimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rawUptimeUs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> statsType) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Process Sensor usage</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> NSE = sensorStats.size(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ise = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; ise < NSE; ise++) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sensorHandle = sensorStats.keyAt(ise); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BatteryStats.Timer timer = sensor.getSensorTime(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (sensorHandle) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> BatteryStats.Uid.Sensor.GPS: app.gpsTimeMs = sensorTime; app.gpsPowerMah = (app.gpsTimeMs * mGpsPowerOn) / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sensorsCount = mSensors.size(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < sensorsCount; i++) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Sensor s = mSensors.get(i); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (s.getHandle() == sensorHandle) { app.sensorPowerMah += (sensorTime * s.getPower()) / (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; } } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; } } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li></ul>
当传感器的类型为GPS时,我们计算每个传感器的时间然后乘以耗电量,和所有的耗电量计算都是一样,不同的是,当传感器不是GPS时,这个时候计算就根据
SensorManager得到所有传感器类型,这个里面保存有不同传感器的单位耗电量,这样就能计算不同传感器的耗电量。
总结
至此我已经把App耗电量的计算讲完了(还有硬件),前后花费3天时间,好痛苦(此处一万只草泥马),不过好在自己也算对这个耗电量的理解有了一定的认识。google官方对耗电量的统计给出的解释都是不能代表真实数据,只能作为参考值,因为受power_profile.xml的干扰太大,如果手机厂商没有严格设置这个文件,那可想而知出来的值可能是不合理的。相关文章推荐
- Android SwipeToDismiss:左滑/右滑删除ListView条目Item
- Android 使用ViewPager自动滚动循环轮播效果
- 如何用Fiddler对Android应用进行抓包
- Android端百度地图API使用详解
- Android官方文档阅读之旅——Animation and Graphics Overview 动画与图形概述
- 初学使用android studio的NDK
- android 将时间戳转为代表"距现在多久之前"的字符串
- 几行代码,让你的 APP 变得花俏—Android Design Support Library 代码实验
- Android开发&Android studio中的jni
- 理解Android系统的进程间通信原理(一)----RPC中的代理模式
- Java课程设计笔记-Android系统创建阻塞式对话框
- Android系统性能调优工具介绍
- Android中常见的热门标签的流式布局的实现
- android studio总结
- Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载
- Android 5.0 系统中来电过程中屏幕会休眠的问题
- android studio中直接运行java程序
- Android 学习的好文章(以后有好的文章将不断更新链接)
- Android 5.0 Material Design酷炫风格的开源项目集合
- 10 条提升 Android 性能的建议