关机充电 分析 -- charger代码分析(Android4.2)

http://blog.csdn.net/u010223349/article/details/8822747

 

Android charger源代码位于system/core/charger目录下,代码量不大,下面就对charger代码作个简单的分析。

 

一、main函数

 

int main(int argc, char **argv)

{

int ret;

 

struct charger *charger = &charger_state;                                            //charger_state是一个charger结构体对象,详见下文第二部分

int64_t now = curr_time_ms() - 1;                                                  //保存当前时间

    int fd;                                  

    int i;

 

    list_init(&charger->supplies);                                                     //初始化供电设备双向链表 

 

    klog_init();                                                                                //设置log输出设备,这里指向/dev/_ksmg_

    klog_set_level(CHARGER_KLOG_LEVEL);                          //设备打印等级为6

 

    dump_last_kmsg();                                                                   //把/dev/last_kmsg中的信息写到/dev/_kmsg_

 

    LOGI("--------------- STARTING CHARGER MODE ---------------\n");

 

    //android提供了一个库minui用于简单的UI输出,源码在bootable/recovery/minui中,

   //gr_init()和gr_font_size()为minui库提供方法,gr_init()为UI输出作准备,gr_font_size()获得字体大小

    gr_init();                                                                          

    gr_font_size(&char_width, &char_height);               

 

    //遍历/dev/input目录下的设备,将EV_REL和EV_KEY设备的信息保存到ev_fds[]等结构体中

    ev_init(input_callback, charger);                              

 

    fd = uevent_open_socket(64*1024, true);                                           //创建一个socket用于接收kernel的uevent

    if (fd >= 0) {

        fcntl(fd, F_SETFL, O_NONBLOCK);

        ev_add_fd(fd, uevent_callback, charger);

    }

    charger->uevent_fd = fd;

    coldboot(charger, "/sys/class/power_supply", "add");                           //让kernel重新发送event

 

     //res_create_surface()为minui库中提供,用于将一张图片生成一个surface

     //这里是生成了一个用于表示电池错误的surface

    ret = res_create_surface("charger/battery_fail", &charger->surf_unknown); 

    if (ret < 0) {

        LOGE("Cannot load image\n");

        charger->surf_unknown = NULL;

    }

 

      //充电画面由几张图片组成,每张图片被称为一帧,charger变量存放的是charger_state

     //变量的指针,charger_state已被初始化过,但是每一个frame的surface字段仍没有初始化,

     //下面这个循环就是初始化每个frame的surface

    for (i = 0; i < charger->batt_anim->num_frames; i++) {

        struct frame *frame = &charger->batt_anim->frames[i];

 

        ret = res_create_surface(frame->name, &frame->surface);

        if (ret < 0) {

            LOGE("Cannot load image %s\n", frame->name);

            /* TODO: free the already allocated surfaces... */

            charger->batt_anim->num_frames = 0;

            charger->batt_anim->num_cycles = 1;

            break;

        }

    }

 

    ev_sync_key_state(set_key_callback, charger);                         //详见下文第三部分

 

#ifndef CHARGER_DISABLE_INIT_BLANK

    gr_fb_blank(true);

#endif

 

    charger->next_screen_transition = now - 1;

    charger->next_key_check = -1;

    charger->next_pwr_check = -1;

    reset_animation(charger->batt_anim);

    kick_animation(charger->batt_anim);

 

     //charger的核心,一个大的循环,详见下文第五部分

    event_loop(charger);              

 

    return 0;

}

 

 

二、charger结构体

 

struct charger {

    int64_t next_screen_transition;

    int64_t next_key_check;

    int64_t next_pwr_check;

 

    struct key_state keys[KEY_MAX + 1];                      //保存按键的状态

    int uevent_fd;                                                              //接收kernel uevent的描述符

 

    struct listnode supplies;                                                //这个listnode用于建立charger对象的双向链表

    int num_supplies;                                                         //供电设备的数量

    int num_supplies_online;                                                //正在连接的供电设备的数量

 

    struct animation *batt_anim;

    gr_surface surf_unknown;

 

    struct power_supply *battery;                                   //电池的信息

};

 

 

 

三、ev_sync_key_state()函数

 

int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data)

