您的位置:首页 > 移动开发 > Android开发

Battery workflow in Android 2.3

2015-12-25 17:40 302 查看


针对以上流程图做以下几点说明:

1.

电池的充电状态、温度、电压以及各种状态信息是由!BatteryService来显示的,但真正的数据来源是由内核提供的,它运行在system_process进程当中。

2.

!BatteryService通过JNI读取内核数据信息。它通过JNI注册的不仅有函数,而且也有变量,应该说他们是通用的,JNI的com_android_server_BatteryService.cpp中操作的其实也是BatteryService.java中声明的变量。

在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;

在JNI com_android_server_BatteryService.cpp

struct FieldIds {

jfieldID mAcOnline;

jfieldID mUsbOnline;

jfieldID mBatteryStatus;

jfieldID mBatteryHealth;

jfieldID mBatteryPresent;

jfieldID mBatteryLevel;

jfieldID mBatteryVoltage;

jfieldID mBatteryTemperature;

jfieldID mBatteryTechnology;

};

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”);

3.

以上数据信息是通过sys文件系统的属性文件来获得的,对应每一个数据值都有一个指定的路径;

define POWER_SUPPLY_PATH “/sys/class/power_supply”

struct PowerSupplyPaths {

char* acOnlinePath;

char* usbOnlinePath;

char* batteryStatusPath;

char* batteryHealthPath;

char* batteryPresentPath;

char* batteryCapacityPath;

char* batteryVoltagePath;

char* batteryTemperaturePath;

char* batteryTechnologyPath;

};

那么batterystatusPath对应的路径:”/sys/class/power_supply/battery/status”;

batteryHealthPath 对应的路径:”/sys/class/power_supply/battery/health”

…..

4.

电池的信息会随着时间不停变化,这在上层需要考虑实时的更新电池的数据信息。所以在!BatteryService启动的时候,通过UEventObserver启动了一个UEventThread线程。

每一个Process最多只能一个UEventThread,即使这个process有多个UEventObserver的实例。当在一个Process中,第一次调用startObserving()方法后,这个UEventThread就启动了,

而这个线程一旦启动之后,将不会停止。从图中我们看到,线程启动后,它会监视是否有事件上报,一旦kernel有uevent报上来之后,线程就会触发onUEvent,而onUEvent调用的是update函数,再次调用native_update,通过JNI访问sysfs系统下的Power_supply的属性信息,我们知道sysfs提供了内核与用户空间信息交流的接口,而内核空间的属性操作show函数会及时的把最新的数据信息编码后放到指定的buffer,以供用户层访问。在内核空间对此进行处理的函数为:power_supply_show_property ;

define POWER_SUPPLY_ATTR(_name) \

{ \

.attr = { .name = #_name, .mode = 0444 }, \

.show = power_supply_show_property, \

.store = NULL, \

}

static ssize_t power_supply_show_property(struct device *dev,

struct device_attribute *attr,

char *buf) {

static char *status_text[] = {

“Unknown”, “Charging”, “Discharging”, “Not charging”, “Full”

};

struct power_supply *psy = dev_get_drvdata(dev);

const ptrdiff_t off = attr - power_supply_attrs;

union power_supply_propval value;

ret = psy->get_property(psy, off, &value);

if (off == POWER_SUPPLY_PROP_STATUS)

return sprintf(buf, “%s\n”, status_text[value.intval]);

else if (off == POWER_SUPPLY_PROP_CHARGE_TYPE)

return sprintf(buf, “%s\n”, charge_type[value.intval]);

else if (off == POWER_SUPPLY_PROP_HEALTH)

return sprintf(buf, “%s\n”, health_text[value.intval]);

else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)

return sprintf(buf, “%s\n”, technology_text[value.intval]);

else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)

return sprintf(buf, “%s\n”, capacity_level_text[value.intval]);

else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)

return sprintf(buf, “%s\n”, value.strval);

return sprintf(buf, “%d\n”, value.intval);

}

当用户层想要读取文件信息时,会调用属性信息的show函数,在这里也就是power_supply_show_property()函数将变化的信息提供给应用层。

何时去更新数据

在UEventThread线程中,在onUevent函数之前会一直调用一个next_event函数,这个函数会一直等待接受来自内核的通过netlink socket上报的battery信息。一旦内核空间向用户空间广播uevent,它就会接受,接受后会去update数据信息,以上已经讲过update的过程。

内核是如何发送uevent事件的?

在battery驱动里面,需要实时的更新数据信息,并且调用power_supply_core.c的一个工作队列power_supply_changed_work,在这个里面会发送一个uevent事件,它会将ACTION=CHANGE以及SUBSYSTEM=POWER_SUPPLY 的信息通过socket的netlink_broadcast广播到用户空间,当observer监测到后会作进一步的处理。

以上只是对框图中的信息进行一下简要说明,关于更多的细节信息不在这里一一陈述,一切都在源码里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: