android6.0系统Healthd深入分析( 三 )

当epoll_waite接受到gBinderfd,wakealarm_fd,uevent_fd其中的事件,便会将监听到的事件加入到event数组中 。在for循环中做处理,for循环中代码看起来非常难懂,其实if判断的便是event有没有相应的处理函数,在前面注册事件时候已经提到,三种句柄上的事件都有对应的处理函数,也就是当收到gBinderfd上的事件,便用binder_event函数处理,当收到uevent_fd上的事件便用uevent_event处理,当收到wakealarm_fd上的事件便用wakealarm_event处理 。
这里以较为重要的uevent_event事件处理为例:
#define UEVENT_MSG_LEN 2048 static void uevent_event(uint32_t /*epevents*/) { char msg[UEVENT_MSG_LEN+2];char *cp;int n;n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);if (n <= 0)return;if (n >= UEVENT_MSG_LEN) /* overflow -- discard */return;msg[n] = '';msg[n+1] = '';cp = msg;while (*cp) {if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {healthd_battery_update();break;}/* advance to after the next*/while (*cp++);} }处理函数首先从uevent_fd 获取事件数目,然后循环判断是否是来自与power_supply目录下的事件,如果是,则调用到healthd_battery_update中去更新电池状态 。
更新电池状态
当收到事件,做一些判断工作便需要更新电池状态,其更新函数为healthd.cpp下的healthd_battery_update函数,但是主要更新并不在heathd中完成的,而是在BatteryMonitor中的update函数,其代码较多,分段分析:
props.chargerAcOnline = false; props.chargerUsbOnline = false; props.chargerWirelessOnline = false; props.batteryStatus = BATTERY_STATUS_UNKNOWN; props.batteryHealth = BATTERY_HEALTH_UNKNOWN;if (!mHealthdConfig->batteryPresentPath.isEmpty()) props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath); elseprops.batteryPresent = mBatteryDevicePresent;props.batteryLevel = mBatteryFixedCapacity ?mBatteryFixedCapacity :getIntField(mHealthdConfig->batteryCapacityPath); props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;props.batteryTemperature = mBatteryFixedTemperature ?mBatteryFixedTemperature :getIntField(mHealthdConfig->batteryTemperaturePath); const int SIZE = 128; char buf[SIZE]; String8 btech;if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)props.batteryStatus = getBatteryStatus(buf);if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)props.batteryHealth = getBatteryHealth(buf);if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)props.batteryTechnology = String8(buf);在init函数中将healthd_config 对象传入,并且将里面的成员的一些地址信息去初始化保存起来 。主要是保存一些地址信息,以及充电方式 。在BatteryMonitor初始化中,heathd_config传入init函数中,赋值为mHealthdConfig,上面一段主要是读取/sys/class/power_supply下的文件节点信息初更新电池数据属性值,
path.AppendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,mChargerNames[i].string());if (readFromFile(path, buf, SIZE) > 0) { if (buf[0] != '0') {path.clear();path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,mChargerNames[i].string());switch(readPowerSupplyType(path)) {case ANDROID_POWER_SUPPLY_TYPE_AC:props.chargerAcOnline = true;break;case ANDROID_POWER_SUPPLY_TYPE_USB:props.chargerUsbOnline = true;break;case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:props.chargerWirelessOnline = true;break;default:KLOG_WARNING(LOG_TAG, "%s: Unknown power supply typen",mChargerNames[i].string());}} }将电池当前的电量级别,电压,温度,健康状况,电池状态以及充放电倍率存入dmesgline变量中,在后面会将电池充电类型,电池使用时间都以字符串存入dmesgline变量中,然后:
KLOG_WARNING(LOG_TAG, "%sn", dmesgline);//向log记录电池当前各种状态信息}healthd_mode_ops->battery_update(&props);//更新电池return props.chargerAcOnline | props.chargerUsbOnline |props.chargerWirelessOnline;//返回是否在充电状态整个update函数做完更新数据,记录数据到log之后,然后调用到BatteryPropertiesRegistrar的update函数继续更新电池状态,最后返回值为是否处于充电状态 。
BatteryPropertiesRegistrar的update函数未作任何操作调用Healthd_mode_android.cpp中的healthd_mode_android_battery_update函数,我们可以看看该函数
void healthd_mode_android_battery_update(struct android::BatteryProperties *props) {if (gBatteryPropertiesRegistrar != NULL)gBatteryPropertiesRegistrar->notifyListeners(*props);return; }这里这里直接调用到BatteryPropertiesRegistrar的notifyListeners去通知props改变了,props是什么呢?props是定义的一个BatteryProperties属性集,里面的成员变量包含了所有的电池状态信息,在update开始便通过读取各个文件节点的实时数据更新电池属性props,更新完成后通过BatteryPropertiesRegistrar通知其属性监听者去更新状态,但是谁是监听呢?


推荐阅读