android 4.4 電池電量管理底層分析(C\C++層)

參考文獻:http://blog.csdn.net/wlwl0071986/article/details/38778897 

簡介:

Linux電池驅動用於和PMIC交互、負責監聽電池產生的相關事件,例如低電報警、電量發生變化、高溫報警、USB插拔等等。

Android電池服務,用來監聽內核上報的電池事件,並將最新的電池數據上報給系統,系統收到新數據後會去更新電池顯示狀態、剩餘電量等信息。如果收到過溫報警和低電報警,系統會自動觸發關機流程,保護電池和機器不受到危害。

Android電池服務的啓動和運行流程:


Android電源管理底層用的是Linux powersupply框架,從Android 4.4開始,Google專門提供了一個healthd來監控電源狀態。它的路徑在:system/core/healthd文件夾下,編譯出來的文件爲/sbin/healthd。


電池系統從底層向Framework層上報數據的流程:



這裏我把文章框架按語言分成 C/C++ 層與Java層。(這篇介紹C/C++ 層, Java 層請看另外一篇博客http://blog.csdn.net/daweibalang717/article/details/40615453),

關於C/C++ 層與驅動交互的代碼我不全部貼出,只給出路徑,大家可以自己查找閱讀,這裏值講述關鍵函數。


一、關係圖:


二、Healthd

  包含兩個文件:\system\core\healthd\healthd.h ,\system\core\healthd\healthd.cpp 

   簡要說明:

    health.h 是個頭文件,只要聲明函數與變量,不做過多介紹。我們說下healthd.cpp ,

  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.     gBatteryMonitor = new BatteryMonitor();  
  22.     gBatteryMonitor->init(&healthd_config, nosvcmgr);  
  23.   
  24.     healthd_mainloop();  
  25.     return 0;  
  26. }  

這是main函數,跟Java中的main是一樣的,作爲程序的入口。這裏做一些初始化工作,獲得BatteryMonitor的指針對象。我們索要關注的是healthd_mainloop()的調用,僅憑函數名就能知道會進入一個無限循環,這樣也就能達到監控電源狀態的目的了。下面我們看一下這個函數:

  1. static void healthd_mainloop(void) {  
  2.     struct epoll_event ev;  
  3.     int epollfd;  
  4.     int maxevents = 0;  
  5.   
  6.     epollfd = epoll_create(MAX_EPOLL_EVENTS);  
  7.     if (epollfd == -1) {  
  8.         KLOG_ERROR(LOG_TAG,  
  9.                    "healthd_mainloop: epoll_create failed; errno=%d\n",  
  10.                    errno);  
  11.         return;  
  12.     }  
  13.   
  14.     if (uevent_fd >= 0) {  
  15.         ev.events = EPOLLIN;  
  16.         ev.data.ptr = (void *)uevent_event;  
  17.         if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1)  
  18.             KLOG_ERROR(LOG_TAG,  
  19.                        "healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n",  
  20.                        errno);  
  21.         else  
  22.             maxevents++;  
  23.     }  
  24.   
  25.     if (wakealarm_fd >= 0) {  
  26.         ev.events = EPOLLIN | EPOLLWAKEUP;  
  27.         ev.data.ptr = (void *)wakealarm_event;  
  28.         if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1)  
  29.             KLOG_ERROR(LOG_TAG,  
  30.                        "healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n",  
  31.                        errno);  
  32.         else  
  33.             maxevents++;  
  34.    }  
  35.   
  36.     if (binder_fd >= 0) {  
  37.         ev.events = EPOLLIN | EPOLLWAKEUP;  
  38.         ev.data.ptr= (void *)binder_event;  
  39.         if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1)  
  40.             KLOG_ERROR(LOG_TAG,  
  41.                        "healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n",  
  42.                        errno);  
  43.         else  
  44.             maxevents++;  
  45.    }  
  46.   
  47.     while (1) {  
  48.         struct epoll_event events[maxevents];  
  49.         int nevents;  
  50.   
  51.         IPCThreadState::self()->flushCommands();  
  52.         nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval);  
  53.   
  54.         if (nevents == -1) {  
  55.             if (errno == EINTR)  
  56.                 continue;  
  57.             KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");  
  58.             break;  
  59.         }  
  60.   
  61.         for (int n = 0; n < nevents; ++n) {  
  62.             if (events[n].data.ptr)  
  63.                 (*(void (*)())events[n].data.ptr)();  
  64.         }  
  65.   
  66.         if (!nevents)  
  67.             periodic_chores();  
  68.     }  
  69.   
  70.     return;  
  71. }  

