分享

深入分析android5.1 healthd

 写意人生 2015-11-13

转自:http://blog.csdn.net/kc58236582/article/details/47300413

healthd主要是读取电池节点的信息,传给BatteryService。或者在关机充电等使用。注意healthd中使用的是kernel的log。

下面先从main函数分析

  1. int main(int argc, char **argv) {  
  2.     int ch;  
  3.     int ret;  
  4.   
  5.     klog_set_level(KLOG_LEVEL);  
  6.     healthd_mode_ops = &android_ops;  
  7.   
  8.     if (!strcmp(basename(argv[0]), "charger")) {//解析输入参数如果是charger的使用charger_ops,这里就不做介绍  
  9.         healthd_mode_ops = &charger_ops;  
  10.     } else {  
  11.         while ((ch = getopt(argc, argv, "cr")) != -1) {//分析输入命令,各个命令对应不同的charger_ops  
  12.             switch (ch) {  
  13.             case 'c':  
  14.                 healthd_mode_ops = &charger_ops;  
  15.                 break;  
  16.             case 'r':  
  17.                 healthd_mode_ops = &recovery_ops;  
  18.                 break;  
  19.             case '?':  
  20.             default:  
  21.                 KLOG_ERROR(LOG_TAG, "Unrecognized healthd option: %c\n",  
  22.                            optopt);  
  23.                 exit(1);  
  24.             }  
  25.         }  
  26.     }  
  27.   
  28.     ret = healthd_init();//healthd做初始化  
  29.     if (ret) {  
  30.         KLOG_ERROR("Initialization failed, exiting\n");  
  31.         exit(2);  
  32.     }  
  33.   
  34.     healthd_mainloop();//主函数  
  35.     KLOG_ERROR("Main loop terminated, exiting\n");  
  36.     return 3;  
  37. }  

如果是正常开机,不走关机充电等,healthd_mode_ops = &android_ops;而这里面具体的函数在后面进行详细的介绍。

  1. static struct healthd_mode_ops android_ops = {  
  2.     .init = healthd_mode_android_init,  
  3.     .preparetowait = healthd_mode_android_preparetowait,  
  4.     .heartbeat = healthd_mode_nop_heartbeat,  
  5.     .battery_update = healthd_mode_android_battery_update,  
  6. };  

下面分析下healthd_init函数,heathd使用了epoll进行IO复用。

  1. static int healthd_init() {  
  2.     epollfd = epoll_create(MAX_EPOLL_EVENTS);  
  3.     if (epollfd == -1) {  
  4.         KLOG_ERROR(LOG_TAG,  
  5.                    "epoll_create failed; errno=%d\n",  
  6.                    errno);  
  7.         return -1;  
  8.     }  
  9.   
  10.     healthd_board_init(&healthd_config);  
  11.     healthd_mode_ops->init(&healthd_config);  
  12.     wakealarm_init();  
  13.     uevent_init();  
  14.     gBatteryMonitor = new BatteryMonitor();  
  15.     gBatteryMonitor->init(&healthd_config);  
  16.     return 0;  
  17. }  


这里的healthd_mode_ops->init的函数是android_ops 的healthd_mode_android_init函数,这里主要是将binder通信的fd也加入epoll,而不像普通binder进程最后使用IPCThreadState::self()->joinThreadPool。这样所有的fd全在epoll管理,只用了一个线程

  1. int healthd_mode_android_preparetowait(void) {  
  2.     IPCThreadState::self()->flushCommands();  
  3.     return -1;  
  4. }  
  5.   
  6. static void binder_event(uint32_t /*epevents*/) {  
  7.     IPCThreadState::self()->handlePolledCommands();  
  8. }  
  9.   
  10. void healthd_mode_android_init(struct healthd_config* /*config*/) {  
  11.     ProcessState::self()->setThreadPoolMaxThreadCount(0);  
  12.     IPCThreadState::self()->disableBackgroundScheduling(true);  
  13.     IPCThreadState::self()->setupPolling(&gBinderFd);  
  14.   
  15.     if (gBinderFd >= 0) {  
  16.         if (healthd_register_event(gBinderFd, binder_event))  
  17.             KLOG_ERROR(LOG_TAG,  
  18.                        "Register for binder events failed\n");  
  19.     }  
  20.   
  21.     gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar();  
  22.     gBatteryPropertiesRegistrar->publish();  
  23. }  

