PowerProfile.java与power_profile.xml
转载自http://blog.csdn.net/green1900/article/details/42427871
现在诸多关于电池管理的应用做的极其绚烂,可实现如耗电应用排行、剩余时间计算、关闭耗电程序以节省电量等功能,这两天对此模块进行了研究,总结如下。
首先解释下各软硬件耗电量的计算。假设设备(如WIFI)单位时间内消耗的电量为w,运行时间为t,则其在这段时间内的耗电量为W=w*t。根据物理学中的知识,电功率(即所谓电量)计算公式为W=UIt,其中U为电压值,I为电流值,t为运行时间。由于在一部机器中,电压值U是恒定不变的(一般如此),因此可以忽略掉参数U,单独通过电流及时间即可表示电量(比如电池容量为2000mA、2500mA等,以mA为单位进行恒量)。根据以上描述,只要我们获得了某程序或某设备运行的时间,以及其运行时所需要电流值,则可以计算出其消耗的电量(以上理论会在代码中体现)。
某程序或硬件设备的运行时间可以分别通过BatteryStats.Uid.Proc和BatteryStatsImpl中的相关接口获得(后文分析代码时会见到),本文主要讲下电流值(即单位时间消耗电量)的获取。
1. PowerProfile.Java
OK,不多废话,直接给出系统中提供的接口--./frameworks/base/core/java/com/Android/internal/os/PowerProfile.java。此类提供了如下接口:
(1)public double getAveragePower(String type)
此方法返回在type子系统下消耗的电流值,单位为mA。type可取PowerProfile中定义的常量值,包括POWER_CPU_IDLE(CPU空闲时),POWER_CPU_ACTIVE(CPU处于活动时),POWER_WIFI_ON(WIFI开启时)等各种状态。例如,如下调用getAveragePower(POWER_CPU_ACTIVE)将返回CPU处于活动时的电流值;getAveragePower(POWER_WIFI_ON)将返回维持WIFI启动状态所需的电流值。结合之前的描述,假设WIFI开启的时间为t(假设此段时间未使用WIFI传输数据,因为WIFI传输数据需要额外的电能消耗),那么在此段时间内WIFI所消耗的电量为W=t*getAveragePower(POWER_WIFI_ON)。
type可取如下值:
/**
* No power consumption, or accounted for elsewhere.
*/
public static final String POWER_NONE = "none";
/**
* Power consumption when CPU is in power collapse mode.
*/
public static final String POWER_CPU_IDLE = "cpu.idle";
/**
* Power consumption when CPU is awake (when a wake lock is held). This
* should be 0 on devices that can go into full CPU power collapse even
* when a wake lock is held. Otherwise, this is the power consumption in
* addition to POWERR_CPU_IDLE due to a wake lock being held but with no
* CPU activity.
*/
public static final String POWER_CPU_AWAKE = "cpu.awake";
/**
* Power consumption when CPU is in power collapse mode.
*/
public static final String POWER_CPU_ACTIVE = "cpu.active";
/**
* Power consumption when WiFi driver is scanning for networks.
*/
public static final String POWER_WIFI_SCAN = "wifi.scan";
/**
* Power consumption when WiFi driver is on.
*/
public static final String POWER_WIFI_ON = "wifi.on";
/**
* Power consumption when WiFi driver is transmitting/receiving.
*/
public static final String POWER_WIFI_ACTIVE = "wifi.active";
/**
* Power consumption when GPS is on.
*/
public static final String POWER_GPS_ON = "gps.on";
/**
* Power consumption when Bluetooth driver is on.
*/
public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
/**
* Power consumption when Bluetooth driver is transmitting/receiving.
*/
public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
/**
* Power consumption when Bluetooth driver gets an AT command.
*/
public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
/**
* Power consumption when screen is on, not including the backlight power.
*/
public static final String POWER_SCREEN_ON = "screen.on";
/**
* Power consumption when cell radio is on but not on a call.
*/
public static final String POWER_RADIO_ON = "radio.on";
/**
* Power consumption when cell radio is hunting for a signal.
*/
public static final String POWER_RADIO_SCANNING = "radio.scanning";
/**
* Power consumption when talking on the phone.
*/
public static final String POWER_RADIO_ACTIVE = "radio.active";
/**
* Power consumption at full backlight brightness. If the backlight is at
* 50% brightness, then this should be multiplied by 0.5
*/
public static final String POWER_SCREEN_FULL = "screen.full";
/**
* Power consumed by the audio hardware when playing back audio content. This is in addition
* to the CPU power, probably due to a DSP and / or amplifier.
*/
public static final String POWER_AUDIO = "dsp.audio";
/**
* Power consumed by any media hardware when playing back video content. This is in addition
* to the CPU power, probably due to a DSP.
*/
public static final String POWER_VIDEO = "dsp.video";
代码段1 PowerProfile.java中定义的子系统类型
(2) public double getAveragePower(String type, int level)
相比于方法(1),此接口需要传入参数level,现在来解释下level的含义。我们知道,android系统中CPU可以以多种速度运行(假设分别为600MHz,800MHz,1GHZ等),速度不同时CPU消耗的电量也不同,参数level即代表不同的运行频率,显然,方法getAveragePower(String type, int level)将返回type子系统在CPU运行速度级别为level时单位时间内所消耗的电量(即电流值)。
(3)public double getBatteryCapacity() 获取电池总电量。
(4)public int getNumSpeedSteps() 获取CPU可以以几种速度运行。
2. power_profile.xml
事实上,通过阅读PowerProfile.java代码及相关注释即可知,此类中各接口返回的电流等数值都是通过读取power_profile.xml文件获得的,即各种子系统消耗的电量值、CPU运行速度值、总电量等信息都是以固定值的形式存储在power_profile.xml中。由于硬件之间的差异,各子系统耗电信息是不同的,因此此文件需要各生产厂商进行定制。android系统原生的power_profile.xml文件的存放路径为:frameworks/base/core/java/com/android/internal/os/PowerProfile.java,经过各硬件厂商定制后,存放路径可能发生变化,如三星某型号的power_profile.xml路径:device/samsung/maguro/overlay/frameworks/base/core/res/res/xml/power_profile.xml,其内容如下:
<device name="Android">
<!-- All values are in mA except as noted -->
<item name="none">0</item>
<item name="screen.on">200</item> <!-- min brite -->
<item name="bluetooth.active">150</item>
<item name="bluetooth.on">1</item>
<item name="bluetooth.at">1</item> <!-- TBD -->
<item name="screen.full">160</item> <!-- 360 max on calendar -->
<item name="wifi.on">1</item> <!-- wifi处于开启状态,但未传输数据 -->
<item name="wifi.active">150</item> <!-- wifi处于传输数据状态 -->
<item name="wifi.scan">200</item> <!-- wifi处于搜索热点状态 -->
<item name="dsp.audio">150</item>
<item name="dsp.video">200</item>
<item name="radio.active">150</item>
<item name="gps.on">55</item>
<item name="battery.capacity">1750</item>
<item name="radio.scanning">90</item> <!-- TBD -->
<!-- Current consumed by the radio at different signal strengths, when paging -->
<array name="radio.on"> <!-- 1 entry per signal strength bin, TBD -->
<value>3.0</value>
<value>3.0</value>
</array>
<array name="cpu.speeds">
<value>350000</value> <!-- 3.5MHz -->
<value>700000</value> <!-- 7.0MHz -->
<value>920000</value> <!-- 9.2MHz -->
<value>1200000</value> <!-- 1.2GHz -->
</array>
<!-- Power consumption in suspend -->
<item name="cpu.idle">7</item>
<!-- Power consumption due to wake lock held -->
<item name="cpu.awake">20</item>
<!-- Power consumption at different speeds -->
<array name="cpu.active">
<value>120</value>
<value>228</value>
<value>299</value>
<value>397</value>
</array>
</device>
代码段2 power_profile.xml内容
显然,从power_profile.xml可知,此型号机器可以以3.5MHz、7.0MHz、9.2MHz、1.2GHz四种速度运行(<array name="cpu.speeds">定义),且在此四种运行速度下CPU的耗电量分别为120mAh,228mAh,299mAh及397mAh(<array name="cpu.active">)。通过对比代码段1可知,PowerProfile.java中定义的常量即对应于power_profile.xml中各属性名。因此,PowerProfile.java只是用于读取power_profile.xml的接口而已,后者才是存储系统耗电信息的核心文件。
通过上述分析可知,android系统对于电池电量信息统计还是提供了数据与接口的(本人菜鸟,之前一直认为耗电及剩余时间信息是由先前一定时间内的耗电量统计而来的,分析了settings中的电池相关的代码后才知是有据可依的)。根据PowerProfile.java及power_profile.xml,我们可以计算出各应用或设备的耗电量、电池剩余时间等信息,相关内容将在后续文章中描述。
PowerProfile.java源码
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package com.android.internal.os; import android.content.Context;
import android.content.res.XmlResourceParser; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; /**
* Reports power consumption values for various device activities. Reads values from an XML file.
* Customize the XML file for different devices.
* [hidden]
*/
public class PowerProfile { /**
* No power consumption, or accounted for elsewhere.
*/
public static final String POWER_NONE = "none"; /**
* Power consumption when CPU is in power collapse mode.
*/
public static final String POWER_CPU_IDLE = "cpu.idle"; /**
* Power consumption when CPU is in power collapse mode.
*/
public static final String POWER_CPU_ACTIVE = "cpu.active"; /**
* Power consumption when WiFi driver is scanning for networks.
*/
public static final String POWER_WIFI_SCAN = "wifi.scan"; /**
* Power consumption when WiFi driver is on.
*/
public static final String POWER_WIFI_ON = "wifi.on"; /**
* Power consumption when WiFi driver is transmitting/receiving.
*/
public static final String POWER_WIFI_ACTIVE = "wifi.active"; /**
* Power consumption when GPS is on.
*/
public static final String POWER_GPS_ON = "gps.on"; /**
* Power consumption when Bluetooth driver is on.
*/
public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; /**
* Power consumption when Bluetooth driver is transmitting/receiving.
*/
public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; /**
* Power consumption when Bluetooth driver gets an AT command.
*/
public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; /**
* Power consumption when screen is on, not including the backlight power.
*/
public static final String POWER_SCREEN_ON = "screen.on"; /**
* Power consumption when cell radio is on but not on a call.
*/
public static final String POWER_RADIO_ON = "radio.on"; /**
* Power consumption when cell radio is hunting for a signal.
*/
public static final String POWER_RADIO_SCANNING = "radio.scanning"; /**
* Power consumption when talking on the phone.
*/
public static final String POWER_RADIO_ACTIVE = "radio.active"; /**
* Power consumption at full backlight brightness. If the backlight is at
* 50% brightness, then this should be multiplied by 0.5
*/
public static final String POWER_SCREEN_FULL = "screen.full"; /**
* Power consumed by the audio hardware when playing back audio content. This is in addition
* to the CPU power, probably due to a DSP and / or amplifier.
*/
public static final String POWER_AUDIO = "dsp.audio"; /**
* Power consumed by any media hardware when playing back video content. This is in addition
* to the CPU power, probably due to a DSP.
*/
public static final String POWER_VIDEO = "dsp.video"; public static final String POWER_CPU_SPEEDS = "cpu.speeds"; static final HashMap<String, Object> sPowerMap = new HashMap(); private static final String TAG_DEVICE = "device";
private static final String TAG_ITEM = "item";
private static final String TAG_ARRAY = "array";
private static final String TAG_ARRAYITEM = "value";
private static final String ATTR_NAME = "name"; public PowerProfile(Context context) {
// Read the XML file for the given profile (normally only one per
// device)
if (sPowerMap.size() == 0) {
readPowerValuesFromXml(context);
}
} private void readPowerValuesFromXml(Context context) {
int id = com.android.internal.R.xml.power_profile;
XmlResourceParser parser = context.getResources().getXml(id);
boolean parsingArray = false;
ArrayList<Double> array = new ArrayList();
String arrayName = null; try {
XmlUtils.beginDocument(parser, TAG_DEVICE); while (true) {
XmlUtils.nextElement(parser); String element = parser.getName();
if (element == null) break; if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
// Finish array
sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
parsingArray = false;
}
if (element.equals(TAG_ARRAY)) {
parsingArray = true;
array.clear();
arrayName = parser.getAttributeValue(null, ATTR_NAME);
} else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) {
String name = null;
if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME);
if (parser.next() == XmlPullParser.TEXT) {
String power = parser.getText();
double value = 0;
try {
value = Double.valueOf(power);
} catch (NumberFormatException nfe) {
}
if (element.equals(TAG_ITEM)) {
sPowerMap.put(name, value);
} else if (parsingArray) {
array.add(value);
}
}
}
}
if (parsingArray) {
sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
}
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
parser.close();
}
} /**
* Returns the average current in mA consumed by the subsystem
* @param type the subsystem type
* @return the average current in milliAmps.
*/
public double getAveragePower(String type) {
if (sPowerMap.containsKey(type)) {
Object data = sPowerMap.get(type);
if (data instanceof Double[]) {
return ((Double[])data)[0];
} else {
return (Double) sPowerMap.get(type);
}
} else {
return 0;
}
} /**
* Returns the average current in mA consumed by the subsystem for the given level.
* @param type the subsystem type
* @param level the level of power at which the subsystem is running. For instance, the
* signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
* If there is no data for multiple levels, the level is ignored.
* @return the average current in milliAmps.
*/
public double getAveragePower(String type, int level) {
if (sPowerMap.containsKey(type)) {
Object data = sPowerMap.get(type);
if (data instanceof Double[]) {
final Double[] values = (Double[]) data;
if (values.length > level && level >= 0) {
return values[level];
} else if (level < 0) {
return 0;
} else {
return values[values.length - 1];
}
} else {
return (Double) data;
}
} else {
return 0;
}
} public int getNumSpeedSteps() {
Object value = sPowerMap.get(POWER_CPU_SPEEDS);
if (value != null && value instanceof Double[]) {
return ((Double[])value).length;
}
return 1; // Only one speed
}
}
PowerProfile.java与power_profile.xml的更多相关文章
- 【解决方案】cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One of '{"http://java.sun.com/xml/ns/javaee":run-as, "http://java.sun.com/xml/ns/javaee":security-role-r
[JAVA错误] cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'. One o ...
- 通过JAXB完成Java对象与XML之间的转换
Java对象转换XML的过程叫marshal. XML转换到Java对象的过程叫unmarshal. 一.Java对象转化为XML 这里省略getter和setter方法 通过标注@XMLRootEl ...
- JAVA基础知识xml,date
虽然说看文档最好是看官方原来的文档,但是呢,下面是我看别的人的总结,算做抛砖引玉吧,如果有不对的,我会在后期给更正或者自己来写一篇 1,JAVA中对xml的操作,包括schema,dtd等相关知识:标 ...
- java对象与XML相互转化
起因 最近在公司做了一次webservice相关的任务,其中我最敢兴趣的就是webservice接受到XML对应的流以后是如何方便的转化成java对象,而java对象又是如何生成对应的XML的. 目的 ...
- Java为何用xml做配置文件?
在Java世界里xml配置文件几乎是首选,xml有什么好的特性呢? xml能存储小量数据,仅仅是存储数据. xml可以跨平台,主流各种平台都对xml有支持, 真正的跨平台, xml读取速度快. xml ...
- JAVA对象和XML文档、原来他们之间还有这一出
最近项目开发中遇到一个问题,访问接口不再通过url地址请求的方式,而是 通过socket发送xml格式的报文到指定服务器来进行信息的统一认证.. 因此组装xml格式的报文字符串以及解析服务器返回的xm ...
- 玩转Java对象和XML相互转换
最近在项目中一直出现Java对象和XML之间的相互转换,一开始由于项目很庞大,我又是临时调度过去,导致在按照项目组长的要求进行写代码的同时,总是在这块云里雾里,最近才慢慢开始搞清楚项目中具体的使用缘由 ...
- java生成解析xml的另外两种方法JAXB
JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例文档反 ...
- java生成解析xml的另外两种方法Xstream
Xstream生成和解析xm和JAXB生成和解析xml的方法. 一,Xstream Xstream非jdk自带的,需要到入Xstream-1.4.3.jar和xpp3_min-1.1.4.jar 1. ...
随机推荐
- KI的斐波那契_DFS
Description KI十分喜欢美丽而优雅的斐波那契数列,最近他新认识了一种斐波那契字符串,定义如下 f (0) = b, f (1) = a, f (2) = f (1) + f (0) = a ...
- Html 开发工具 之Hbulider
下载地址 : 百度搜索该名字即可 或 点击此处 选择 文件->新建Web项目 输入项目名称即可 如下图 它会自动生成一些 文件夹 或文件,不需要的删除即可.
- 一键编译go文件命令.bat
一键编译go文件命令.bat , 请新建 一键编译go文件命令.bat 文件,放到你的xxx.go文件目录下 ( 欢迎加入go语言群: 218160862 , 群内有实践) 点击加入 @e ...
- iredmail安装脚本分析(三)---conf/global DISTRO值的来源及操作系统的判断
作者在引入conf/global 文件时,就已经对操作系统的类型进行判断,同时也对DISTRO进行了赋值. 部分代码,如图: 显然文件里的KERNEL_NAME的值就是判断完成的操作系统,具体分析该值 ...
- D - 图论
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Descr ...
- windows下Bullet 2.82编译安装(Bullet Physics开发环境配置)
平台:Win7,VS2010 1. Bullet库的组织 下图是Bullet_User_Manual中的截图: 从中可见,Bullet的LinearMath(线性数学模块),其上是BulletColl ...
- jQuery基本语法
jQuery 是 JavaScript 的一个函数库.方便.主流 jQuery的开发步骤: (1) 导入jQuery 库 (2) 在 <script src="../js/j ...
- JSON数据;
1.JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 2.JSON的规则很简单: 对象是一个无序的“‘名称/值'对”集合.一个对象以“{”(左括号)开始, ...
- iptables的扩展匹配
iptables的匹配条件 一.通用匹配:-s.-d.-p.-i.-o 二.扩展匹配 1.隐含扩展:使用-p{tcp|udp|icmp}指定某特定协议后,自动能够对协议进行扩展 -p tcp --dp ...
- 【jq】c#零基础学习之路(2)循环和分支
一.循环语句 1).do { //循环体,先运行一次. } while (true); 2). while (true) { //循环体 } 3). for (int i = 0; i < le ...