我們來看一下這個函數都幹了哪些事情呢?首先,代碼:epollfd = epoll_create(MAX_EPOLL_EVENTS);創建一個 epoll 實例,並要求內核分配一個可以保存 size 個描述符的空間( 關於epoll,Linux中的字符設備驅動中有一個函數是poll,Linux 2.5.44版本後被epoll取代,請參考:http://baike.baidu.com/view/1385104.htm?fr=aladdin ), 然後把函數賦值 ev.data.ptr = (void *)uevent_event; 在while(1) 的 調用 nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval); 等待EPOLL事件的發生,相當於監聽。當收到監聽後,就是在
[java] view plain copy
  1. for (int n = 0; n < nevents; ++n) {  
  2.     if (events[n].data.ptr)  
  3.         (*(void (*)())events[n].data.ptr)();  
  4. }  

for循環中調用 事件賦值 ev.data.ptr = (void *)uevent_event; 所賦值的函數, 其實相當於Java中的回調接口。我們這裏值關注uevent_event 函數。因爲這個是跟電池屬性相關的。uevent_event 函數如下:

  1. static void uevent_event(void) {  
  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.   
  16.     while (*cp) {  
  17.         if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {  
  18.             battery_update();  
  19.             break;  
  20.         }  
  21.   
  22.         /* advance to after the next \0 */  
  23.         while (*cp++)  
  24.             ;  
  25.     }  
  26. }  

它會讀取socket中的字符串,然後判斷事件來源是否是由kernel的power_supply發出的,代碼if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) ,如果是,那就調用battery_update()更新電源狀態。下面來看看battery_update()是如何更新電源狀態的:

  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.    int new_wake_interval = gBatteryMonitor->update() ?  
  6.        healthd_config.periodic_chores_interval_fast :  
  7.            healthd_config.periodic_chores_interval_slow;  
  8.   
  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 ?  
  22.                 -1 : healthd_config.periodic_chores_interval_fast * 1000;  
  23. }  
主要就是這一句:gBatteryMonitor->update() ,gBatteryMonitor 是在mian 函數中初始化的BatteryMonitor的指針對象。 看關係圖,這裏就由Healthd 跳到BatteryMonitor了。

下面,我們看一下BatteryMonitor


三、BatteryMonitor

  包含兩個文件:\system\core\healthd\BatteryMonitor.h ,\system\core\healthd\BatteryMonitor.cpp

   簡要說明:

    BatteryMonitor.h 是個頭文件,只要聲明函數與變量,不做過多介紹。我們說下BatteryMonitor.cpp ,

    上面說到,battery_update() 中會調用gBatteryMonitor->update() ,那BatteryMonitor.cpp 中的 update()都做了什麼了?代碼如下:

  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.   
  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.     unsigned int i;  
  43.   
  44.     for (i = 0; i < mChargerNames.size(); i++) {  
  45.         String8 path;  
  46.         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,  
  47.                           mChargerNames[i].string());  
  48.   
  49.         if (readFromFile(path, buf, SIZE) > 0) {  
  50.             if (buf[0] != '0') {  
  51.                 path.clear();  
  52.                 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,  
  53.                                   mChargerNames[i].string());  
  54.                 switch(readPowerSupplyType(path)) {  
  55.                 case ANDROID_POWER_SUPPLY_TYPE_AC:  
  56.                     props.chargerAcOnline = true;  
  57.                     break;  
  58.                 case ANDROID_POWER_SUPPLY_TYPE_USB:  
  59.                     props.chargerUsbOnline = true;  
  60.                     break;  
  61.                 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:  
  62.                     props.chargerWirelessOnline = true;  
  63.                     break;  
  64.                 default:  
  65.                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",  
  66.                                  mChargerNames[i].string());  
  67.                 }  
  68.             }  
  69.         }  
  70.     }  
  71.   
  72.     logthis = !healthd_board_battery_update(&props);  
  73.   
  74.     if (logthis) {  
  75.         char dmesgline[256];  
  76.         snprintf(dmesgline, sizeof(dmesgline),  
  77.                  "battery l=%d v=%d t=%s%d.%d h=%d st=%d",  
  78.                  props.batteryLevel, props.batteryVoltage,  
  79.                  props.batteryTemperature < 0 ? "-" : "",  
  80.                  abs(props.batteryTemperature / 10),  
  81.                  abs(props.batteryTemperature % 10), props.batteryHealth,  
  82.                  props.batteryStatus);  
  83.   
  84.         if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  85.             char b[20];  
  86.   
  87.             snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);  
  88.             strlcat(dmesgline, b, sizeof(dmesgline));  
  89.         }  
  90.   
  91.         KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,  
  92.                   props.chargerAcOnline ? "a" : "",  
  93.                   props.chargerUsbOnline ? "u" : "",  
  94.                   props.chargerWirelessOnline ? "w" : "");  
  95.     }  
  96.   
  97.     if (mBatteryPropertiesRegistrar != NULL)  
  98.         mBatteryPropertiesRegistrar->notifyListeners(props);  
  99.   
  100.     return props.chargerAcOnline | props.chargerUsbOnline |  
  101.             props.chargerWirelessOnline;  
  102. }  