gBatteryPropertiesRegistrar->publish将"batteryproperties"这个Service加入到ServiceManager中

  1. void BatteryPropertiesRegistrar::publish() {  
  2.     defaultServiceManager()->addService(String16("batteryproperties"), this);  
  3. }  

接下来再来看下wakealarm_init

  1. static void wakealarm_init(void) {  
  2.     wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);  
  3.     if (wakealarm_fd == -1) {  
  4.         KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");  
  5.         return;  
  6.     }  
  7.   
  8.     if (healthd_register_event(wakealarm_fd, wakealarm_event))  
  9.         KLOG_ERROR(LOG_TAG,  
  10.                    "Registration of wakealarm event failed\n");  
  11.   
  12.     wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);  
  13. }  

wakealarm_init设置alarm唤醒的interval,再来看下时间处理函数

  1. static void wakealarm_event(uint32_t /*epevents*/) {  
  2.     unsigned long long wakeups;  
  3.   
  4.     if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {//出错结束  
  5.         KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n");  
  6.         return;  
  7.     }  
  8.     KLOG_ERROR(LOG_TAG, "wakealarm_event\n");  
  9.     periodic_chores();  
  10. }  
  1. static void periodic_chores() {  
  2.     healthd_battery_update();  
  3. }  
  1. void healthd_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.     KLOG_ERROR(LOG_TAG, "healthd_battery_update enter\n");  
  5.    int new_wake_interval = gBatteryMonitor->update() ?//调用主要的update函数,根据返回值,如果当前在充电返回true  
  6.        healthd_config.periodic_chores_interval_fast ://时间设置1分钟  
  7.            healthd_config.periodic_chores_interval_slow;  
  8.     KLOG_ERROR(LOG_TAG, "kangchen healthd_battery_update after\n");  
  9.     if (new_wake_interval != wakealarm_wake_interval)  
  10.             wakealarm_set_interval(new_wake_interval);  
  11.   
  12.     // During awake periods poll at fast rate.  If wake alarm is set at fast  
  13.     // rate then just use the alarm; if wake alarm is set at slow rate then  
  14.     // poll at fast rate while awake and let alarm wake up at slow rate when  
  15.     // asleep.  
  16.   
  17.     if (healthd_config.periodic_chores_interval_fast == -1)  
  18.         awake_poll_interval = -1;  
  19.     else  
  20.         awake_poll_interval =  
  21.             new_wake_interval == healthd_config.periodic_chores_interval_fast ?//当前时间是一分钟,epoll为永远阻塞,否则为1分钟  
  22.                 -1 : healthd_config.periodic_chores_interval_fast * 1000;  
  23. }  

接下来再来看看uEvent的,

  1. static void uevent_init(void) {  
  2.     uevent_fd = uevent_open_socket(64*1024, true);  
  3.   
  4.     if (uevent_fd < 0) {  
  5.         KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");  
  6.         return;  
  7.     }  
  8.       
  9.     fcntl(uevent_fd, F_SETFL, O_NONBLOCK);  
  10.     if (healthd_register_event(uevent_fd, uevent_event))  
  11.         KLOG_ERROR(LOG_TAG,  
  12.                    "register for uevent events failed\n");  
  13. }  

看看uevent_event的处理函数,获取uevent后主要判断是否是电源系统的,如果是调用healthd_battery_update函数

  1. static void uevent_event(uint32_t /*epevents*/) {  
  2.     char msg[UEVENT_MSG_LEN+2];  
  3.     char *cp;  
  4.     int n;  
  5.   
  6.     n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);  
  7.     if (n <= 0)  
  8.         return;  
  9.     if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */  
  10.         return;  
  11.   
  12.     msg[n] = '\0';  
  13.     msg[n+1] = '\0';  
  14.     cp = msg;  
  15.     KLOG_ERROR(LOG_TAG, "uevent_event\n");  
  16.     while (*cp) {  
  17.         if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {//是这个子系统的调用healthd_battery_update函数  
  18.             healthd_battery_update();  
  19.             break;  
  20.         }  
  21.   
  22.         /* advance to after the next \0 */  
  23.         while (*cp++)  
  24.             ;  
  25.     }  
  26. }  


