參考文獻: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 ,
- 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();
- gBatteryMonitor = new BatteryMonitor();
- gBatteryMonitor->init(&healthd_config, nosvcmgr);
- healthd_mainloop();
- return 0;
- }
這是main函數,跟Java中的main是一樣的,作爲程序的入口。這裏做一些初始化工作,獲得BatteryMonitor的指針對象。我們索要關注的是healthd_mainloop()的調用,僅憑函數名就能知道會進入一個無限循環,這樣也就能達到監控電源狀態的目的了。下面我們看一下這個函數:
- static void healthd_mainloop(void) {
- struct epoll_event ev;
- int epollfd;
- int maxevents = 0;
- epollfd = epoll_create(MAX_EPOLL_EVENTS);
- if (epollfd == -1) {
- KLOG_ERROR(LOG_TAG,
- "healthd_mainloop: epoll_create failed; errno=%d\n",
- errno);
- return;
- }
- if (uevent_fd >= 0) {
- ev.events = EPOLLIN;
- ev.data.ptr = (void *)uevent_event;
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1)
- KLOG_ERROR(LOG_TAG,
- "healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n",
- errno);
- else
- maxevents++;
- }
- if (wakealarm_fd >= 0) {
- ev.events = EPOLLIN | EPOLLWAKEUP;
- ev.data.ptr = (void *)wakealarm_event;
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1)
- KLOG_ERROR(LOG_TAG,
- "healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n",
- errno);
- else
- maxevents++;
- }
- if (binder_fd >= 0) {
- ev.events = EPOLLIN | EPOLLWAKEUP;
- ev.data.ptr= (void *)binder_event;
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1)
- KLOG_ERROR(LOG_TAG,
- "healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n",
- errno);
- else
- maxevents++;
- }
- while (1) {
- struct epoll_event events[maxevents];
- int nevents;
- IPCThreadState::self()->flushCommands();
- nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval);
- if (nevents == -1) {
- if (errno == EINTR)
- continue;
- KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
- break;
- }
- for (int n = 0; n < nevents; ++n) {
- if (events[n].data.ptr)
- (*(void (*)())events[n].data.ptr)();
- }
- if (!nevents)
- periodic_chores();
- }
- return;
- }
我們來看一下這個函數都幹了哪些事情呢?首先,代碼: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事件的發生,相當於監聽。當收到監聽後,就是在
- for (int n = 0; n < nevents; ++n) {
- if (events[n].data.ptr)
- (*(void (*)())events[n].data.ptr)();
- }
for循環中調用 事件賦值 ev.data.ptr = (void *)uevent_event; 所賦值的函數, 其實相當於Java中的回調接口。我們這裏值關注uevent_event 函數。因爲這個是跟電池屬性相關的。uevent_event 函數如下:
- static void uevent_event(void) {
- char msg[UEVENT_MSG_LEN+2];
- char *cp;
- int n;
- n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
- if (n <= 0)
- return;
- if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
- return;
- msg[n] = '\0';
- msg[n+1] = '\0';
- cp = msg;
- while (*cp) {
- if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
- battery_update();
- break;
- }
- /* advance to after the next \0 */
- while (*cp++)
- ;
- }
- }
它會讀取socket中的字符串,然後判斷事件來源是否是由kernel的power_supply發出的,代碼if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) ,如果是,那就調用battery_update()更新電源狀態。下面來看看battery_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).
- 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;
- }
下面,我們看一下BatteryMonitor。
三、BatteryMonitor
包含兩個文件:\system\core\healthd\BatteryMonitor.h ,\system\core\healthd\BatteryMonitor.cpp
簡要說明:
BatteryMonitor.h 是個頭文件,只要聲明函數與變量,不做過多介紹。我們說下BatteryMonitor.cpp ,
上面說到,battery_update() 中會調用gBatteryMonitor->update() ,那BatteryMonitor.cpp 中的 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;
- 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);
- unsigned int i;
- 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)
- mBatteryPropertiesRegistrar->notifyListeners(props);
- return props.chargerAcOnline | props.chargerUsbOnline |
- props.chargerWirelessOnline;
- }
- if (mBatteryPropertiesRegistrar != NULL)
- mBatteryPropertiesRegistrar->notifyListeners(props);
那麼問題來了------->挖掘機技術哪家強?哈哈,開個玩笑。下面我們就要分兩個分支來講述:
(1)這些屬性是從哪裏來的。
(2)屬性變化後調用的監聽是誰註冊的。
首先,(1)這些屬性是從哪裏來的。
我們先看一下 上面的 healthd.cpp 的main 函數初始化 BatteryMonitor 時,調用了
- gBatteryMonitor = new BatteryMonitor();
- gBatteryMonitor->init(&healthd_config, nosvcmgr);
- 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);
- switch(readPowerSupplyType(path)) {
- case ANDROID_POWER_SUPPLY_TYPE_AC:
- case ANDROID_POWER_SUPPLY_TYPE_USB:
- 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 (mHealthdConfig->batteryCapacityPath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
- name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryCapacityPath = path;
- }
- if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/voltage_now",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0) {
- mHealthdConfig->batteryVoltagePath = path;
- } else {
- path.clear();
- path.appendFormat("%s/%s/batt_vol",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryVoltagePath = path;
- }
- }
- if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/current_now",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryCurrentNowPath = path;
- }
- if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/charge_counter",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryChargeCounterPath = path;
- }
- if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
- name);
- if (access(path, R_OK) == 0) {
- mHealthdConfig->batteryTemperaturePath = path;
- } else {
- path.clear();
- path.appendFormat("%s/%s/batt_temp",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryTemperaturePath = path;
- }
- }
- if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
- path.clear();
- path.appendFormat("%s/%s/technology",
- POWER_SUPPLY_SYSFS_PATH, name);
- if (access(path, R_OK) == 0)
- mHealthdConfig->batteryTechnologyPath = path;
- }
- break;
- case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
- break;
- }
- }
- closedir(dir);
- }
- if (!mChargerNames.size())
- KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
- if (mHealthdConfig->batteryStatusPath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
- if (mHealthdConfig->batteryHealthPath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
- if (mHealthdConfig->batteryPresentPath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
- if (mHealthdConfig->batteryCapacityPath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
- if (mHealthdConfig->batteryVoltagePath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
- if (mHealthdConfig->batteryTemperaturePath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
- if (mHealthdConfig->batteryTechnologyPath.isEmpty())
- KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
- if (nosvcmgr == false) {
- mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
- mBatteryPropertiesRegistrar->publish();
- }
- }
在init()裏會調用opendir(POWER_SUPPLY_SYSFS_PATH);
opendir()函數的作用是:打開目錄句柄,將返回一組目錄流(一組目錄字符串),說白了就是目錄下的文件名。
- #define POWER_SUPPLY_SUBSYSTEM "power_supply"
- #define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
比如ac (充電器就叫AC)目錄下面都有什麼呢:
然後我們看init()代碼裏面,其實就是把各種路徑讀取出來,然後把路徑賦值。 我們知道了init()幹了什麼,然後迴歸到主題:update() 中的屬性從哪裏來的。
我們只舉一個例子。在update()中如何讀取的當前電量級別(其他屬性獲取都是類似的)。在 update()函數中,獲取當前電量等級代碼如下:
- if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
- props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);
看到沒,其實就是讀取文件裏面的值。 100 是我當前手機的電量,我的手機是滿電狀態。
到此,我們第一個問題:
BatteryMonitor 中 update 方面裏面如何獲取的屬性已經解決。就是根據路徑,讀取文件獲得的。
下面來看第二個問題:
(2)屬性變化後調用誰註冊的監聽。
在BatteryMonitor.cpp中的init()函數末尾 有這麼一句:
- if (nosvcmgr == false) {
- mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
- mBatteryPropertiesRegistrar->publish();
- }
而在在BatteryMonitor.cpp中的update()函數末尾 有這麼一句:
- if (mBatteryPropertiesRegistrar != NULL)
- 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文件內容:
- #ifndef ANDROID_IBATTERYPROPERTIESREGISTRAR_H
- #define ANDROID_IBATTERYPROPERTIESREGISTRAR_H
- #include <binder/IInterface.h>
- #include <batteryservice/IBatteryPropertiesListener.h>
- namespace android {
- // must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl
- enum {
- REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
- UNREGISTER_LISTENER,
- };
- class IBatteryPropertiesRegistrar : public IInterface {
- public:
- DECLARE_META_INTERFACE(BatteryPropertiesRegistrar);
- virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- };
- class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
- };
- }; // namespace android
- #endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H
咦,我們可以看到IBatteryPropertiesRegistrar 繼承於 IInterface ,還有一個類BnBatteryPropertiesRegistrar 繼承於BnInterface。 而且還調用了
- DECLARE_META_INTERFACE(BatteryPropertiesRegistrar);
\frameworks\native\services\batteryservice\IBatteryPropertiesRegistrar.cpp的內容
- #define LOG_TAG "IBatteryPropertiesRegistrar"
- //#define LOG_NDEBUG 0
- #include <utils/Log.h>
- #include <batteryservice/IBatteryPropertiesListener.h>
- #include <batteryservice/IBatteryPropertiesRegistrar.h>
- #include <stdint.h>
- #include <sys/types.h>
- #include <binder/Parcel.h>
- namespace android {
- class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> {
- public:
- BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)
- : BpInterface<IBatteryPropertiesRegistrar>(impl) {}
- void registerListener(const sp<IBatteryPropertiesListener>& listener) {
- Parcel data;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(listener->asBinder());
- remote()->transact(REGISTER_LISTENER, data, NULL);
- }
- void unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
- Parcel data;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(listener->asBinder());
- remote()->transact(UNREGISTER_LISTENER, data, NULL);
- }
- };
- IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar");
- status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags)
- {
- switch(code) {
- case REGISTER_LISTENER: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- sp<IBatteryPropertiesListener> listener =
- interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
- //這個方法並不是上面 BpBatteryPropertiesRegistrar中的registerListener(),他們就不是一個類。這個方法還未實現
- registerListener(listener);
- return OK;
- }
- case UNREGISTER_LISTENER: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- sp<IBatteryPropertiesListener> listener =
- interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
- //這個方法並不是上面 BpBatteryPropertiesRegistrar中的unregisterListener(),他們就不是一個類。這個方法還未實現
- unregisterListener(listener);
- return OK;
- }
- }
- return BBinder::onTransact(code, data, reply, flags);
- };
- // ----------------------------------------------------------------------------
- }; // namespace android
\system\core\healthd\BatteryPropertiesRegistrar.cpp 中實現的。
\system\core\healthd\BatteryPropertiesRegistrar.h 中的內容:
- #ifndef HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
- #define HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
- #include "BatteryMonitor.h"
- #include <binder/IBinder.h>
- #include <utils/Mutex.h>
- #include <utils/Vector.h>
- #include <batteryservice/BatteryService.h>
- #include <batteryservice/IBatteryPropertiesListener.h>
- #include <batteryservice/IBatteryPropertiesRegistrar.h>
- namespace android {
- class BatteryMonitor;
- class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar,
- public IBinder::DeathRecipient {
- public:
- BatteryPropertiesRegistrar(BatteryMonitor* monitor);
- void publish();
- void notifyListeners(struct BatteryProperties props);
- private:
- BatteryMonitor* mBatteryMonitor;
- Mutex mRegistrationLock;
- Vector<sp<IBatteryPropertiesListener> > mListeners;
- void registerListener(const sp<IBatteryPropertiesListener>& listener);
- void unregisterListener(const sp<IBatteryPropertiesListener>& listener);
- void binderDied(const wp<IBinder>& who);
- };
- }; // namespace android
- #endif // HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
然後是\system\core\healthd\BatteryPropertiesRegistrar.cpp 的內容:
- #include "BatteryPropertiesRegistrar.h"
- #include <batteryservice/BatteryService.h>
- #include <batteryservice/IBatteryPropertiesListener.h>
- #include <batteryservice/IBatteryPropertiesRegistrar.h>
- #include <binder/IServiceManager.h>
- #include <utils/Errors.h>
- #include <utils/Mutex.h>
- #include <utils/String16.h>
- namespace android {
- BatteryPropertiesRegistrar::BatteryPropertiesRegistrar(BatteryMonitor* monitor) {
- mBatteryMonitor = monitor;
- }
- void BatteryPropertiesRegistrar::publish() {
- defaultServiceManager()->addService(String16("batterypropreg"), this);
- }
- void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {
- Mutex::Autolock _l(mRegistrationLock);
- for (size_t i = 0; i < mListeners.size(); i++) {
- mListeners[i]->batteryPropertiesChanged(props);
- }
- }
- void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {
- {
- Mutex::Autolock _l(mRegistrationLock);
- // check whether this is a duplicate
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == listener->asBinder()) {
- return;
- }
- }
- mListeners.add(listener);
- listener->asBinder()->linkToDeath(this);
- }
- mBatteryMonitor->update();
- }
- void BatteryPropertiesRegistrar::unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
- Mutex::Autolock _l(mRegistrationLock);
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == listener->asBinder()) {
- mListeners[i]->asBinder()->unlinkToDeath(this);
- mListeners.removeAt(i);
- break;
- }
- }
- }
- void BatteryPropertiesRegistrar::binderDied(const wp<IBinder>& who) {
- Mutex::Autolock _l(mRegistrationLock);
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == who) {
- mListeners.removeAt(i);
- break;
- }
- }
- }
- } // 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
- #ifndef ANDROID_IBATTERYPROPERTIESLISTENER_H
- #define ANDROID_IBATTERYPROPERTIESLISTENER_H
- #include <binder/IBinder.h>
- #include <binder/IInterface.h>
- #include <batteryservice/BatteryService.h>
- namespace android {
- // must be kept in sync with interface defined in IBatteryPropertiesListener.aidl
- enum {
- TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION,
- };
- // ----------------------------------------------------------------------------
- class IBatteryPropertiesListener : public IInterface {
- public:
- DECLARE_META_INTERFACE(BatteryPropertiesListener);
- virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0;
- };
- // ----------------------------------------------------------------------------
- }; // namespace android
- #endif
咦,這個依然用的是Binder 機制。這裏進行代理與服務端的聲明。
IBatteryPropertiesListener.cpp:
- #include <stdint.h>
- #include <sys/types.h>
- #include <batteryservice/IBatteryPropertiesListener.h>
- #include <binder/Parcel.h>
- namespace android {
- class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener>
- {
- public:
- BpBatteryPropertiesListener(const sp<IBinder>& impl)
- : BpInterface<IBatteryPropertiesListener>(impl)
- {
- }
- void batteryPropertiesChanged(struct BatteryProperties props)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor());
- data.writeInt32(1);
- props.writeToParcel(&data);
- status_t err = remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);
- }
- };
- IMPLEMENT_META_INTERFACE(BatteryPropertiesListener, "android.os.IBatteryPropertiesListener");
- // ----------------------------------------------------------------------------
- }; // namespace android
這裏進行代理的實現。 但是並沒有對服務端進行實現。這個應該是在BatteryService.java 中的:
- private final class BatteryListener extends IBatteryPropertiesListener.Stub {
- public void batteryPropertiesChanged(BatteryProperties props) {
- BatteryService.this.update(props);
- }
中進行實現的。
到這裏我們對於第二個問題:屬性變化後調用誰註冊的監聽。 還沒有解決, 只是瞭解下注冊類與註冊接口。那麼真正註冊在那呢? 是在\frameworks\base\services\java\com\android\server\BatteryService.java中:
這個BatteryService 繼承於Binder 類,在他的構造函數中,是這麼註冊的:
- mBatteryPropertiesListener = new BatteryListener();
- IBinder b = ServiceManager.getService("batterypropreg");
- mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
- try {
- mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
- } catch (RemoteException e) {
- // Should never happen.
- }
大家不禁要問了。這裏是Java 代碼呀,怎麼掉的C++的呢,這就是Binder機制了。 而且上面所述的 IBatteryPropertiesListener 、IBatteryPropertiesRegistrar 在Java層都有對應的aidl 文件。目錄:
\frameworks\base\core\java\android\os\IBatteryPropertiesListener.aidl
- package android.os;
- import android.os.BatteryProperties;
- /**
- * {@hide}
- */
- oneway interface IBatteryPropertiesListener {
- void batteryPropertiesChanged(in BatteryProperties props);
- }
\frameworks\base\core\java\android\os\IBatteryPropertiesRegistrar.aidl
- package android.os;
- import android.os.IBatteryPropertiesListener;
- /**
- * {@hide}
- */
- interface IBatteryPropertiesRegistrar {
- void registerListener(IBatteryPropertiesListener listener);
- void unregisterListener(IBatteryPropertiesListener listener);
- }
當編譯的時候會自動生成 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)