這個函數首先定義了BatteryProperties props; 這個屬性集(爲了減少介紹的複雜度,大家可以簡單的認爲只是一個包含各種屬性的類),然後給這個屬性集 props 裏面的屬性賦值。然後在最後會在最後判斷有無註冊監聽 ,如果有的話,調用註冊的監聽,把屬性傳入監聽:

  1. if (mBatteryPropertiesRegistrar != NULL)  
  2.      mBatteryPropertiesRegistrar->notifyListeners(props);  
調用的就是上面的東西。 到目前爲止,我們知道了health 裏面有個無線循環,監控驅動事件,然後調用BatteryProperties中的update方法。 然後update會讀取各種屬性值,然後調用註冊的監聽。如下圖


  那麼問題來了------->挖掘機技術哪家強?哈哈,開個玩笑。下面我們就要分兩個分支來講述:

(1)這些屬性是從哪裏來的。 

(2)屬性變化後調用的監聽是誰註冊的。




首先,(1)這些屬性是從哪裏來的。

     我們先看一下 上面的 healthd.cpp 的main 函數初始化 BatteryMonitor 時,調用了

  1. gBatteryMonitor = new BatteryMonitor();  
  2.  gBatteryMonitor->init(&healthd_config, nosvcmgr);  
  這個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.             switch(readPowerSupplyType(path)) {  
  22.             case ANDROID_POWER_SUPPLY_TYPE_AC:  
  23.             case ANDROID_POWER_SUPPLY_TYPE_USB:  
  24.             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:  
  25.                 path.clear();  
  26.                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);  
  27.                 if (access(path.string(), R_OK) == 0)  
  28.                     mChargerNames.add(String8(name));  
  29.                 break;  
  30.   
  31.             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:  
  32.                 if (mHealthdConfig->batteryStatusPath.isEmpty()) {  
  33.                     path.clear();  
  34.                     path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,  
  35.                                       name);  
  36.                     if (access(path, R_OK) == 0)  
  37.                         mHealthdConfig->batteryStatusPath = path;  
  38.                 }  
  39.   
  40.                 if (mHealthdConfig->batteryHealthPath.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->batteryHealthPath = path;  
  46.                 }  
  47.   
  48.                 if (mHealthdConfig->batteryPresentPath.isEmpty()) {  
  49.                     path.clear();  
  50.                     path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,  
  51.                                       name);  
  52.                     if (access(path, R_OK) == 0)  
  53.                         mHealthdConfig->batteryPresentPath = path;  
  54.                 }  
  55.   
  56.                 if (mHealthdConfig->batteryCapacityPath.isEmpty()) {  
  57.                     path.clear();  
  58.                     path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,  
  59.                                       name);  
  60.                     if (access(path, R_OK) == 0)  
  61.                         mHealthdConfig->batteryCapacityPath = path;  
  62.                 }  
  63.   
  64.                 if (mHealthdConfig->batteryVoltagePath.isEmpty()) {  
  65.                     path.clear();  
  66.                     path.appendFormat("%s/%s/voltage_now",  
  67.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  68.                     if (access(path, R_OK) == 0) {  
  69.                         mHealthdConfig->batteryVoltagePath = path;  
  70.                     } else {  
  71.                         path.clear();  
  72.                         path.appendFormat("%s/%s/batt_vol",  
  73.                                           POWER_SUPPLY_SYSFS_PATH, name);  
  74.                         if (access(path, R_OK) == 0)  
  75.                             mHealthdConfig->batteryVoltagePath = path;  
  76.                     }  
  77.                 }  
  78.   
  79.                 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {  
  80.                     path.clear();  
  81.                     path.appendFormat("%s/%s/current_now",  
  82.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  83.                     if (access(path, R_OK) == 0)  
  84.                         mHealthdConfig->batteryCurrentNowPath = path;  
  85.                 }  
  86.   
  87.                 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {  
  88.                     path.clear();  
  89.                     path.appendFormat("%s/%s/charge_counter",  
  90.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  91.                     if (access(path, R_OK) == 0)  
  92.                         mHealthdConfig->batteryChargeCounterPath = path;  
  93.                 }  
  94.   
  95.                 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {  
  96.                     path.clear();  
  97.                     path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,  
  98.                                       name);  
  99.                     if (access(path, R_OK) == 0) {  
  100.                         mHealthdConfig->batteryTemperaturePath = path;  
  101.                     } else {  
  102.                         path.clear();  
  103.                         path.appendFormat("%s/%s/batt_temp",  
  104.                                           POWER_SUPPLY_SYSFS_PATH, name);  
  105.                         if (access(path, R_OK) == 0)  
  106.                             mHealthdConfig->batteryTemperaturePath = path;  
  107.                     }  
  108.                 }  
  109.   
  110.                 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {  
  111.                     path.clear();  
  112.                     path.appendFormat("%s/%s/technology",  
  113.                                       POWER_SUPPLY_SYSFS_PATH, name);  
  114.                     if (access(path, R_OK) == 0)  
  115.                         mHealthdConfig->batteryTechnologyPath = path;  
  116.                 }  
  117.   
  118.                 break;  
  119.   
  120.             case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:  
  121.                 break;  
  122.             }  
  123.         }  
  124.         closedir(dir);  
  125.     }  
  126.   
  127.     if (!mChargerNames.size())  
  128.         KLOG_ERROR(LOG_TAG, "No charger supplies found\n");  
  129.     if (mHealthdConfig->batteryStatusPath.isEmpty())  
  130.         KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");  
  131.     if (mHealthdConfig->batteryHealthPath.isEmpty())  
  132.         KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");  
  133.     if (mHealthdConfig->batteryPresentPath.isEmpty())  
  134.         KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");  
  135.     if (mHealthdConfig->batteryCapacityPath.isEmpty())  
  136.         KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");  
  137.     if (mHealthdConfig->batteryVoltagePath.isEmpty())  
  138.         KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");  
  139.     if (mHealthdConfig->batteryTemperaturePath.isEmpty())  
  140.         KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");  
  141.     if (mHealthdConfig->batteryTechnologyPath.isEmpty())  
  142.         KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");  
  143.   
  144.     if (nosvcmgr == false) {  
  145.             mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);  
  146.             mBatteryPropertiesRegistrar->publish();  
  147.     }  
  148. }  