下面分析下healthd_mainloop这个主函数,主函数主要是epoll函数监听3个fd,有事件就处理。

  1. static void healthd_mainloop(void) {  
  2.     while (1) {  
  3.         struct epoll_event events[eventct];  
  4.         int nevents;  
  5.         int timeout = awake_poll_interval;  
  6.         int mode_timeout;  
  7.   
  8.         mode_timeout = healthd_mode_ops->preparetowait();  
  9.         if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout))  
  10.             timeout = mode_timeout;  
  11.         nevents = epoll_wait(epollfd, events, eventct, timeout);//epoll_wait等待各个fd的事件,timeout为超时时间  
  12.         KLOG_ERROR(LOG_TAG, "kangchen healthd_mainloop epoll_wait\n");  
  13.         if (nevents == -1) {  
  14.             if (errno == EINTR)  
  15.                 continue;  
  16.             KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");  
  17.             break;  
  18.         }  
  19.   
  20.         for (int n = 0; n < nevents; ++n) {  
  21.             if (events[n].data.ptr)//遍历各个fd的事件上来,每个处理函数处理  
  22.                 (*(void (*)(int))events[n].data.ptr)(events[n].events);  
  23.         }  
  24.   
  25.         if (!nevents)//当什么事件没有的时候,是因为epoll超时设置走下来的,这时候也要update下  
  26.             periodic_chores();  
  27.   
  28.         healthd_mode_ops->heartbeat();  
  29.     }  
  30.   
  31.     return;  
  32. }  


