欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入解析android5.1 healthd

 更新時間:2018年01月12日 09:00:58   作者:kc專欄  
這篇文章主要為大家詳細(xì)介紹了android5.1 healthd的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

healthd主要是讀取電池節(jié)點的信息,傳給BatteryService?;蛘咴陉P(guān)機(jī)充電等使用。注意healthd中使用的是kernel的log。

下面先從main函數(shù)分析

int main(int argc, char **argv) { 
 int ch; 
 int ret; 
 
 klog_set_level(KLOG_LEVEL); 
 healthd_mode_ops = &android_ops; 
 
 if (!strcmp(basename(argv[0]), "charger")) {//解析輸入?yún)?shù)如果是charger的使用charger_ops,這里就不做介紹 
  healthd_mode_ops = &charger_ops; 
 } else { 
  while ((ch = getopt(argc, argv, "cr")) != -1) {//分析輸入命令,各個命令對應(yīng)不同的charger_ops 
   switch (ch) { 
   case 'c': 
    healthd_mode_ops = &charger_ops; 
    break; 
   case 'r': 
    healthd_mode_ops = &recovery_ops; 
    break; 
   case '?': 
   default: 
    KLOG_ERROR(LOG_TAG, "Unrecognized healthd option: %c\n", 
       optopt); 
    exit(1); 
   } 
  } 
 } 
 
 ret = healthd_init();//healthd做初始化 
 if (ret) { 
  KLOG_ERROR("Initialization failed, exiting\n"); 
  exit(2); 
 } 
 
 healthd_mainloop();//主函數(shù) 
 KLOG_ERROR("Main loop terminated, exiting\n"); 
 return 3; 
} 

如果是正常開機(jī),不走關(guān)機(jī)充電等,healthd_mode_ops = &android_ops;而這里面具體的函數(shù)在后面進(jìn)行詳細(xì)的介紹。

static struct healthd_mode_ops android_ops = { 
 .init = healthd_mode_android_init, 
 .preparetowait = healthd_mode_android_preparetowait, 
 .heartbeat = healthd_mode_nop_heartbeat, 
 .battery_update = healthd_mode_android_battery_update, 
}; 

下面分析下healthd_init函數(shù),heathd使用了epoll進(jìn)行IO復(fù)用。

static int healthd_init() { 
 epollfd = epoll_create(MAX_EPOLL_EVENTS); 
 if (epollfd == -1) { 
  KLOG_ERROR(LOG_TAG, 
     "epoll_create failed; errno=%d\n", 
     errno); 
  return -1; 
 } 
 
 healthd_board_init(&healthd_config); 
 healthd_mode_ops->init(&healthd_config); 
 wakealarm_init(); 
 uevent_init(); 
 gBatteryMonitor = new BatteryMonitor(); 
 gBatteryMonitor->init(&healthd_config); 
 return 0; 
} 

這里的healthd_mode_ops->init的函數(shù)是android_ops 的healthd_mode_android_init函數(shù),這里主要是將binder通信的fd也加入epoll,而不像普通binder進(jìn)程最后使用IPCThreadState::self()->joinThreadPool。這樣所有的fd全在epoll管理,只用了一個線程

int healthd_mode_android_preparetowait(void) { 
 IPCThreadState::self()->flushCommands(); 
 return -1; 
} 
 
static void binder_event(uint32_t /*epevents*/) { 
 IPCThreadState::self()->handlePolledCommands(); 
} 
 
void healthd_mode_android_init(struct healthd_config* /*config*/) { 
 ProcessState::self()->setThreadPoolMaxThreadCount(0); 
 IPCThreadState::self()->disableBackgroundScheduling(true); 
 IPCThreadState::self()->setupPolling(&gBinderFd); 
 
 if (gBinderFd >= 0) { 
  if (healthd_register_event(gBinderFd, binder_event)) 
   KLOG_ERROR(LOG_TAG, 
      "Register for binder events failed\n"); 
 } 
 
 gBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(); 
 gBatteryPropertiesRegistrar->publish(); 
} 

gBatteryPropertiesRegistrar->publish將"batteryproperties"這個Service加入到ServiceManager中

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

接下來再來看下wakealarm_init

static void wakealarm_init(void) { 
 wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK); 
 if (wakealarm_fd == -1) { 
  KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n"); 
  return; 
 } 
 
 if (healthd_register_event(wakealarm_fd, wakealarm_event)) 
  KLOG_ERROR(LOG_TAG, 
     "Registration of wakealarm event failed\n"); 
 
 wakealarm_set_interval(healthd_config.periodic_chores_interval_fast); 
} 