在init()裏會調用opendir(POWER_SUPPLY_SYSFS_PATH);  

opendir()函數的作用是:打開目錄句柄,將返回一組目錄流(一組目錄字符串),說白了就是目錄下的文件名。 

  1. #define POWER_SUPPLY_SUBSYSTEM "power_supply"  
  2. #define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM  
其實 opendir 打開的就是 sys/class/power_supply ,並返回這個路徑下的所有文件。文件如下:

比如ac (充電器就叫AC)目錄下面都有什麼呢:


然後我們看init()代碼裏面,其實就是把各種路徑讀取出來,然後把路徑賦值。 我們知道了init()幹了什麼,然後迴歸到主題:update() 中的屬性從哪裏來的。

我們只舉一個例子。在update()中如何讀取的當前電量級別(其他屬性獲取都是類似的)。在 update()函數中,獲取當前電量等級代碼如下:

  1. if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())  
  2.     props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);  
會用getIntField() 去讀取當前電量值。而且傳入的參數是我們init()時獲取的文件路徑。 從路徑下讀取的值是什麼呢,大家看下截圖就明白了。如下:


看到沒,其實就是讀取文件裏面的值。 100 是我當前手機的電量,我的手機是滿電狀態。

到此,我們第一個問題:

BatteryMonitor 中 update 方面裏面如何獲取的屬性已經解決。就是根據路徑,讀取文件獲得的。