init函数主要将healthd_config 对象传入,并且将里面的成员的一些地址信息去初始化保存起来。主要是保存一些地址信息,以及充电方式。

  1. void BatteryMonitor::init(struct healthd_config *hc) {  
  2.     String8 path;  
  3.     char pval[PROPERTY_VALUE_MAX];  
  4.   
  5.     mHealthdConfig = hc;//将外面传进来的heathdconfig的指针赋给成员变量  
  6.     DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);//打开地址 /sys/class/power_supply  
  7.     if (dir == NULL) {  
  8.         KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);  
  9.     } else {  
  10.         struct dirent* entry;  
  11.   
  12.         while ((entry = readdir(dir))) {  
  13.             const char* name = entry->d_name;  
  14.   
  15.             if (!strcmp(name, ".") || !strcmp(name, ".."))  
  16.                 continue;  
  17.   
  18.             char buf[20];  
  19.             // Look for "type" file in each subdirectory  
  20.             path.clear();  
  21.             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);  
  22.             switch(readPowerSupplyType(path)) {//读取各个目录下type的值,比如/sys/class/power_supply/battery 下type的值为Battery,在readPowerSupplyType读取并且转化为ANDROID_POWER_SUPPLY_TYPE_BATTERY  
  23.             case ANDROID_POWER_SUPPLY_TYPE_AC:  
  24.                 if (mHealthdConfig->acChargeHeathPath.isEmpty()) {  
  25.                     path.clear();  
  26.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  27.                                       name);  
  28.                     if (access(path, R_OK) == 0)  
  29.                         mHealthdConfig->acChargeHeathPath = path;//配置路径  
  30.                 }  
  31.                 path.clear();  
  32.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  33.                 if (access(path.string(), R_OK) == 0)  
  34.                     mChargerNames.add(String8(name));//chargername 就是当前目录名字:ac  
  35.                 break;  
  36.   
  37.             case ANDROID_POWER_SUPPLY_TYPE_USB://usb 类似ac  
  38.                 if (mHealthdConfig->usbChargeHeathPath.isEmpty()) {  
  39.                     path.clear();  
  40.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  41.                                       name);  
  42.                     if (access(path, R_OK) == 0)  
  43.                         mHealthdConfig->usbChargeHeathPath = path;  
  44.                 }  
  45.                 path.clear();  
  46.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  47.                 if (access(path.string(), R_OK) == 0)  
  48.                     mChargerNames.add(String8(name));  
  49.                 break;  
  50.   
  51.             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS://类似  
  52.                 path.clear();  
  53.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  54.                 if (access(path.string(), R_OK) == 0)  
  55.                     mChargerNames.add(String8(name));  
  56.                 break;  
  57.   
  58.             case ANDROID_POWER_SUPPLY_TYPE_BATTERY://battery  
  59.                 mBatteryDevicePresent = true;  
  60.   
  61.                 if (mHealthdConfig->batteryStatusPath.isEmpty()) {  
  62.                     path.clear();  
  63.                     path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,  
  64.                                       name);  
  65.                     if (access(path, R_OK) == 0)  
  66.                         mHealthdConfig->batteryStatusPath = path;  
  67.                 }  
  68.   
  69.                 if (mHealthdConfig->batteryHealthPath.isEmpty()) {  
  70.                     path.clear();  
  71.                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,  
  72.                                       name);  
  73.                     if (access(path, R_OK) == 0)  
  74.                         mHealthdConfig->batteryHealthPath = path;  
  75.                 }  
  76.   
  77.                 if (mHealthdConfig->batteryPresentPath.isEmpty()) {  
  78.                     path.clear();  
  79.                     path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,  
  80.                                       name);  
  81.                     if (access(path, R_OK) == 0)  
  82.                         mHealthdConfig->batteryPresentPath = path;  
  83.                 }  
  84.   
  85.                 if (mHealthdConfig->batteryCapacityPath.isEmpty()) {  
  86.                     path.clear();  
  87.                     path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,  
  88.                                       name);  
  89.                     if (access(path, R_OK) == 0)  
  90.                         mHealthdConfig->batteryCapacityPath = path;  
  91.                 }  
  92.   
  93.                 if (mHealthdConfig->batteryVoltagePath.isEmpty()) {  
  94.                     path.clear();  
  95.                     path.appendFormat("%s/%s/voltage_now",  
  96.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  97.                     if (access(path, R_OK) == 0) {  
  98.                         mHealthdConfig->batteryVoltagePath = path;  
  99.                     } else {  
  100.                         path.clear();  
  101.                         path.appendFormat("%s/%s/batt_vol",  
  102.                                           POWER_SUPPLY_SYSFS_PATH, name);  
  103.                         if (access(path, R_OK) == 0)  
  104.                             mHealthdConfig->batteryVoltagePath = path;  
  105.                     }  
  106.                 }  
  107.   
  108.                 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  109.                     path.clear();  
  110.                     path.appendFormat("%s/%s/current_now",  
  111.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  112.                     if (access(path, R_OK) == 0)  
  113.                         mHealthdConfig->batteryCurrentNowPath = path;  
  114.                 }  
  115.   
  116.                 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {  
  117.                     path.clear();  
  118.                     path.appendFormat("%s/%s/current_avg",  
  119.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  120.                     if (access(path, R_OK) == 0)  
  121.                         mHealthdConfig->batteryCurrentAvgPath = path;  
  122.                 }  
  123.   
  124.                 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {  
  125.                     path.clear();  
  126.                     path.appendFormat("%s/%s/charge_counter",  
  127.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  128.                     if (access(path, R_OK) == 0)  
  129.                         mHealthdConfig->batteryChargeCounterPath = path;  
  130.                 }  
  131.   
  132.                 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {  
  133.                     path.clear();  
  134.                     path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,  
  135.                                       name);  
  136.                     if (access(path, R_OK) == 0) {  
  137.                         mHealthdConfig->batteryTemperaturePath = path;  
  138.                     } else {  
  139.                         path.clear();  
  140.                         path.appendFormat("%s/%s/batt_temp",  
  141.                                           POWER_SUPPLY_SYSFS_PATH, name);  
  142.                         if (access(path, R_OK) == 0)  
  143.                             mHealthdConfig->batteryTemperaturePath = path;  
  144.                     }  
  145.                 }  
  146.   
  147.                 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {  
  148.                     path.clear();  
  149.                     path.appendFormat("%s/%s/technology",  
  150.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  151.                     if (access(path, R_OK) == 0)  
  152.                         mHealthdConfig->batteryTechnologyPath = path;  
  153.                 }  
  154.   
  155.                 break;  
  156.   
  157.             case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:  
  158.                 break;  
  159.             }  
  160.         }  
  161.         closedir(dir);  
  162.     }  
  163.   
  164.     if (!mChargerNames.size())  
  165.         KLOG_ERROR(LOG_TAG, "No charger supplies found\n");  
  166.     if (!mBatteryDevicePresent) {//主要由battery该成员变量就为true  
  167.         KLOG_WARNING(LOG_TAG, "No battery devices found\n");  
  168.         hc->periodic_chores_interval_fast = -1;  
  169.         hc->periodic_chores_interval_slow = -1;  
  170.     } else {  
  171.         if (mHealthdConfig->batteryStatusPath.isEmpty())  
  172.             KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");  
  173. 。。。。。。。。。。。。。//这里都是一些警告  
  174.     }  
  175.   
  176.     if (property_get("ro.boot.fake_battery", pval, NULL) > 0  
  177.                                                && strtol(pval, NULL, 10) != 0) {  
  178.         mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;  
  179.         mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;  
  180.     }  
  181. }  

