Android电池管理体系(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhou12314/article/details/79404348
在前面的文章中我们提到了Android电池模块中的驱动层,该层主要通过充电芯片驱动去读取电池电量,电池状态等信息。在我们在驱动中拿到电池电量信息的时候是怎么一步步传到Android层的,在这里就需要提到health模块。health模块是Android4.4以后推出的,主要用于向下读取电池驱动中的电量信息,然后向上传递给Framwork中的 BatteryService.
该篇文章主要就Android health模块进行分析(下面关键代码会有注释):
Health模块的代码位置位于/system/core/healthd/,其入口在Healthd.cpp中的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();  //主要做初始化的工作
    if (ret) {
        KLOG_ERROR("Initialization failed, exiting\n");
        exit(2);
    }

    healthd_mainloop();
    KLOG_ERROR("Main loop terminated, exiting\n");
    return 3;
}


healthd_mode_ops是一个充电状态的结构体, 正常开机情况下会 将android_ops结构体赋值给healthd_mode_ops ,如果在关机情况下会将 charget_ops结构体赋值给healthd_mode_opos,就是关机充电的使用。

然后在healthd_init中,主要做一些初始化工作:
  static int healthd_init() {
    epollfd = epoll_create(MAX_EPOLL_EVENTS); //创建epoll用于
    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;
}



在上面的代码中首先创建了一个epoll,主要用于将文件指针挂在工作队列中,用于轮询查看驱动层是否发来信息,然后调用uevent_init()对uevent进行注册,应为从上篇文章我们明白,电池驱动是通过uevent与health进行通信的,uevent通信本质上就是socket通信,这里不详细说了。

然后调用完healthd_init(),接下来比较重要的就是执行healthd_mainloop()了

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

        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 (*)(int))events[n].data.ptr)(events[n].events);
        }

        if (!nevents)
            periodic_chores();

        healthd_mode_ops->heartbeat();
    }
    return;
}



可以看到,在这里直接开启了一个无线循环,监听是否有uevent事件到来,如果在for循环中检测到uevent事件到来的时候,会直接调用 uevent_event函数
   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();
            break;
        }

        /* advance to after the next \0 */
        while (*cp++)
            ;
    }
}


在uevent_event函数中,会判断SSUBSYSTEM是否等于POWER_SUPPLY_SUBSYSTEM,如果是的话,说明是电池驱动传过来的信息,会执行 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() ?
       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中的update()函数,对电池的各个属性进行更新,并在最后调用在前面注册的监听进行上报
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;
    props.maxChargingCurrent = 0;

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

    // For devices which do not have battery and are always plugged
    // into power souce.
    if (mAlwaysPluggedDevice) {
        props.chargerAcOnline = true;
        props.batteryPresent = true;
        props.batteryStatus = BATTERY_STATUS_CHARGING;
        props.batteryHealth = BATTERY_HEALTH_GOOD;
    }

    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)) {  //判断充电状态,看是否AC或者USB充电还是无线充电
                case ANDROID_POWER_SUPPLY_TYPE_AC: //当前为电源适配器充电
                    props.chargerAcOnline = true;
                    break;
                case ANDROID_POWER_SUPPLY_TYPE_USB: //当前为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());
                }
                path.clear();
                path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
                                  mChargerNames[i].string());
                if (access(path.string(), R_OK) == 0) {
                    int maxChargingCurrent = getIntField(path);
                    if (props.maxChargingCurrent < maxChargingCurrent) {
                        props.maxChargingCurrent = maxChargingCurrent;
                    }
                }
            }
        }
    }

    //读取电池节点信息
    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");
        }

        size_t len = strlen(dmesgline);
        //存储当前电池状态
        snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
                 props.chargerAcOnline ? "a" : "",
                 props.chargerUsbOnline ? "u" : "",
                 props.chargerWirelessOnline ? "w" : "");

        log_time realtime(CLOCK_REALTIME);
        time_t t = realtime.tv_sec;
        struct tm *tmp = gmtime(&t);
        if (tmp) {
            static const char fmt[] = " %Y-%m-%d %H:%M:%S.XXXXXXXXX UTC";
            len = strlen(dmesgline);
            if ((len < (sizeof(dmesgline) - sizeof(fmt) - 8)) // margin
                    && strftime(dmesgline + len, sizeof(dmesgline) - len,
                                fmt, tmp)) {
                char *usec = strchr(dmesgline + len, 'X');
                if (usec) {
                    len = usec - dmesgline;
                    snprintf(dmesgline + len, sizeof(dmesgline) - len,
                             "%09u", realtime.tv_nsec);
                    usec[9] = ' ';
                }
            }
        }

        KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
    }

    healthd_mode_ops->battery_update(&props); //向上更新电池状态
    return props.chargerAcOnline | props.chargerUsbOnline |
            props.chargerWirelessOnline;   //当前为电源充电或者USB充电或者无线充电
}





在该函数中调用 healthd_mode_ops->battery_update(&props) 进行,其中battery_update(&props)为在health.cpp中初始化的结构体,最后返回当前的充电状态。

battery_update()调用的函数如下,调用注册的监听进行上报:

void healthd_mode_android_battery_update(
    struct android::BatteryProperties *props) {
    if (gBatteryPropertiesRegistrar != NULL)
        gBatteryPropertiesRegistrar->notifyListeners(*props); //调用监听并传入属性值
    return;
}



截至到这里health()模块就分析完了,接着gBatteryPropertiesRegistrar 这个监听就会回调在framwork层实现的函数,然后通过Binder机制向上层通信,这个在下一篇文章中分析

猜你喜欢

转载自blog.csdn.net/zhou12314/article/details/79404348
今日推荐