下面來看第二個問題:

(2)屬性變化後調用誰註冊的監聽。

在BatteryMonitor.cpp中的init()函數末尾 有這麼一句:

  1. if (nosvcmgr == false) {  
  2.         mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);  
  3.         mBatteryPropertiesRegistrar->publish();  
  4. }  

而在在BatteryMonitor.cpp中的update()函數末尾 有這麼一句:

  1. if (mBatteryPropertiesRegistrar != NULL)  
  2.     mBatteryPropertiesRegistrar->notifyListeners(props);  

由上面兩個函數中的調用,我們很容易推測出 註冊監聽跟 BatteryPropertiesRegistrar有關。


我們來分析下 BatteryPropertiesRegistrar 有什麼。


BatteryPropertiesRegistrar:

此類的相關文件有4個,具體路徑:

\frameworks\native\include\batteryservice\IBatteryPropertiesRegistrar.h

\frameworks\native\services\batteryservice\IBatteryPropertiesRegistrar.cpp

\system\core\healthd\BatteryPropertiesRegistrar.cpp  

\system\core\healthd\BatteryPropertiesRegistrar.h




\frameworks\native\include\batteryservice\IBatteryPropertiesRegistrar.h文件內容:

  1. #ifndef ANDROID_IBATTERYPROPERTIESREGISTRAR_H  
  2. #define ANDROID_IBATTERYPROPERTIESREGISTRAR_H  
  3.   
  4. #include <binder/IInterface.h>  
  5. #include <batteryservice/IBatteryPropertiesListener.h>  
  6.   
  7. namespace android {  
  8.   
  9. // must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl  
  10. enum {  
  11.     REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,  
  12.     UNREGISTER_LISTENER,  
  13. };  
  14.   
  15. class IBatteryPropertiesRegistrar : public IInterface {  
  16. public:  
  17.     DECLARE_META_INTERFACE(BatteryPropertiesRegistrar);  
  18.   
  19.     virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0;  
  20.     virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0;  
  21. };  
  22.   
  23. class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> {  
  24. public:  
  25.     virtual status_t onTransact(uint32_t code, const Parcel& data,  
  26.                                 Parcel* reply, uint32_t flags = 0);  
  27. };  
  28.   
  29. }; // namespace android  
  30.   
  31. #endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H  

咦,我們可以看到IBatteryPropertiesRegistrar 繼承於  IInterface  ,還有一個類BnBatteryPropertiesRegistrar 繼承於BnInterface。 而且還調用了
  1. DECLARE_META_INTERFACE(BatteryPropertiesRegistrar);  