下面就是update函数,将数据封装在BatteryProperties 中,并且通过healthd_mode_ops->battery_update把BatteryProperties 发给上层。

  1. bool BatteryMonitor::update(void) {  
  2.     bool logthis;  
  3.   
  4.     props.chargerAcOnline = false;  
  5.     props.chargerUsbOnline = false;  
  6.     props.chargerWirelessOnline = false;  
  7.     props.batteryStatus = BATTERY_STATUS_UNKNOWN;  
  8.     props.batteryHealth = BATTERY_HEALTH_UNKNOWN;  
  9. //都是从之前配置的mHealthd中取地址,读取节点信息,保存到props成员变量中  
  10.     if (!mHealthdConfig->batteryPresentPath.isEmpty())  
  11.         props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);  
  12.     else  
  13.         props.batteryPresent = mBatteryDevicePresent;  
  14.   
  15.     props.batteryLevel = mBatteryFixedCapacity ?  
  16.         mBatteryFixedCapacity :  
  17.         getIntField(mHealthdConfig->batteryCapacityPath);  
  18.     props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;  
  19.   
  20.     props.batteryTemperature = mBatteryFixedTemperature ?  
  21.         mBatteryFixedTemperature :  
  22.         getIntField(mHealthdConfig->batteryTemperaturePath);  
  23.   
  24.     const int SIZE = 128;  
  25.     char buf[SIZE];  
  26.     String8 btech;  
  27.   
  28.     if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)  
  29.         props.batteryStatus = getBatteryStatus(buf);  
  30.   
  31.     if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)  
  32.         props.batteryHealth = getBatteryHealth(buf);  
  33.   
  34.     if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)  
  35.         props.batteryTechnology = String8(buf);  
  36.   
  37.     if (readFromFile(mHealthdConfig->acChargeHeathPath, buf, SIZE) > 0)  
  38.         props.acChargeHeath= String8(buf);  
  39.   
  40.     if (readFromFile(mHealthdConfig->usbChargeHeathPath, buf, SIZE) > 0)  
  41.         props.usbChargeHeath= String8(buf);  
  42.   
  43.     unsigned int i;  
  44.   
  45.     for (i = 0; i < mChargerNames.size(); i++) {//遍历之前保存的各个充电方式  
  46.         String8 path;  
  47.         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,  
  48.                           mChargerNames[i].string());//路径就是每个目录下的online字段,比如/sys/class/power_supply/usb 下的online  
  49.   
  50.         if (readFromFile(path, buf, SIZE) > 0) {  
  51.             if (buf[0] != '0') {//读取online里面的内容,如果当前在usb线上充电,那么usb下online里面的内容为1  
  52.                 path.clear();  
  53.                 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,  
  54.                                   mChargerNames[i].string());//这里看看是哪个type的  
  55.                 switch(readPowerSupplyType(path)) {  
  56.                 case ANDROID_POWER_SUPPLY_TYPE_AC:  
  57.                     props.chargerAcOnline = true;  
  58.                     break;  
  59.                 case ANDROID_POWER_SUPPLY_TYPE_USB://将其值赋成true  
  60.                     props.chargerUsbOnline = true;  
  61.                     break;  
  62.                 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:  
  63.                     props.chargerWirelessOnline = true;  
  64.                     break;  
  65.                 default:  
  66.                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",  
  67.                                  mChargerNames[i].string());  
  68.                 }  
  69.             }  
  70.         }  
  71.     }  
  72.   
  73.     logthis = !healthd_board_battery_update(&props);  
  74.   
  75.     if (logthis) {  
  76.         char dmesgline[256];  
  77.   
  78.         if (props.batteryPresent) {  
  79.             snprintf(dmesgline, sizeof(dmesgline),  
  80.                  "battery l=%d v=%d t=%s%d.%d h=%d st=%d",  
  81.                  props.batteryLevel, props.batteryVoltage,  
  82.                  props.batteryTemperature < 0 ? "-" : "",  
  83.                  abs(props.batteryTemperature / 10),  
  84.                  abs(props.batteryTemperature % 10), props.batteryHealth,  
  85.                  props.batteryStatus);  
  86.   
  87.             if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  88.                 int c = getIntField(mHealthdConfig->batteryCurrentNowPath);  
  89.                 char b[20];  
  90.   
  91.                 snprintf(b, sizeof(b), " c=%d", c / 1000);  
  92.                 strlcat(dmesgline, b, sizeof(dmesgline));  
  93.             }  
  94.         } else {  
  95.             snprintf(dmesgline, sizeof(dmesgline),  
  96.                  "battery none");  
  97.         }  
  98.   
  99.         KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,  
  100.                      props.chargerAcOnline ? "a" : "",  
  101.                      props.chargerUsbOnline ? "u" : "",  
  102.                      props.chargerWirelessOnline ? "w" : "");  
  103.     }  
  104.   
  105.     healthd_mode_ops->battery_update(&props);//将数据传到上层的BatteryService  
  106.     return props.chargerAcOnline | props.chargerUsbOnline |//返回当前是否属于充电  
  107.             props.chargerWirelessOnline;  
  108. }  

