先看healthd,healthd直接查看設備節點中各類電池屬性,而後調用BatteryService的update函數,下來先看healthd的代碼。app
- 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函數。less
- 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函數,代碼以下:oop
- 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分析。this