wakealarm_init設(shè)置alarm喚醒的interval,再來看下時間處理函數(shù)

static void wakealarm_event(uint32_t /*epevents*/) { 
 unsigned long long wakeups; 
 
 if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {//出錯結(jié)束 
  KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n"); 
  return; 
 } 
 KLOG_ERROR(LOG_TAG, "wakealarm_event\n"); 
 periodic_chores(); 
} 
static void periodic_chores() { 
 healthd_battery_update(); 
} 
void healthd_battery_update(void) { 
 // Fast wake interval when on charger (watch for overheat); 
 // slow wake interval when on battery (watch for drained battery). 
 KLOG_ERROR(LOG_TAG, "healthd_battery_update enter\n"); 
 int new_wake_interval = gBatteryMonitor->update() ?//調(diào)用主要的update函數(shù),根據(jù)返回值,如果當(dāng)前在充電返回true 
  healthd_config.periodic_chores_interval_fast ://時間設(shè)置1分鐘 
   healthd_config.periodic_chores_interval_slow; 
 KLOG_ERROR(LOG_TAG, "healthd_battery_update after\n"); 
 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 ?//當(dāng)前時間是一分鐘,epoll為永遠(yuǎn)阻塞,否則為1分鐘 
    -1 : healthd_config.periodic_chores_interval_fast * 1000; 
} 

接下來再來看看uEvent的,

static void uevent_init(void) { 
 uevent_fd = uevent_open_socket(64*1024, true); 
 
 if (uevent_fd < 0) { 
  KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n"); 
  return; 
 } 
  
 fcntl(uevent_fd, F_SETFL, O_NONBLOCK); 
 if (healthd_register_event(uevent_fd, uevent_event)) 
  KLOG_ERROR(LOG_TAG, 
     "register for uevent events failed\n"); 
} 

看看uevent_event的處理函數(shù),獲取uevent后主要判斷是否是電源系統(tǒng)的,如果是調(diào)用healthd_battery_update函數(shù)

static void uevent_event(uint32_t /*epevents*/) { 
 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; 
 KLOG_ERROR(LOG_TAG, "uevent_event\n"); 
 while (*cp) { 
  if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {//是這個子系統(tǒng)的調(diào)用healthd_battery_update函數(shù) 
   healthd_battery_update(); 
   break; 
  } 
 
  /* advance to after the next \0 */ 
  while (*cp++) 
   ; 
 } 
} 

下面分析下healthd_mainloop這個主函數(shù),主函數(shù)主要是epoll函數(shù)監(jiān)聽3個fd,有事件就處理。

static void healthd_mainloop(void) { 
 while (1) { 
  struct epoll_event events[eventct]; 
  int nevents; 
  int timeout = awake_poll_interval; 
  int mode_timeout; 
 
  mode_timeout = healthd_mode_ops->preparetowait(); 
  if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) 
   timeout = mode_timeout; 
  nevents = epoll_wait(epollfd, events, eventct, timeout);//epoll_wait等待各個fd的事件,timeout為超時時間 
  KLOG_ERROR(LOG_TAG, "kangchen healthd_mainloop epoll_wait\n"); 
  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)//遍歷各個fd的事件上來,每個處理函數(shù)處理 
    (*(void (*)(int))events[n].data.ptr)(events[n].events); 
  } 
 
  if (!nevents)//當(dāng)什么事件沒有的時候,是因為epoll超時設(shè)置走下來的,這時候也要update下 
   periodic_chores(); 
 
  healthd_mode_ops->heartbeat(); 
 } 
 
 return; 
} 

init函數(shù)主要將healthd_config 對象傳入,并且將里面的成員的一些地址信息去初始化保存起來。主要是保存一些地址信息,以及充電方式。