接下来看看healthd_mode_ops->battery_update是怎么把数据传到上层的

  1. void healthd_mode_android_battery_update(  
  2.     struct android::BatteryProperties *props) {  
  3.     if (gBatteryPropertiesRegistrar != NULL)  
  4.         gBatteryPropertiesRegistrar->notifyListeners(*props);  
  5.   
  6.     return;  
  7. }  

上层会通过binder通信,注册一个回调到BatteryPropertiesRegistrar

  1. void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {  
  2.     {  
  3.         if (listener == NULL)  
  4.             return;  
  5.         Mutex::Autolock _l(mRegistrationLock);  
  6.         // check whether this is a duplicate  
  7.         for (size_t i = 0; i < mListeners.size(); i++) {  
  8.             if (mListeners[i]->asBinder() == listener->asBinder()) {  
  9.                 return;  
  10.             }  
  11.         }  
  12.   
  13.         mListeners.add(listener);  
  14.         listener->asBinder()->linkToDeath(this);  
  15.     }  
  16.     healthd_battery_update();  
  17. }  

而update函数就是调用了notifyListeners遍历各个listener传到上层BatteryService

  1. void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {  
  2.     Mutex::Autolock _l(mRegistrationLock);  
  3.     for (size_t i = 0; i < mListeners.size(); i++) {  
  4.         mListeners[i]->batteryPropertiesChanged(props);  
  5.     }  
  6. }  

再来看看BatteryService中,在onStart中通过ServiceManager,和batteryproperties这个Service通信,将BatteryListener这个listenter注册到batteryproperties中去

  1. @Override  
  2. public void onStart() {  
  3.     IBinder b = ServiceManager.getService("batteryproperties");  
  4.     final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =  
  5.             IBatteryPropertiesRegistrar.Stub.asInterface(b);  
  6.     try {  
  7.         batteryPropertiesRegistrar.registerListener(new BatteryListener());  
  8.     } catch (RemoteException e) {  
  9.         // Should never happen.  
  10.     }  
  11.   
  12.     publishBinderService("battery", new BinderService());  
  13.     publishLocalService(BatteryManagerInternal.class, new LocalService());  
  14. }  

