Android 6.0 Healthd

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

main函数
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")) {
        healthd_mode_ops = &charger_ops;
    } else {
        while ((ch = getopt(argc, argv, "cr")) != -1) {
            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();//healthd主函数
    KLOG_ERROR("Main loop terminated, exiting\n");
    return 3;
}
如果是正常开机,不走关机充电等,healthd_mode_ops = &android_ops;而这里面具体的函数在后面进行详细的介绍。

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
heathd使用了epoll进行IO复用

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

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设置alarm唤醒的interval,再来看下时间处理函数
static void wakealarm_event(uint32_t /*epevents*/) {
    unsigned long long wakeups;
 
    if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {
        KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n");
        return;
    }
 
    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).
 
   int new_wake_interval = gBatteryMonitor->update() ?//调用主要的update函数,根据返回值,如果当前在充电返回true 
       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;

uevent_init
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的处理函数,获取uevent后主要判断是否是电源系统的,如果是调用healthd_battery_update函数

扫描二维码关注公众号,回复: 5475660 查看本文章

#define UEVENT_MSG_LEN 2048
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;
 
    while (*cp) {
        if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {//是这个子系统的调用healthd_battery_update函数
            healthd_battery_update();
            break;
        }
 
        /* advance to after the next \0 */
        while (*cp++)
            ;
    }
}

下面分析下healthd_mainloop这个主函数,主函数主要是epoll函数监听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为超时时间
 
        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的事件上来,每个处理函数处理
                (*(void (*)(int))events[n].data.ptr)(events[n].events);
        }
 
        if (!nevents)//没有event的时候也需要update
            periodic_chores();
 
        healthd_mode_ops->heartbeat();
    }
 
    return;
}


BatteryMonitor::init
gBatteryMonitor->init(&healthd_config),init函数主要将healthd_config 对象传入,并且将里面的成员的一些地址信息去初始化保存起来。主要是保存一些地址信息,以及充电方式
void BatteryMonitor::init(struct healthd_config *hc) {
    String8 path;
    char pval[PROPERTY_VALUE_MAX];
 
    mHealthdConfig = hc;//将外面传进来的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读取并且转化为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 就是当前目录名字: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函数,将数据封装在BatteryProperties 中,并且通过healthd_mode_ops->battery_update把BatteryProperties 发给上层

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中取地址,读取节点信息,保存到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里面的内容,如果当前在usb线上充电,那么usb下online里面的内容为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);//将数据传到上层的BatteryService
    return props.chargerAcOnline | props.chargerUsbOnline |//返回当前是否属于充电
            props.chargerWirelessOnline;
}

healthd_mode_ops->battery_update是把数据传到上层
void healthd_mode_android_battery_update(
    struct android::BatteryProperties *props) {
    if (gBatteryPropertiesRegistrar != NULL)
        gBatteryPropertiesRegistrar->notifyListeners(*props);
 
    return;
}

上层会通过binder通信,注册一个回调到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 (IInterface::asBinder(mListeners[i]) == IInterface::asBinder(listener)) {
                return;
            }
        }
 
        mListeners.add(listener);
        IInterface::asBinder(listener)->linkToDeath(this);
    }
    healthd_battery_update();
}

而update函数就是调用了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中去

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接口,当下面调这个接口,就会调用BatteryService的update函数

    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的数据都是被动的,healthd传过来的。有没有主动去healthd查询的

扩展
主动查询数据

    private long queryProperty(int id) {
        long ret;
 
        if (mBatteryPropertiesRegistrar == null) {
            IBinder b = ServiceManager.getService("batteryproperties");//获取batteryproperties Service
            mBatteryPropertiesRegistrar =
                IBatteryPropertiesRegistrar.Stub.asInterface(b);//接口转化下
 
            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;
    }

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);
}

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://根据不同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;
}

猜你喜欢

转载自blog.csdn.net/sdkdlwk/article/details/88354125