BatteryService分析​

来源:互联网 发布:狗狗起名的软件 编辑:程序博客网 时间:2024/06/05 22:54

. BatteryService分析

电池的信息,电压,温度,充电状态等等,都是由BatteryService来提供的。BatteryService是跑在system_process当中,在系统初始化的时候启动,如下

BatteryService.java中:
Log.i(TAG, “Starting Battery Service.”);
BatteryService battery = new BatteryService(context);
ServiceManager.addService(“battery”, battery);

========================================================================================

1. 
数据来源
BatteryService
通过JNIcom_android_server_BatteryService.cpp)读取数据。BatteryService通过JNI注册的不仅有函数,还有变量。 如下:

//##############BatteryService.java中声明的变量################
private boolean mAcOnline;
private boolean mUsbOnline;
private int mBatteryStatus;
private int mBatteryHealth;
private boolean mBatteryPresent;
private int mBatteryLevel;
private int mBatteryVoltage;
private int mBatteryTemperature;
private String mBatteryTechnology;

// BatteryService.java中声明的变量,在com_android_server_BatteryService.cpp中共 用,即 在com_android_server_BatteryService.cpp中其实操作的也是BatteryService.java中声明的变量

gFieldIds.mAcOnline = env->GetFieldID(clazz, “mAcOnline”, “Z”);
gFieldIds.mUsbOnline = env->GetFieldID(clazz, “mUsbOnline”, “Z”);
gFieldIds.mBatteryStatus = env->GetFieldID(clazz, “mBatteryStatus”, “I”);
gFieldIds.mBatteryHealth = env->GetFieldID(clazz, “mBatteryHealth”, “I”);
gFieldIds.mBatteryPresent = env->GetFieldID(clazz, “mBatteryPresent”, “Z”);
gFieldIds.mBatteryLevel = env->GetFieldID(clazz, “mBatteryLevel”, “I”);
gFieldIds.mBatteryTechnology = env->GetFieldID(clazz, “mBatteryTechnology”, “Ljava/lang/String;”);
gFieldIds.mBatteryVoltage = env->GetFieldID(clazz, “mBatteryVoltage”, “I”);
gFieldIds.mBatteryTemperature = env->GetFieldID(clazz, “mBatteryTemperature”, “I”);

//上面这些变量的值,对应是从下面的文件中读取的,一只文件存储一个数值。
#define AC_ONLINE_PATH “/sys/class/power_supply/ac/online”
#define USB_ONLINE_PATH “/sys/class/power_supply/usb/online”
#define BATTERY_STATUS_PATH “/sys/class/power_supply/battery/status”
#define BATTERY_HEALTH_PATH “/sys/class/power_supply/battery/health”
#define BATTERY_PRESENT_PATH “/sys/class/power_supply/battery/present”
#define BATTERY_CAPACITY_PATH “/sys/class/power_supply/battery/capacity”
#define BATTERY_VOLTAGE_PATH “/sys/class/power_supply/battery/batt_vol”
#define BATTERY_TEMPERATURE_PATH “/sys/class/power_supply/battery/batt_temp”
#define BATTERY_TECHNOLOGY_PATH “/sys/class/power_supply/battery/technology”

Android是运行在Linux内核上面的,/sys/class/power_supply亦是Linux内核下面的目录。至于这些文件时怎么生成的,则是由Platform来控制的。

———————————————————————————————————————————–
2. 
数据传送
电池的这些信息是通过何种方式,被其他应用所获得的。可以想到的有两种方式,第一种,应用主动从BatteryService获得数据;第二种,BatteryService主动把数据传送给所关心的应用程序。

BatteryService采用的是第二种方式,所有的电池的信息数据是通过Intent传送出去的。在BatteryService.java中,Code如下:

Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

intent.putExtra(“status”, mBatteryStatus);
intent.putExtra(“health”, mBatteryHealth);
intent.putExtra(“present”, mBatteryPresent);
intent.putExtra(“level”, mBatteryLevel);
intent.putExtra(“scale”, BATTERY_SCALE);
intent.putExtra(“icon-small”, icon);
intent.putExtra(“plugged”, mPlugType);
intent.putExtra(“voltage”, mBatteryVoltage);
intent.putExtra(“temperature”, mBatteryTemperature);
intent.putExtra(“technology”, mBatteryTechnology);

ActivityManagerNative.broadcastStickyIntent(intent, null);

———————————————————————————————————————————–
3. 
数据接收
应用如果想要接收到BatteryService发送出来的电池信息,则需要注册一个IntentIntent.ACTION_BATTERY_CHANGEDBroadcastReceiver

注册方法如下:
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(mIntentReceiver, mIntentFilter);

private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

int nVoltage = intent.getIntExtra(“voltage”, 0);
if(nVoltage!=0){
mVoltage.setText(“V: ” + nVoltage + “mV – Success…”);
}
else

{
mVoltage.setText(“V: ” + nVoltage + “mV – fail…”);
}
}
}
};

———————————————————————————————————————————–
4. 
数据更新
电池的信息会随着时间不停变化,自然地,就需要考虑如何实时的更新电池的数据信息。在BatteryService启动的时候,会同时通过UEventObserver启动一个onUEvent Thread