再来看看BatteryListener 的batteryPropertiesChanged接口,当下面调这个接口,就会调用BatteryService的update函数,然后就是BatteryService的一些主要流程就不分析了。

  1. private final class BatteryListener extends IBatteryPropertiesListener.Stub {  
  2.     @Override  
  3.     public void batteryPropertiesChanged(BatteryProperties props) {  
  4.         final long identity = Binder.clearCallingIdentity();  
  5.         try {  
  6.             BatteryService.this.update(props);  
  7.         } finally {  
  8.             Binder.restoreCallingIdentity(identity);  
  9.         }  
  10.    }  
  11. }  


BatteryService接受healthd的数据都是被动的,healthd穿过来的。有没有主动去healthd查询的。

在BatteryManager中就有主动去healthd查询的,代码如下

  1. private long queryProperty(int id) {  
  2.     long ret;  
  3.   
  4.     if (mBatteryPropertiesRegistrar == null) {  
  5.         IBinder b = ServiceManager.getService("batteryproperties");//获取batteryproperties Service  
  6.         mBatteryPropertiesRegistrar =  
  7.             IBatteryPropertiesRegistrar.Stub.asInterface(b);//接口转化下  
  8.   
  9.         if (mBatteryPropertiesRegistrar == null)  
  10.             return Long.MIN_VALUE;  
  11.     }  
  12.   
  13.     try {  
  14.         BatteryProperty prop = new BatteryProperty();  
  15.   
  16.         if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)//prop是输出  
  17.             ret = prop.getLong();  
  18.         else  
  19.             ret = Long.MIN_VALUE;  
  20.     } catch (RemoteException e) {  
  21.         ret = Long.MIN_VALUE;  
  22.     }  
  23.   
  24.     return ret;  
  25. }  

再到healthd看看对应的接口

  1. status_t BatteryPropertiesRegistrar::getProperty(int id, struct BatteryProperty *val) {  
  2.     return healthd_get_property(id, val);  
  3. }  

  1. status_t healthd_get_property(int id, struct BatteryProperty *val) {  
  2.     return gBatteryMonitor->getProperty(id, val);  
  3. }  
java的BatteryProperty对象对应到这边是指针
  1. status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {  
  2.     status_t ret = BAD_VALUE;  
  3.   
  4.     val->valueInt64 = LONG_MIN;  
  5.   
  6.     switch(id) {  
  7.     case BATTERY_PROP_CHARGE_COUNTER://根据不同ID,返回不同值  
  8.         if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {  
  9.             val->valueInt64 =  
  10.                 getIntField(mHealthdConfig->batteryChargeCounterPath);  
  11.             ret = NO_ERROR;  
  12.         } else {  
  13.             ret = NAME_NOT_FOUND;  
  14.         }  
  15.         break;  
  16.   
  17.     case BATTERY_PROP_CURRENT_NOW:  
  18.         if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  19.             val->valueInt64 =  
  20.                 getIntField(mHealthdConfig->batteryCurrentNowPath);  
  21.             ret = NO_ERROR;  
  22.         } else {  
  23.             ret = NAME_NOT_FOUND;  
  24.         }  
  25.         break;  
  26.   
  27.     case BATTERY_PROP_CURRENT_AVG:  
  28.         if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {  
  29.             val->valueInt64 =  
  30.                 getIntField(mHealthdConfig->batteryCurrentAvgPath);  
  31.             ret = NO_ERROR;  
  32.         } else {  
  33.             ret = NAME_NOT_FOUND;  
  34.         }  
  35.         break;  
  36.   
  37.     case BATTERY_PROP_CAPACITY:  
  38.         if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {  
  39.             val->valueInt64 =  
  40.                 getIntField(mHealthdConfig->batteryCapacityPath);  
  41.             ret = NO_ERROR;  
  42.         } else {  
  43.             ret = NAME_NOT_FOUND;  
  44.         }  
  45.         break;  
  46.   
  47.     case BATTERY_PROP_ENERGY_COUNTER:  
  48.         if (mHealthdConfig->energyCounter) {  
  49.             ret = mHealthdConfig->energyCounter(&val->valueInt64);  
  50.         } else {  
  51.             ret = NAME_NOT_FOUND;  
  52.         }  
  53.         break;  
  54.   
  55.     default:  
  56.         break;  
  57.     }  
  58.   
  59.     return ret;  
  60. }  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多