android4.4 healthd深刻分析

先看healthd,healthd直接查看設備節點中各類電池屬性,而後調用BatteryService的update函數,下來先看healthd的代碼。app

  1. int main(int argc, char **argv) {  
  2.     int ch;  
  3.   
  4.     klog_set_level(KLOG_LEVEL);  
  5.   
  6.     while ((ch = getopt(argc, argv, "n")) != -1) {  
  7.         switch (ch) {  
  8.         case 'n':  
  9.             nosvcmgr = true;  
  10.             break;  
  11.         case '?':  
  12.         default:  
  13.             KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch);  
  14.         }  
  15.     }  
  16.   
  17.     healthd_board_init(&healthd_config);  
  18.     wakealarm_init();  
  19.     uevent_init();  
  20.     binder_init();  
  21.     //建BatteryMonitor對象,及初始化  
  22.     gBatteryMonitor = new BatteryMonitor();  
  23.     gBatteryMonitor->init(&healthd_config, nosvcmgr);  
  24.     //主函數、用epoll不斷循環看有沒有事件,有事件直接到battery_update  
  25.     healthd_mainloop();  
  26.     return 0;  
  27. }  


 

 

直接調用battery_update函數,主要設置了電池狀態檢查的時間,以及調用BatteryMonitor的update函數。less

  1. static void battery_update(void) {  
  2.     // Fast wake interval when on charger (watch for overheat);  
  3.     // slow wake interval when on battery (watch for drained battery).  
  4.       
  5.     //直接調用BatteryMonitor的update函數,若是在充電就將循環監控的時間設短,沒在充電就長些  
  6.    int new_wake_interval = gBatteryMonitor->update() ?  
  7.        healthd_config.periodic_chores_interval_fast :  
  8.            healthd_config.periodic_chores_interval_slow;  
  9.   
  10.     if (new_wake_interval != wakealarm_wake_interval)  
  11.             wakealarm_set_interval(new_wake_interval);  
  12.   
  13.     // During awake periods poll at fast rate.  If wake alarm is set at fast  
  14.     // rate then just use the alarm; if wake alarm is set at slow rate then  
  15.     // poll at fast rate while awake and let alarm wake up at slow rate when  
  16.     // asleep.  
  17.   
  18.     if (healthd_config.periodic_chores_interval_fast == -1)  
  19.         awake_poll_interval = -1;  
  20.     else  
  21.         awake_poll_interval =  
  22.             new_wake_interval == healthd_config.periodic_chores_interval_fast ?  
  23.                 -1 : healthd_config.periodic_chores_interval_fast * 1000;  
  24. }  


 

 

init函數主要是保存一些地址信息,以及充電方式。函數

  1. void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) {  
  2.     String8 path;  
  3.   
  4.     mHealthdConfig = hc;  
  5.     DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);  
  6.     if (dir == NULL) {  
  7.         KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);  
  8.     } else {  
  9.         struct dirent* entry;  
  10.   
  11.         while ((entry = readdir(dir))) {  
  12.             const char* name = entry->d_name;  
  13.   
  14.             if (!strcmp(name, ".") || !strcmp(name, ".."))  
  15.                 continue;  
  16.   
  17.             char buf[20];  
  18.             // Look for "type" file in each subdirectory  
  19.             path.clear();  
  20.             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);  
  21.             //先根據sys/power/../type 來看是屬於兩個類型的  
  22.             switch(readPowerSupplyType(path)) {  
  23.             case ANDROID_POWER_SUPPLY_TYPE_AC:  
  24.                 //保存地址  
  25.                 if (mHealthdConfig->acChargeHeathPath.isEmpty()) {  
  26.                     path.clear();  
  27.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  28.                                       name);  
  29.                     if (access(path, R_OK) == 0)  
  30.                         mHealthdConfig->acChargeHeathPath = path;  
  31.                 }  
  32.                 path.clear();  
  33.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  34.                 if (access(path.string(), R_OK) == 0)  
  35.                 //充電方式都保存起來  
  36.                     mChargerNames.add(String8(name));  
  37.                 break;  
  38.   
  39.             case ANDROID_POWER_SUPPLY_TYPE_USB:  
  40.                 if (mHealthdConfig->usbChargeHeathPath.isEmpty()) {  
  41.                     path.clear();  
  42.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  43.                                       name);  
  44.                     if (access(path, R_OK) == 0)  
  45.                         mHealthdConfig->usbChargeHeathPath = path;  
  46.                 }  
  47.                 path.clear();  
  48.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  49.                 if (access(path.string(), R_OK) == 0)  
  50.                     mChargerNames.add(String8(name));  
  51.                 break;  
  52.   
  53.             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:  
  54.                 path.clear();  
  55.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  56.                 if (access(path.string(), R_OK) == 0)  
  57.                     mChargerNames.add(String8(name));  
  58.                 break;  
  59.   
  60.             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:  
  61.                 //電池狀態的各個信息保存起來  
  62.                 if (mHealthdConfig->batteryStatusPath.isEmpty()) {  
  63.                     path.clear();  
  64.                     path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,  
  65.                                       name);  
  66.                     if (access(path, R_OK) == 0)  
  67.                         mHealthdConfig->batteryStatusPath = path;  
  68.                 }  
  69.   
  70.                 if (mHealthdConfig->batteryHealthPath.isEmpty()) {  
  71.                     path.clear();  
  72.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  73.                                       name);  
  74.                     if (access(path, R_OK) == 0)  
  75.                         mHealthdConfig->batteryHealthPath = path;  
  76.                 }  
  77.   
  78.                 if (mHealthdConfig->batteryPresentPath.isEmpty()) {  
  79.                     path.clear();  
  80.                     path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,  
  81.                                       name);  
  82.                     if (access(path, R_OK) == 0)  
  83.                         mHealthdConfig->batteryPresentPath = path;  
  84.                 }  
  85.   
  86.   
  87. 。。。  
  88.   
  89.   
  90.   
  91.   
  92.     if (nosvcmgr == false) {  
  93.   
  94.            \\這裏其實封裝了binder,用於和batterservice通訊  
  95.             mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);  
  96.             mBatteryPropertiesRegistrar->publish();  
  97.     }  

 

 