{

    unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)];

    unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];

    unsigned i;

    int ret;

 

    for (i = 0; i < ev_dev_count; i++) {

        int code;

 

        memset(key_bits, 0, sizeof(key_bits));

        memset(ev_bits, 0, sizeof(ev_bits));

 

        //测试ev_fds[]中的设备是否有key,如果没有key则continue

        ret = ioctl(ev_fds[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);

        if (ret < 0 || !test_bit(EV_KEY, ev_bits))

            continue;

 

        //检测ev_fd[]中的设备key的状态

        ret = ioctl(ev_fds[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits);

        if (ret < 0)

            continue;

 

        for (code = 0; code <= KEY_MAX; code++) {

           //如果有键被触发,则调用set_key_callback, set_key_callback实现,详见下文第四部分

            if (test_bit(code, key_bits))                   

                 set_key_cb(code, 1, data); 

        }

    }

 

    return 0;

}

 

 

 

 

四、set_key_callback()函数

 

set_key_callback()主要用于记录按键的状态,接受三个参数:code、value、data, code表示键值,value表示按键的状态,data是charger的指针。

 

static int set_key_callback(int code, int value, void *data)

{

    struct charger *charger = data;

    int64_t now = curr_time_ms();

    int down = !!value;

 

    if (code > KEY_MAX)

        return -1;

 

    /* ignore events that don't modify our state */

    if (charger->keys[code].down == down)

        return 0;

 

    /* only record the down even timestamp, as the amount

     * of time the key spent not being pressed is not useful */

    if (down)

        charger->keys[code].timestamp = now;                            //记录按下事件的时间

    charger->keys[code].down = down;                                    //记录按键的状态

    charger->keys[code].pending = true;                 

    if (down) {

        LOGV("[%lld] key[%d] down\n", now, code);

    } else {

        int64_t duration = now - charger->keys[code].timestamp;

        int64_t secs = duration / 1000;

        int64_t msecs = duration - secs * 1000;

        LOGV("[%lld] key[%d] up (was down for %lld.%lldsec)\n", now,

            code, secs, msecs);

    }

 

    return 0;

}

 

 

五、event_loop()函数

 

static void event_loop(struct charger *charger)

{

    int ret;

 

    while (true) {

        int64_t now = curr_time_ms();

 

        LOGV("[%lld] event_loop()\n", now);

        handle_input_state(charger, now);                                             //详见下文第六部分

        handle_power_supply_state(charger, now);                              //详见下文第八部分

 

        /* do screen update last in case any of the above want to start

         * screen transitions (animations, etc)

         */

        update_screen_state(charger, now);                                        //根据上面两个handle_设置的状态进行画面更新

 

         //根据上面操作得到的时间间隔来poll设备,如果有事件,

          //最后会调用set_key_callback()函数来保存按键的事件,供一次循环使用

        wait_next_event(charger, now);      

    }

}

 

六、handle_input_state()函数

 

static void handle_input_state(struct charger *charger, int64_t now)

{

    process_key(charger, KEY_POWER, now);                                //捕捉POWER键的事件,详见下文第七部分

 

    if (charger->next_key_check != -1 && now > charger->next_key_check)

        charger->next_key_check = -1;

}

 

 

七、process_key()函数

 

static void process_key(struct charger *charger, int code, int64_t now)

{

    struct key_state *key = &charger->keys[code];

    int64_t next_key_check;

 

if (code == KEY_POWER) {

           //如果是POWER键,并且是按下事件,则判断是否是长按,

           //长按则重启android正常进入系统,否则设置下次检测按键的时间, wait_next_event()会//用到

        if (key->down) {

            int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;

            if (now >= reboot_timeout) {

                      int fd = open("/sys/devices/platform/asoc_spi.1/spi_master/spi1/spi1.0/set_charger_status", O_RDWR);

                      write(fd, "0x1", strlen("0x1"));

                      close(fd);

 

                LOGI("[%lld] rebooting\n", now);

                android_reboot(ANDROID_RB_RESTART, 0, 0);

            } else {

                /* if the key is pressed but timeout hasn't expired,

                 * make sure we wake up at the right-ish time to check

                 */

                set_next_key_check(charger, key, POWER_ON_KEY_TIME);

            }

 

         //如果产生的不是POWER按键的事件,则显示充电动画

        } else {

            /* if the power key got released, force screen state cycle */

            if (key->pending) {

                request_suspend(false);

                kick_animation(charger->batt_anim);

            }

        }

}

 

 

 

八、handle_power_supply_state()函数

 

static void handle_power_supply_state(struct charger *charger, int64_t now)

{

    //如果当前没有连接供电设备,则在一定时间内重启android进入系统

    if (charger->num_supplies_online == 0) {

        request_suspend(false);

        if (charger->next_pwr_check == -1) {

            charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;

            LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n",

                 now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);

        } else if (now >= charger->next_pwr_check) {

            LOGI("[%lld] shutting down\n", now);

            android_reboot(ANDROID_RB_POWEROFF, 0, 0);

        } else {

            /* otherwise we already have a shutdown timer scheduled */

        }

    //如果连接了充电设备,则显示充电画面

    } else {

        /* online supply present, reset shutdown timer if set */

        if (charger->next_pwr_check != -1) {

            LOGI("[%lld] device plugged in: shutdown cancelled\n", now);

            kick_animation(charger->batt_anim);

        }

        charger->next_pwr_check = -1;

    }

}

 

posted on 2016-08-24 17:22  jamboo  阅读(1172)  评论(0编辑  收藏  举报

导航