void BatteryMonitor::init(struct healthd_config *hc) { 
 String8 path; 
 char pval[PROPERTY_VALUE_MAX]; 
 
 mHealthdConfig = hc;//將外面?zhèn)鬟M(jìn)來的heathdconfig的指針賦給成員變量 
 DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);//打開地址 /sys/class/power_supply 
 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)) {//讀取各個目錄下type的值,比如/sys/class/power_supply/battery 下type的值為Battery,在readPowerSupplyType讀取并且轉(zhuǎn)化為ANDROID_POWER_SUPPLY_TYPE_BATTERY 
   case ANDROID_POWER_SUPPLY_TYPE_AC: 
    if (mHealthdConfig->acChargeHeathPath.isEmpty()) { 
     path.clear(); 
     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, 
          name); 
     if (access(path, R_OK) == 0) 
      mHealthdConfig->acChargeHeathPath = path;//配置路徑 
    } 
    path.clear(); 
    path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); 
    if (access(path.string(), R_OK) == 0) 
     mChargerNames.add(String8(name));//chargername 就是當(dāng)前目錄名字:ac 
    break; 
 
   case ANDROID_POWER_SUPPLY_TYPE_USB://usb 類似ac 
    if (mHealthdConfig->usbChargeHeathPath.isEmpty()) { 
     path.clear(); 
     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, 
          name); 
     if (access(path, R_OK) == 0) 
      mHealthdConfig->usbChargeHeathPath = path; 
    } 
    path.clear(); 
    path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); 
    if (access(path.string(), R_OK) == 0) 
     mChargerNames.add(String8(name)); 
    break; 
 
   case ANDROID_POWER_SUPPLY_TYPE_WIRELESS://類似 
    path.clear(); 
    path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); 
    if (access(path.string(), R_OK) == 0) 
     mChargerNames.add(String8(name)); 
    break; 
 
   case ANDROID_POWER_SUPPLY_TYPE_BATTERY://battery 
    mBatteryDevicePresent = true; 
 
    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->batteryCurrentAvgPath.isEmpty()) { 
     path.clear(); 
     path.appendFormat("%s/%s/current_avg", 
          POWER_SUPPLY_SYSFS_PATH, name); 
     if (access(path, R_OK) == 0) 
      mHealthdConfig->batteryCurrentAvgPath = 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 (!mBatteryDevicePresent) {//主要由battery該成員變量就為true 
  KLOG_WARNING(LOG_TAG, "No battery devices found\n"); 
  hc->periodic_chores_interval_fast = -1; 
  hc->periodic_chores_interval_slow = -1; 
 } else { 
  if (mHealthdConfig->batteryStatusPath.isEmpty()) 
   KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n"); 
。。。。。。。。。。。。。//這里都是一些警告 
 } 
 
 if (property_get("ro.boot.fake_battery", pval, NULL) > 0 
            && strtol(pval, NULL, 10) != 0) { 
  mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY; 
  mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; 
 } 
} 

下面就是update函數(shù),將數(shù)據(jù)封裝在BatteryProperties 中,并且通過healthd_mode_ops->battery_update把BatteryProperties 發(fā)給上層。

bool BatteryMonitor::update(void) { 
 bool logthis; 
 
 props.chargerAcOnline = false; 
 props.chargerUsbOnline = false; 
 props.chargerWirelessOnline = false; 
 props.batteryStatus = BATTERY_STATUS_UNKNOWN; 
 props.batteryHealth = BATTERY_HEALTH_UNKNOWN; 
//都是從之前配置的mHealthd中取地址,讀取節(jié)點信息,保存到props成員變量中 
 if (!mHealthdConfig->batteryPresentPath.isEmpty()) 
  props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath); 
 else 
  props.batteryPresent = mBatteryDevicePresent; 
 
 props.batteryLevel = mBatteryFixedCapacity ? 
  mBatteryFixedCapacity : 
  getIntField(mHealthdConfig->batteryCapacityPath); 
 props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000; 
 
 props.batteryTemperature = mBatteryFixedTemperature ? 
  mBatteryFixedTemperature : 
  getIntField(mHealthdConfig->batteryTemperaturePath); 
 
 const int SIZE = 128; 
 char buf[SIZE]; 
 String8 btech; 
 
 if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0) 
  props.batteryStatus = getBatteryStatus(buf); 
 
 if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0) 
  props.batteryHealth = getBatteryHealth(buf); 
 
 if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0) 
  props.batteryTechnology = String8(buf); 
 
 if (readFromFile(mHealthdConfig->acChargeHeathPath, buf, SIZE) > 0) 
  props.acChargeHeath= String8(buf); 
 
 if (readFromFile(mHealthdConfig->usbChargeHeathPath, buf, SIZE) > 0) 
  props.usbChargeHeath= String8(buf); 
 
 unsigned int i; 
 
 for (i = 0; i < mChargerNames.size(); i++) {//遍歷之前保存的各個充電方式 
  String8 path; 
  path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, 
       mChargerNames[i].string());//路徑就是每個目錄下的online字段,比如/sys/class/power_supply/usb 下的online 
 
  if (readFromFile(path, buf, SIZE) > 0) { 
   if (buf[0] != '0') {//讀取online里面的內(nèi)容,如果當(dāng)前在usb線上充電,那么usb下online里面的內(nèi)容為1 
    path.clear(); 
    path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, 
         mChargerNames[i].string());//這里看看是哪個type的 
    switch(readPowerSupplyType(path)) { 
    case ANDROID_POWER_SUPPLY_TYPE_AC: 
     props.chargerAcOnline = true; 
     break; 
    case ANDROID_POWER_SUPPLY_TYPE_USB://將其值賦成true 
     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]; 
 
  if (props.batteryPresent) { 
   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()) { 
    int c = getIntField(mHealthdConfig->batteryCurrentNowPath); 
    char b[20]; 
 
    snprintf(b, sizeof(b), " c=%d", c / 1000); 
    strlcat(dmesgline, b, sizeof(dmesgline)); 
   } 
  } else { 
   snprintf(dmesgline, sizeof(dmesgline), 
     "battery none"); 
  } 
 
  KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline, 
      props.chargerAcOnline ? "a" : "", 
      props.chargerUsbOnline ? "u" : "", 
      props.chargerWirelessOnline ? "w" : ""); 
 } 
 
 healthd_mode_ops->battery_update(&props);//將數(shù)據(jù)傳到上層的BatteryService 
 return props.chargerAcOnline | props.chargerUsbOnline |//返回當(dāng)前是否屬于充電 
   props.chargerWirelessOnline; 
} 