每一个Process最多只能有一个onUEvent Thread,即使这个Process中有多个UEventObserver的实例。当在一个Process中,第一次Call startObserving()方法后,这个UEvent thread就启动了。
而一旦这个UEvent thread启动之后,就不会停止。

//BatteryService.java
mUEventObserver.startObserving(“SUBSYSTEM=power_supply”);

private UEventObserver mUEventObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
update();
}
};
UEvent thread中会不停调用 update()方法,来更新电池的信息数据。

二 应用实例

这里介绍电池信息的取得.
    android.content.BroadcastReceiver

    android.os.BatteryManager

● 电池信息的取得,调用registerReceiver()方法。

         1个参数,设置BroadcastReceiver实例
         
2个参数,设置追加了Intent.ACTION_BATTERY_CHANGED处理的IntentFilter实例。

● BroadcastReceiveronReceive()事件,接收到的Intent.ACTION_BATTERY_CHANGED,包括下面的信息。
    “status”
int类型)…状态,定义值是BatteryManager.BATTERY_STATUS_XXX
    “health”
int类型)…健康,定义值是BatteryManager.BATTERY_HEALTH_XXX
    “present”
boolean类型)
    “level”
int类型)…电池剩余容量
    “scale”
int类型)…电池最大值。通常为100
    “icon-small”
int类型)…图标ID
    “plugged”
int类型)…连接的电源插座,定义值是BatteryManager.BATTERY_PLUGGED_XXX
    “voltage”
int类型)…mV
    “temperature”
int类型)…温度,0.1度单位。例如 表示197的时候,意思为19.7度。  
    “technology”
String类型)…电池类型,例如,Li-ion等等。

 

实例代码如下

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.BatteryManager;

import android.os.Bundle;

import android.widget.TextView;

 

public class Power extends Activity

{

private TextView m_txtMsg;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

m_txtMsg = (TextView) findViewById(R.id.TXT_MSG);

}

 

@Override

protected void onResume()

{

super.onResume();

 

IntentFilter filter = new IntentFilter();

 

filter.addAction(Intent.ACTION_BATTERY_CHANGED);

registerReceiver(mBroadcastReceiver, filter);

}

 

@Override

protected void onPause()

{

super.onPause();

 

unregisterReceiver(mBroadcastReceiver);

}

 

private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()

{

@Override

public void onReceive(Context context, Intent intent)

{

String action = intent.getAction();

if (action.equals(Intent.ACTION_BATTERY_CHANGED))

{

int status = intent.getIntExtra("status", 0);

int health = intent.getIntExtra("health", 0);

boolean present = intent.getBooleanExtra("present"false);

int level = intent.getIntExtra("level", 0);

int scale = intent.getIntExtra("scale", 0);

int icon_small = intent.getIntExtra("icon-small", 0);

int plugged = intent.getIntExtra("plugged", 0);

int voltage = intent.getIntExtra("voltage", 0);

int temperature = intent.getIntExtra("temperature", 0);

String technology = intent.getStringExtra("technology");

 

String statusString = "";

 

switch (status)

{

case BatteryManager.BATTERY_STATUS_UNKNOWN:

statusString = "unknown";

break;

case BatteryManager.BATTERY_STATUS_CHARGING:

statusString = "charging";

break;

case BatteryManager.BATTERY_STATUS_DISCHARGING:

statusString = "discharging";

break;

case BatteryManager.BATTERY_STATUS_NOT_CHARGING:

statusString = "not charging";

break;

case BatteryManager.BATTERY_STATUS_FULL:

statusString = "full";

break;

}

 

String healthString = "";

 

switch (health)

{

case BatteryManager.BATTERY_HEALTH_UNKNOWN:

healthString = "unknown";

break;

case BatteryManager.BATTERY_HEALTH_GOOD:

healthString = "good";

break;

case BatteryManager.BATTERY_HEALTH_OVERHEAT:

healthString = "overheat";

break;

case BatteryManager.BATTERY_HEALTH_DEAD:

healthString = "dead";

break;

case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:

healthString = "voltage";

break;

case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:

healthString = "unspecified failure";

break;

}

 

String acString = "";

 

switch (plugged)

{

case BatteryManager.BATTERY_PLUGGED_AC:

acString = "plugged ac";

break;

case BatteryManager.BATTERY_PLUGGED_USB:

acString = "plugged usb";

break;

}

String log = "status = " + statusString + "/n"

"health = " + healthString + "/n"

"present = " + String.valueOf(present) + "/n"

"level = " + String.valueOf(level) + "/n"

"scale = " + String.valueOf(scale) + "/n"

"icon_small = "+ String.valueOf(icon_small) + "/n"

"plugged = " + acString + "/n"

//+ "voltage = " + String.valueOf(voltage) + "/n"

"voltage = " + Integer.toString(voltage) + "/n"

"temperature = " + String.valueOf(temperature) + "/n"

"technology = "+ technology;

m_txtMsg.setText(log);

}

}

};

} 
原创粉丝点击