這個宏定義接口。如果你有看過我上篇 Binder 初解(http://blog.csdn.net/daweibalang717/article/details/41382603 )的話,你可以很輕易的看出這裏是Binder的寫法。而且明顯是個 native service。 對於這四個文件的關係。你讀完 Binder 初解後,就一目瞭然了。


\frameworks\native\services\batteryservice\IBatteryPropertiesRegistrar.cpp的內容

  1. #define LOG_TAG "IBatteryPropertiesRegistrar"  
  2. //#define LOG_NDEBUG 0  
  3. #include <utils/Log.h>  
  4.   
  5. #include <batteryservice/IBatteryPropertiesListener.h>  
  6. #include <batteryservice/IBatteryPropertiesRegistrar.h>  
  7. #include <stdint.h>  
  8. #include <sys/types.h>  
  9. #include <binder/Parcel.h>  
  10.   
  11. namespace android {  
  12.   
  13. class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> {  
  14. public:  
  15.     BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)  
  16.         : BpInterface<IBatteryPropertiesRegistrar>(impl) {}  
  17.   
  18.         void registerListener(const sp<IBatteryPropertiesListener>& listener) {  
  19.             Parcel data;  
  20.             data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());  
  21.             data.writeStrongBinder(listener->asBinder());  
  22.             remote()->transact(REGISTER_LISTENER, data, NULL);  
  23.         }  
  24.   
  25.         void unregisterListener(const sp<IBatteryPropertiesListener>& listener) {  
  26.             Parcel data;  
  27.             data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());  
  28.             data.writeStrongBinder(listener->asBinder());  
  29.             remote()->transact(UNREGISTER_LISTENER, data, NULL);  
  30.         }  
  31. };  
  32.   
  33. IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar");  
  34.   
  35. status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code,  
  36.                                                   const Parcel& data,  
  37.                                                   Parcel* reply,  
  38.                                                   uint32_t flags)  
  39. {  
  40.     switch(code) {  
  41.         case REGISTER_LISTENER: {  
  42.             CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);  
  43.             sp<IBatteryPropertiesListener> listener =  
  44.                 interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());  
  45.             //這個方法並不是上面 BpBatteryPropertiesRegistrar中的registerListener(),他們就不是一個類。這個方法還未實現        
  46.             registerListener(listener);  
  47.             return OK;  
  48.         }  
  49.   
  50.         case UNREGISTER_LISTENER: {  
  51.             CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);  
  52.             sp<IBatteryPropertiesListener> listener =  
  53.                 interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());  
  54.  //這個方法並不是上面 BpBatteryPropertiesRegistrar中的unregisterListener(),他們就不是一個類。這個方法還未實現   
  55.             unregisterListener(listener);  
  56.             return OK;  
  57.         }  
  58.     }  
  59.     return BBinder::onTransact(code, data, reply, flags);  
  60. };  
  61.   
  62. // ----------------------------------------------------------------------------  
  63.   
  64. }; // namespace android  

我們看到 這裏是服務端與代理端的實現。 但是服務端 onTransact( )中調用的 registerListener(listener); 與unregisterListener(listener); 是沒有實現的。這兩個方法是在

\system\core\healthd\BatteryPropertiesRegistrar.cpp  中實現的。

 \system\core\healthd\BatteryPropertiesRegistrar.h 中的內容:

  1. #ifndef HEALTHD_BATTERYPROPERTIES_REGISTRAR_H  
  2. #define HEALTHD_BATTERYPROPERTIES_REGISTRAR_H  
  3.   
  4. #include "BatteryMonitor.h"  
  5.   
  6. #include <binder/IBinder.h>  
  7. #include <utils/Mutex.h>  
  8. #include <utils/Vector.h>  
  9. #include <batteryservice/BatteryService.h>  
  10. #include <batteryservice/IBatteryPropertiesListener.h>  
  11. #include <batteryservice/IBatteryPropertiesRegistrar.h>  
  12.   
  13. namespace android {  
  14.   
  15. class BatteryMonitor;  
  16.   
  17. class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar,  
  18.                                    public IBinder::DeathRecipient {  
  19. public:  
  20.     BatteryPropertiesRegistrar(BatteryMonitor* monitor);  
  21.     void publish();  
  22.     void notifyListeners(struct BatteryProperties props);  
  23.   
  24. private:  
  25.     BatteryMonitor* mBatteryMonitor;  
  26.     Mutex mRegistrationLock;  
  27.     Vector<sp<IBatteryPropertiesListener> > mListeners;  
  28.   
  29.     void registerListener(const sp<IBatteryPropertiesListener>& listener);  
  30.     void unregisterListener(const sp<IBatteryPropertiesListener>& listener);  
  31.     void binderDied(const wp<IBinder>& who);  
  32. };  
  33.   
  34. };  // namespace android  
  35.   
  36. #endif // HEALTHD_BATTERYPROPERTIES_REGISTRAR_H  
這個類是對\frameworks\native\include\batteryservice\IBatteryPropertiesRegistrar.h 中的  BnBatteryPropertiesRegistrar的擴展,並繼承於public IBinder::DeathRecipient