接下來看看healthd_mode_ops->battery_update是怎么把數(shù)據(jù)傳到上層的

void healthd_mode_android_battery_update( 
 struct android::BatteryProperties *props) { 
 if (gBatteryPropertiesRegistrar != NULL) 
  gBatteryPropertiesRegistrar->notifyListeners(*props); 
 
 return; 
} 

上層會通過binder通信,注冊一個回調(diào)到BatteryPropertiesRegistrar

void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) { 
 { 
  if (listener == NULL) 
   return; 
  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); 
 } 
 healthd_battery_update(); 
} 

而update函數(shù)就是調(diào)用了notifyListeners遍歷各個listener傳到上層BatteryService

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

再來看看BatteryService中,在onStart中通過ServiceManager,和batteryproperties這個Service通信,將BatteryListener這個listenter注冊到batteryproperties中去

@Override 
public void onStart() { 
 IBinder b = ServiceManager.getService("batteryproperties"); 
 final IBatteryPropertiesRegistrar batteryPropertiesRegistrar = 
   IBatteryPropertiesRegistrar.Stub.asInterface(b); 
 try { 
  batteryPropertiesRegistrar.registerListener(new BatteryListener()); 
 } catch (RemoteException e) { 
  // Should never happen. 
 } 
 
 publishBinderService("battery", new BinderService()); 
 publishLocalService(BatteryManagerInternal.class, new LocalService()); 
} 

再來看看BatteryListener 的batteryPropertiesChanged接口,當(dāng)下面調(diào)這個接口,就會調(diào)用BatteryService的update函數(shù),然后就是BatteryService的一些主要流程就不分析了。

private final class BatteryListener extends IBatteryPropertiesListener.Stub { 
 @Override 
 public void batteryPropertiesChanged(BatteryProperties props) { 
  final long identity = Binder.clearCallingIdentity(); 
  try { 
   BatteryService.this.update(props); 
  } finally { 
   Binder.restoreCallingIdentity(identity); 
  } 
 } 
} 

BatteryService接受healthd的數(shù)據(jù)都是被動的,healthd穿過來的。有沒有主動去healthd查詢的。

在BatteryManager中就有主動去healthd查詢的,代碼如下

private long queryProperty(int id) { 
 long ret; 
 
 if (mBatteryPropertiesRegistrar == null) { 
  IBinder b = ServiceManager.getService("batteryproperties");//獲取batteryproperties Service 
  mBatteryPropertiesRegistrar = 
   IBatteryPropertiesRegistrar.Stub.asInterface(b);//接口轉(zhuǎn)化下 
 
  if (mBatteryPropertiesRegistrar == null) 
   return Long.MIN_VALUE; 
 } 
 
 try { 
  BatteryProperty prop = new BatteryProperty(); 
 
  if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)//prop是輸出 
   ret = prop.getLong(); 
  else 
   ret = Long.MIN_VALUE; 
 } catch (RemoteException e) { 
  ret = Long.MIN_VALUE; 
 } 
 
 return ret; 
} 

再到healthd看看對應(yīng)的接口

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

status_t healthd_get_property(int id, struct BatteryProperty *val) { 
 return gBatteryMonitor->getProperty(id, val); 
} 

java的BatteryProperty對象對應(yīng)到這邊是指針