接下來調用update函數,代碼以下:oop

  1. bool BatteryMonitor::update(void) {  
  2.     struct BatteryProperties props;  
  3.     bool logthis;  
  4.       
  5.     props.chargerAcOnline = false;  
  6.     props.chargerUsbOnline = false;  
  7.     props.chargerWirelessOnline = false;  
  8.     props.batteryStatus = BATTERY_STATUS_UNKNOWN;  
  9.     props.batteryHealth = BATTERY_HEALTH_UNKNOWN;  
  10.     props.batteryCurrentNow = INT_MIN;  
  11.     props.batteryChargeCounter = INT_MIN;  
  12.     //用前面init中獲取到的地址保存各類電池狀態信息  
  13.     if (!mHealthdConfig->batteryPresentPath.isEmpty())  
  14.         props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);  
  15.     else  
  16.         props.batteryPresent = true;  
  17.   
  18.     props.batteryLevel = getIntField(mHealthdConfig->batteryCapacityPath);  
  19.     props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;  
  20.   
  21.     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())  
  22.         props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);  
  23.   
  24.     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())  
  25.         props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);  
  26.   
  27.     props.batteryTemperature = getIntField(mHealthdConfig->batteryTemperaturePath);  
  28.   
  29.     const int SIZE = 128;  
  30.     char buf[SIZE];  
  31.     String8 btech;  
  32.   
  33.     if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)  
  34.         props.batteryStatus = getBatteryStatus(buf);  
  35.   
  36.     if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)  
  37.         props.batteryHealth = getBatteryHealth(buf);  
  38.   
  39.     if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)  
  40.         props.batteryTechnology = String8(buf);  
  41.   
  42.     if (readFromFile(mHealthdConfig->acChargeHeathPath, buf, SIZE) > 0)  
  43.         props.acChargeHeath= String8(buf);  
  44.   
  45.     if (readFromFile(mHealthdConfig->usbChargeHeathPath, buf, SIZE) > 0)  
  46.         props.usbChargeHeath= String8(buf);  
  47.   
  48.     unsigned int i;  
  49.     //利用init中保存的各個充電方式,看是哪一個在充電  
  50.     for (i = 0; i < mChargerNames.size(); i++) {  
  51.         String8 path;  
  52.         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,  
  53.                           mChargerNames[i].string());  
  54.   
  55.         if (readFromFile(path, buf, SIZE) > 0) {  
  56.             if (buf[0] != '0') {  
  57.                 path.clear();  
  58.                 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,  
  59.                                   mChargerNames[i].string());  
  60.                 switch(readPowerSupplyType(path)) {  
  61.                 case ANDROID_POWER_SUPPLY_TYPE_AC:  
  62.                     props.chargerAcOnline = true;  
  63.                     break;  
  64.                 case ANDROID_POWER_SUPPLY_TYPE_USB:  
  65.                     props.chargerUsbOnline = true;  
  66.                     break;  
  67.                 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:  
  68.                     props.chargerWirelessOnline = true;  
  69.                     break;  
  70.                 default:  
  71.                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",  
  72.                                  mChargerNames[i].string());  
  73.                 }  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     logthis = !healthd_board_battery_update(&props);  
  79.   
  80.     if (logthis) {  
  81.         char dmesgline[256];  
  82.         snprintf(dmesgline, sizeof(dmesgline),  
  83.                  "battery l=%d v=%d t=%s%d.%d h=%d st=%d",  
  84.                  props.batteryLevel, props.batteryVoltage,  
  85.                  props.batteryTemperature < 0 ? "-" : "",  
  86.                  abs(props.batteryTemperature / 10),  
  87.                  abs(props.batteryTemperature % 10), props.batteryHealth,  
  88.                  props.batteryStatus);  
  89.   
  90.         if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  91.             char b[20];  
  92.   
  93.             snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);  
  94.             strlcat(dmesgline, b, sizeof(dmesgline));  
  95.         }  
  96.   
  97.         KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,  
  98.                   props.chargerAcOnline ? "a" : "",  
  99.                   props.chargerUsbOnline ? "u" : "",  
  100.                   props.chargerWirelessOnline ? "w" : "");  
  101.     }  
  102.   
  103.     if (mBatteryPropertiesRegistrar != NULL)  
  104.         //利用binder封裝,傳數據到BatteryService  
  105.         mBatteryPropertiesRegistrar->notifyListeners(props);  
  106.     //返回是否在充電,用來電池循環檢查的時間間隔設置  
  107.     return props.chargerAcOnline | props.chargerUsbOnline |  
  108.             props.chargerWirelessOnline;  
  109.  }  

如此healthd差很少分析完了,接下來看BatteryService分析。this

相關文章
相關標籤/搜索