然後是\system\core\healthd\BatteryPropertiesRegistrar.cpp  的內容:

  1. #include "BatteryPropertiesRegistrar.h"  
  2. #include <batteryservice/BatteryService.h>  
  3. #include <batteryservice/IBatteryPropertiesListener.h>  
  4. #include <batteryservice/IBatteryPropertiesRegistrar.h>  
  5. #include <binder/IServiceManager.h>  
  6. #include <utils/Errors.h>  
  7. #include <utils/Mutex.h>  
  8. #include <utils/String16.h>  
  9.   
  10. namespace android {  
  11.   
  12. BatteryPropertiesRegistrar::BatteryPropertiesRegistrar(BatteryMonitor* monitor) {  
  13.     mBatteryMonitor = monitor;  
  14. }  
  15.   
  16. void BatteryPropertiesRegistrar::publish() {  
  17.     defaultServiceManager()->addService(String16("batterypropreg"), this);  
  18. }  
  19.   
  20. void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {  
  21.     Mutex::Autolock _l(mRegistrationLock);  
  22.     for (size_t i = 0; i < mListeners.size(); i++) {  
  23.         mListeners[i]->batteryPropertiesChanged(props);  
  24.     }  
  25. }  
  26.   
  27. void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {  
  28.     {  
  29.         Mutex::Autolock _l(mRegistrationLock);  
  30.         // check whether this is a duplicate  
  31.         for (size_t i = 0; i < mListeners.size(); i++) {  
  32.             if (mListeners[i]->asBinder() == listener->asBinder()) {  
  33.                 return;  
  34.             }  
  35.         }  
  36.   
  37.         mListeners.add(listener);  
  38.         listener->asBinder()->linkToDeath(this);  
  39.     }  
  40.     mBatteryMonitor->update();  
  41. }  
  42.   
  43. void BatteryPropertiesRegistrar::unregisterListener(const sp<IBatteryPropertiesListener>& listener) {  
  44.     Mutex::Autolock _l(mRegistrationLock);  
  45.     for (size_t i = 0; i < mListeners.size(); i++) {  
  46.         if (mListeners[i]->asBinder() == listener->asBinder()) {  
  47.             mListeners[i]->asBinder()->unlinkToDeath(this);  
  48.             mListeners.removeAt(i);  
  49.             break;  
  50.         }  
  51.     }  
  52. }  
  53.   
  54. void BatteryPropertiesRegistrar::binderDied(const wp<IBinder>& who) {  
  55.     Mutex::Autolock _l(mRegistrationLock);  
  56.   
  57.     for (size_t i = 0; i < mListeners.size(); i++) {  
  58.         if (mListeners[i]->asBinder() == who) {  
  59.             mListeners.removeAt(i);  
  60.             break;  
  61.         }  
  62.     }  
  63. }  
  64.   
  65. }  // namespace android  

這個類是對 \system\core\healthd\BatteryPropertiesRegistrar.h 的實現。  真正 調用registerListener(listener); 與unregisterListener(listener); 的地方。


這個BatteryPropertiesRegistrar:其實就是註冊監聽的類,而且監聽的接口叫IBatteryPropertiesListener。


IBatteryPropertiesListener :

文件路徑:

\frameworks\native\include\batteryservice\IBatteryPropertiesListener.h

\frameworks\native\services\batteryservice\IBatteryPropertiesListener.cpp

文件內容:

IBatteryPropertiesListener.h 

  1. #ifndef ANDROID_IBATTERYPROPERTIESLISTENER_H  
  2. #define ANDROID_IBATTERYPROPERTIESLISTENER_H  
  3.   
  4. #include <binder/IBinder.h>  
  5. #include <binder/IInterface.h>  
  6.   
  7. #include <batteryservice/BatteryService.h>  
  8.   
  9. namespace android {  
  10.   
  11. // must be kept in sync with interface defined in IBatteryPropertiesListener.aidl  
  12. enum {  
  13.         TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION,  
  14. };  
  15.   
  16. // ----------------------------------------------------------------------------  
  17.   
  18. class IBatteryPropertiesListener : public IInterface {  
  19. public:  
  20.     DECLARE_META_INTERFACE(BatteryPropertiesListener);  
  21.   
  22.     virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0;  
  23. };  
  24.   
  25. // ----------------------------------------------------------------------------  
  26.   
  27. }; // namespace android  
  28.   
  29. #endif   

咦,這個依然用的是Binder 機制。這裏進行代理與服務端的聲明。