status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) { 
 status_t ret = BAD_VALUE; 
 
 val->valueInt64 = LONG_MIN; 
 
 switch(id) { 
 case BATTERY_PROP_CHARGE_COUNTER://根據(jù)不同ID,返回不同值 
  if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) { 
   val->valueInt64 = 
    getIntField(mHealthdConfig->batteryChargeCounterPath); 
   ret = NO_ERROR; 
  } else { 
   ret = NAME_NOT_FOUND; 
  } 
  break; 
 
 case BATTERY_PROP_CURRENT_NOW: 
  if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 
   val->valueInt64 = 
    getIntField(mHealthdConfig->batteryCurrentNowPath); 
   ret = NO_ERROR; 
  } else { 
   ret = NAME_NOT_FOUND; 
  } 
  break; 
 
 case BATTERY_PROP_CURRENT_AVG: 
  if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) { 
   val->valueInt64 = 
    getIntField(mHealthdConfig->batteryCurrentAvgPath); 
   ret = NO_ERROR; 
  } else { 
   ret = NAME_NOT_FOUND; 
  } 
  break; 
 
 case BATTERY_PROP_CAPACITY: 
  if (!mHealthdConfig->batteryCapacityPath.isEmpty()) { 
   val->valueInt64 = 
    getIntField(mHealthdConfig->batteryCapacityPath); 
   ret = NO_ERROR; 
  } else { 
   ret = NAME_NOT_FOUND; 
  } 
  break; 
 
 case BATTERY_PROP_ENERGY_COUNTER: 
  if (mHealthdConfig->energyCounter) { 
   ret = mHealthdConfig->energyCounter(&val->valueInt64); 
  } else { 
   ret = NAME_NOT_FOUND; 
  } 
  break; 
 
 default: 
  break; 
 } 
 
 return ret; 
} 

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 微信舉報解除和微信解除限制的6個方法

    微信舉報解除和微信解除限制的6個方法

    本文主要介紹微信被舉報怎么解除?微信解除限制,這里整理了6種方法,有需要的小伙伴可以參考下
    2016-09-09
  • Android自定義View實現(xiàn)垂直時間軸布局

    Android自定義View實現(xiàn)垂直時間軸布局

    這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)垂直時間軸布局的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • android 上傳aar到私有maven服務(wù)器的示例

    android 上傳aar到私有maven服務(wù)器的示例

    這篇文章主要介紹了android 上傳aar到私有maven服務(wù)器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • Android實現(xiàn)登陸界面的記住密碼功能

    Android實現(xiàn)登陸界面的記住密碼功能

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)登陸界面的記住密碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 21天學(xué)習(xí)android開發(fā)教程之XML解析與生成

    21天學(xué)習(xí)android開發(fā)教程之XML解析與生成

    21天學(xué)習(xí)android開發(fā)教程之XML解析與生成,使用SAX來解析XML,在Android里面可以使用SAX和DOM,DOM需要把整個XML文件讀入內(nèi)存再解析,比較消耗內(nèi)存,而SAX基于事件驅(qū)動的處理方式,可以在各節(jié)點觸發(fā)回調(diào)函數(shù),需要的朋友可以參考下
    2016-02-02
  • Android中NestedScrolling滑動機(jī)制詳解

    Android中NestedScrolling滑動機(jī)制詳解

    本篇文章主要介紹了Android中NestedScrolling滑動機(jī)制詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • Android使用TouchDelegate增加View的觸摸范圍

    Android使用TouchDelegate增加View的觸摸范圍

    這篇文章主要為大家詳細(xì)介紹了Android使用TouchDelegate增加View的觸摸范圍,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Android Jetpack組件庫LiveData源碼深入探究

    Android Jetpack組件庫LiveData源碼深入探究

    LiveData是Jetpack組件的一部分,更多的時候是搭配ViewModel來使用,相對于Observable,LiveData的最大優(yōu)勢是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動生命周期狀態(tài)的時候才會更新數(shù)據(jù)
    2022-09-09
  • Android Flutter實現(xiàn)上拉加載組件的示例代碼

    Android Flutter實現(xiàn)上拉加載組件的示例代碼

    既然列表有下拉刷新外當(dāng)然還有上拉加載更多操作了,本次就為大家詳細(xì)介紹如何利用Flutter實現(xiàn)為列表增加上拉加載更多的交互,感興趣的可以了解一下
    2022-08-08
  • Android基于Pull方式解析xml的方法詳解

    Android基于Pull方式解析xml的方法詳解

    這篇文章主要介紹了Android基于Pull方式解析xml的方法,結(jié)合實例形式詳細(xì)分析了Pull方式解析xml的原理、操作步驟與相關(guān)技巧,需要的朋友可以參考下
    2016-07-07

最新評論