先看healthd,healthd直接查看设备节点中各种电池属性,然后调用BatteryService的update函数,下来先看healthd的代码。
int main(int argc, char **argv) { int ch; klog_set_level(KLOG_LEVEL); while ((ch = getopt(argc, argv, "n")) != -1) { switch (ch) { case 'n': nosvcmgr = true; break; case '?': default: KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch); } } healthd_board_init(&healthd_config); wakealarm_init(); uevent_init(); binder_init(); //建BatteryMonitor对象,及初始化 gBatteryMonitor = new BatteryMonitor(); gBatteryMonitor->init(&healthd_config, nosvcmgr); //主函数、用epoll不断循环看有没有事件,有事件直接到battery_update healthd_mainloop(); return 0; }
直接调用battery_update函数,主要设置了电池状态检查的时间,以及调用BatteryMonitor的update函数。
static void battery_update(void) { // Fast wake interval when on charger (watch for overheat); // slow wake interval when on battery (watch for drained battery). //直接调用BatteryMonitor的update函数,如果在充电就将循环监控的时间设短,没在充电就长些 int new_wake_interval = gBatteryMonitor->update() ? healthd_config.periodic_chores_interval_fast : healthd_config.periodic_chores_interval_slow; if (new_wake_interval != wakealarm_wake_interval) wakealarm_set_interval(new_wake_interval); // During awake periods poll at fast rate. If wake alarm is set at fast // rate then just use the alarm; if wake alarm is set at slow rate then // poll at fast rate while awake and let alarm wake up at slow rate when // asleep. if (healthd_config.periodic_chores_interval_fast == -1) awake_poll_interval = -1; else awake_poll_interval = new_wake_interval == healthd_config.periodic_chores_interval_fast ? -1 : healthd_config.periodic_chores_interval_fast * 1000; }
init函数主要是保存一些地址信息,以及充电方式。
void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) { String8 path; mHealthdConfig = hc; DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH); if (dir == NULL) { KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH); } else { struct dirent* entry; while ((entry = readdir(dir))) { const char* name = entry->d_name; if (!strcmp(name, ".") || !strcmp(name, "..")) continue; char buf[20]; // Look for "type" file in each subdirectory path.clear(); path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name); //先根据sys/power/../type 来看是属于两个类型的 switch(readPowerSupplyType(path)) { case ANDROID_POWER_SUPPLY_TYPE_AC: //保存地址 if (mHealthdConfig->acChargeHeathPath.isEmpty()) { path.clear(); path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name); if (access(path, R_OK) == 0) mHealthdConfig->acChargeHeathPath = path; } path.clear(); path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); if (access(path.string(), R_OK) == 0) //充电方式都保存起来 mChargerNames.add(String8(name)); break; case ANDROID_POWER_SUPPLY_TYPE_USB: if (mHealthdConfig->usbChargeHeathPath.isEmpty()) { path.clear(); path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name); if (access(path, R_OK) == 0) mHealthdConfig->usbChargeHeathPath = path; } path.clear(); path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); if (access(path.string(), R_OK) == 0) mChargerNames.add(String8(name)); break; case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: path.clear(); path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); if (access(path.string(), R_OK) == 0) mChargerNames.add(String8(name)); break; case ANDROID_POWER_SUPPLY_TYPE_BATTERY: //电池状态的各个信息保存起来 if (mHealthdConfig->batteryStatusPath.isEmpty()) { path.clear(); path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, name); if (access(path, R_OK) == 0) mHealthdConfig->batteryStatusPath = path; } if (mHealthdConfig->batteryHealthPath.isEmpty()) { path.clear(); path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name); if (access(path, R_OK) == 0) mHealthdConfig->batteryHealthPath = path; } if (mHealthdConfig->batteryPresentPath.isEmpty()) { path.clear(); path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, name); if (access(path, R_OK) == 0) mHealthdConfig->batteryPresentPath = path; } 。。。 if (nosvcmgr == false) { \\这里其实封装了binder,用于和batterservice通信 mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this); mBatteryPropertiesRegistrar->publish(); }
接下来调用update函数,代码如下:
bool BatteryMonitor::update(void) { struct BatteryProperties props; bool logthis; props.chargerAcOnline = false; props.chargerUsbOnline = false; props.chargerWirelessOnline = false; props.batteryStatus = BATTERY_STATUS_UNKNOWN; props.batteryHealth = BATTERY_HEALTH_UNKNOWN; props.batteryCurrentNow = INT_MIN; props.batteryChargeCounter = INT_MIN; //用前面init中获取到的地址保存各种电池状态信息 if (!mHealthdConfig->batteryPresentPath.isEmpty()) props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath); else props.batteryPresent = true; props.batteryLevel = getIntField(mHealthdConfig->batteryCapacityPath); props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000; if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath); if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath); props.batteryTemperature = 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); if (readFromFile(mHealthdConfig->acChargeHeathPath, buf, SIZE) > 0) props.acChargeHeath= String8(buf); if (readFromFile(mHealthdConfig->usbChargeHeathPath, buf, SIZE) > 0) props.usbChargeHeath= String8(buf); unsigned int i; //利用init中保存的各个充电方式,看是哪个在充电 for (i = 0; i < mChargerNames.size(); i++) { String8 path; 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 type\n", mChargerNames[i].string()); } } } } logthis = !healthd_board_battery_update(&props); if (logthis) { char dmesgline[256]; snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d", props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "", abs(props.batteryTemperature / 10), abs(props.batteryTemperature % 10), props.batteryHealth, props.batteryStatus); if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { char b[20]; snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000); strlcat(dmesgline, b, sizeof(dmesgline)); } KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline, props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "", props.chargerWirelessOnline ? "w" : ""); } if (mBatteryPropertiesRegistrar != NULL) //利用binder封装,传数据到BatteryService mBatteryPropertiesRegistrar->notifyListeners(props); //返回是否在充电,用来电池循环检查的时间间隔设置 return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline; }
如此healthd差不多分析完了,接下来看BatteryService分析。