IBatteryPropertiesListener.cpp:

  1. #include <stdint.h>  
  2. #include <sys/types.h>  
  3. #include <batteryservice/IBatteryPropertiesListener.h>  
  4. #include <binder/Parcel.h>  
  5.   
  6. namespace android {  
  7.   
  8. class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener>  
  9. {  
  10. public:  
  11.     BpBatteryPropertiesListener(const sp<IBinder>& impl)  
  12.         : BpInterface<IBatteryPropertiesListener>(impl)  
  13.     {  
  14.     }  
  15.   
  16.     void batteryPropertiesChanged(struct BatteryProperties props)  
  17.     {  
  18.         Parcel data, reply;  
  19.         data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor());  
  20.         data.writeInt32(1);  
  21.         props.writeToParcel(&data);  
  22.         status_t err = remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);  
  23.     }  
  24. };  
  25.   
  26. IMPLEMENT_META_INTERFACE(BatteryPropertiesListener, "android.os.IBatteryPropertiesListener");  
  27.   
  28. // ----------------------------------------------------------------------------  
  29.   
  30. }; // namespace android  

這裏進行代理的實現。 但是並沒有對服務端進行實現。這個應該是在BatteryService.java 中的:

[java] view plain copy
  1. private final class BatteryListener extends IBatteryPropertiesListener.Stub {  
  2.     public void batteryPropertiesChanged(BatteryProperties props) {  
  3.         BatteryService.this.update(props);  
  4.    }  

中進行實現的。


到這裏我們對於第二個問題:屬性變化後調用誰註冊的監聽。 還沒有解決, 只是瞭解下注冊類與註冊接口。那麼真正註冊在那呢? 是在\frameworks\base\services\java\com\android\server\BatteryService.java中:

這個BatteryService 繼承於Binder 類,在他的構造函數中,是這麼註冊的:

[java] view plain copy
  1. mBatteryPropertiesListener = new BatteryListener();  
  2.   
  3. IBinder b = ServiceManager.getService("batterypropreg");  
  4. mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);  
  5.   
  6. try {  
  7.     mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);  
  8. catch (RemoteException e) {  
  9.     // Should never happen.  
  10. }  

大家不禁要問了。這裏是Java 代碼呀,怎麼掉的C++的呢,這就是Binder機制了。 而且上面所述的 IBatteryPropertiesListener  、IBatteryPropertiesRegistrar 在Java層都有對應的aidl 文件。目錄:

\frameworks\base\core\java\android\os\IBatteryPropertiesListener.aidl  

[java] view plain copy
  1. package android.os;  
  2.   
  3. import android.os.BatteryProperties;  
  4.   
  5. /** 
  6.  * {@hide} 
  7.  */  
  8.   
  9. oneway interface IBatteryPropertiesListener {  
  10.     void batteryPropertiesChanged(in BatteryProperties props);  
  11. }  


\frameworks\base\core\java\android\os\IBatteryPropertiesRegistrar.aidl


[java] view plain copy
  1. package android.os;  
  2.   
  3. import android.os.IBatteryPropertiesListener;  
  4.   
  5. /** 
  6.  * {@hide} 
  7.  */  
  8.   
  9. interface IBatteryPropertiesRegistrar {  
  10.     void registerListener(IBatteryPropertiesListener listener);  
  11.     void unregisterListener(IBatteryPropertiesListener listener);  
  12. }  

當編譯的時候會自動生成 IBatteryPropertiesListener.java  與 IBatteryPropertiesRegistrar.java 文件。這個我就不多贅述了。


好吧,我們總結下第二個問題:


1、在BatteryService.java 實現回調函數中的接口,並註冊到BatteryPropertiesRegistrar 中。 

2、Healthd 中監控PMU 驅動,事件變更,調用BatteryMonitor中的update()函數中回調BatteryPropertiesRegistrar註冊的接口,調用的就是BatteryService.java 實現的接口


到此,我們電池電量管理底層分析(C\C++層) 的分析已經完成。  如果你要了解 BatteryService.java 中被回調後執行了哪些事情,請觀看我的博客 :

android 4.4 電池電量顯示分析(低電量提醒與電池圖標)Java 層 (http://blog.csdn.net/daweibalang717/article/details/40615453)


發佈了16 篇原創文章 · 獲贊 21 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章