http://blog.csdn.net/xnwyd/article/details/42915465
系统进入充电模式时,显示 充电画面,充电画面的代码在/system/core/charger/charger.c,下面对其关键代码进行分析
1)结构体
- /*power_supply信息*/
- struct power_supply {
- /*链表节点*/
- struct listnode list;
- /*power_supply名称,如rk-ac/rk-usb/rk-bat*/
- char name[256];
- //power_supply类型,如Mains/USB/Battery
- char type[32];
- //状态,判断ac,battery或usb的 in/out
- bool online;
- bool valid;
- char cap_path[PATH_MAX];
- };
- /*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];
- //uevent fd,通过此fd读取kernel的power_supply信息
- int uevent_fd;
- //power_supply链表,存储各个power_supply信息
- struct listnode supplies;
- //供电源的数量
- int num_supplies;
- //充电源的数量
- int num_supplies_online;
- struct animation *batt_anim;
- gr_surface surf_unknown;
- //电池信息
- struct power_supply *battery;
- bool state;//the state of screen
- };
2)main函数
- int main(int argc, char **argv)
- {
- int ret;
- struct charger *charger = &charger_state;
- int64_t now = curr_time_ms() - 1;
- int fd;
- int i;
- //初始化power_supply链表
- list_init(&charger->supplies);
- klog_init();
- klog_set_level(CHARGER_KLOG_LEVEL);
- //dump_last_kmsg();
- LOGI("--------------- STARTING CHARGER MODE ---------------\n");
- acquire_wake_lock(PARTIAL_WAKE_LOCK,"PowerManagerService");
- gr_init();
- gr_font_size(&char_width, &char_height);
- //遍历/dev/input目录下的设备,将EV_REL和EV_KEY设备的信息保存到ev_fds[]等结构体中
- ev_init(input_callback, charger);//参见下文3)
- //创建一个socket用于接收kernel的uevent
- fd = uevent_open_socket(64*1024, true);
- if (fd >= 0) {
- fcntl(fd, F_SETFL, O_NONBLOCK);
- ev_add_fd(fd, uevent_callback, charger);//参见下文6)
- }
- charger->uevent_fd = fd;
- coldboot(charger, "/sys/class/power_supply", "add");
- ret = res_create_surface("charger/battery_fail", &charger->surf_unknown);
- if (ret < 0) {
- LOGE("Cannot load image\n");
- charger->surf_unknown = NULL;
- }
- 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);
- //主循环函数
- event_loop(charger);
- return 0;
- }
3)ev_init, input_callback函数
- <pre name="code" class="cpp">//bootable/recovery/minui/events.c
- int ev_init(ev_callback input_cb, void *data)
- {
- DIR *dir;
- struct dirent *de;
- int fd;
- dir = opendir("/dev/input");
- if(dir != 0) {
- while((de = readdir(dir))) {
- unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
- // fprintf(stderr,"/dev/input/%s\n", de->d_name);
- if(strncmp(de->d_name,"event",5)) continue;
- fd = openat(dirfd(dir), de->d_name, O_RDONLY);
- if(fd < 0) continue;
- /* read the evbits of the input device */
- if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
- close(fd);
- continue;
- }
- /* TODO: add ability to specify event masks. For now, just assume
- * that only EV_KEY and EV_REL event types are ever needed. */
- if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
- close(fd);
- continue;
- }
- ev_fds[ev_count].fd = fd;
- ev_fds[ev_count].events = POLLIN;
- ev_fdinfo[ev_count].cb = input_cb;
- ev_fdinfo[ev_count].data = data;
- ev_count++;
- ev_dev_count++;
- if(ev_dev_count == MAX_DEVICES) break;
- }
- }
- return 0;
- }
- static int input_callback(int fd, short revents, void *data)
- {
- struct charger *charger = data;
- struct input_event ev;
- int ret;
- //读取input_event信息
- ret = ev_get_input(fd, revents, &ev);
- if (ret)
- return -1;
- update_input_state(charger, &ev);
- return 0;
- }
- static void update_input_state(struct charger *charger,
- struct input_event *ev)
- {
- if (ev->type != EV_KEY)
- return;
- //按键code,按键value
- set_key_callback(ev->code, ev->value, 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;
- }
4)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);//参见下文5)
- //处理充电事件
- handle_power_supply_state(charger, now);//参见下文7)
- /* do screen update last in case any of the above want to start
- * screen transitions (animations, etc)
- */
- update_screen_state(charger, now);
- wait_next_event(charger, now);
- }
- }
5)handle_input_state函数
- static void handle_input_state(struct charger *charger, int64_t now)
- {
- process_key(charger, KEY_POWER, now);
- if (charger->next_key_check != -1 && now > charger->next_key_check)
- charger->next_key_check = -1;
- }
- 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) {
- if (key->down) {
- int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;
- //重启系统
- if (now >= reboot_timeout) {
- 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);
- }
- } else {
- /* if the power key got released, force screen state cycle */
- if (key->pending) {
- request_suspend(false);
- if(charger->state)
- {
- charger->state = false;
- reset_animation(charger->batt_anim);
- set_screen_state(SUSPEND);
- //read_file(NEW_PATHS[0],lock_name,sizeof(lock_name));
- }
- else
- {
- charger->state = true;
- charger->next_pwr_check = -1;
- charger->next_screen_transition = -1;
- kick_animation(charger->batt_anim);
- set_screen_state(ON);
- }
- // kick_animation(charger->batt_anim);
- }
- }
- }
- key->pending = false;
- }
6)uevent_callback函数
- static int uevent_callback(int fd, short revents, void *data)
- {
- struct charger *charger = data;
- if (!(revents & POLLIN))
- return -1;
- //调用handle_uevent_fd
- return handle_uevent_fd(charger, fd);
- }
- static int handle_uevent_fd(struct charger *charger, int fd)
- {
- char msg[UEVENT_MSG_LEN+2];
- int n;
- if (fd < 0)
- return -1;
- while (true) {
- struct uevent uevent;
- n = uevent_kernel_multicast_recv(fd, msg, UEVENT_MSG_LEN);
- if (n <= 0)
- break;
- if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
- continue;
- msg[n] = '\0';
- msg[n+1] = '\0';
- //解析msg到uevent
- parse_uevent(msg, &uevent);
- //处理uevent,更新charger状态
- process_uevent(charger, &uevent);
- }
- return 0;
- }
- //解析消息到uevent
- static void parse_uevent(const char *msg, struct uevent *uevent)
- {
- /*************************************************************
- 消息示例
- msg-消息
- event-uevent
- power supply-charger信息
- msg=add@/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-bat
- event { 'add', '/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-bat', 'power_supply', 'rk-bat', '', '' }
- power supply rk-bat (Battery) (action=add num_online=0 num_supplies=1)
- msg=add@/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-ac
- event { 'add', '/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-ac', 'power_supply', 'rk-ac', '', '1' }
- power supply rk-ac (Mains) online (action=add num_online=1 num_supplies=2)
- msg=add@/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-usb
- event { 'add', '/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-usb', 'power_supply', 'rk-usb', '', '0' }
- power supply rk-usb (USB) offline (action=add num_online=1 num_supplies=3)
- *
- */
- //action = add / change /remove
- uevent->action = "";
- //path = /devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/
- uevent->path = "";
- //subsystem = power_supply
- uevent->subsystem = "";
- //ps_name = rk-ac / rk-battery /rk-usb
- uevent->ps_name = "";
- //ps_online = 0 / 1
- uevent->ps_online = "";
- //ps_type = ''
- uevent->ps_type = "";
- /* currently ignoring SEQNUM */
- while (*msg) {
- #ifdef DEBUG_UEVENTS
- LOGV("uevent str: %s\n", msg);
- #endif
- if (!strncmp(msg, "ACTION=", 7)) {
- msg += 7;
- uevent->action = msg;
- } else if (!strncmp(msg, "DEVPATH=", 8)) {
- msg += 8;
- uevent->path = msg;
- } else if (!strncmp(msg, "SUBSYSTEM=", 10)) {
- msg += 10;
- uevent->subsystem = msg;
- } else if (!strncmp(msg, "POWER_SUPPLY_NAME=", 18)) {
- msg += 18;
- uevent->ps_name = msg;
- } else if (!strncmp(msg, "POWER_SUPPLY_ONLINE=", 20)) {
- msg += 20;
- uevent->ps_online = msg;
- } else if (!strncmp(msg, "POWER_SUPPLY_TYPE=", 18)) {
- msg += 18;
- uevent->ps_type = msg;
- }
- /* advance to after the next \0 */
- while (*msg++)
- ;
- }
- //LOGV
- LOGI("event { '%s', '%s', '%s', '%s', '%s', '%s' }\n",
- uevent->action, uevent->path, uevent->subsystem,
- uevent->ps_name, uevent->ps_type, uevent->ps_online);
- }
- //处理uevent信息,更新charger的power_supply状态
- static void process_ps_uevent(struct charger *charger, struct uevent *uevent)
- {
- int online;
- char ps_type[32];
- struct power_supply *supply = NULL;
- int i;
- bool was_online = false;
- bool battery = false;
- bool usb = false;
- //如果ps_type为空,则重新从驱动路径中获取ps_type
- if (uevent->ps_type[0] == '\0') {
- char *path;
- int ret;
- if (uevent->path[0] == '\0')
- return;
- /*
- /sys/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-ac
- /sys/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-bat
- /sys/devices/platform/rk30_i2c.0/i2c-0/0-0062/power_supply/rk-usb
- */
- //生成路径
- ret = asprintf(&path, "/sys/%s/type", uevent->path);
- if (ret <= 0)
- return;
- /*
- type = Mains / Battery /USB
- */
- //读取type
- ret = read_file(path, ps_type, sizeof(ps_type));
- free(path);
- if (ret < 0)
- return;
- } else {
- strlcpy(ps_type, uevent->ps_type, sizeof(ps_type));
- }
- //type == Battery
- if (!strncmp(ps_type, "Battery", 7)){
- battery = true;
- }
- //读取uevent的online值
- online = atoi(uevent->ps_online);
- //从charger的list查找name为ps_name的power_supply
- supply = find_supply(charger, uevent->ps_name);
- if (supply) {//list包含该power_supply
- was_online = supply->online;
- //更新charger的online状态
- supply->online = online;
- }
- if (!strcmp(uevent->action, "add")) {
- //该supply不在list中
- if (!supply) {
- //新建supply,拷贝uevent的信息到supply,然后添加到charger的list
- //同时更新charger的num_supplies++
- supply = add_supply(charger, uevent->ps_name, ps_type, uevent->path,
- online);
- if (!supply) {
- LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name,
- uevent->ps_type, online);
- return;
- }
- /* only pick up the first battery for now */
- if (battery && !charger->battery)
- charger->battery = supply;
- //该supply已在list中
- } else {
- LOGE("supply '%s' already exists..\n", uevent->ps_name);
- }
- } else if (!strcmp(uevent->action, "remove")) {
- if (supply) {
- if (charger->battery == supply)
- charger->battery = NULL;
- //从list中移除该supply,并更新charger->num_supplies--
- remove_supply(charger, supply);
- supply = NULL;
- }
- //前面已更新了charger的online状态,此处不做任何动作
- } else if (!strcmp(uevent->action, "change")) {
- if (!supply) {
- LOGE("power supply '%s' not found ('%s' %d)\n",
- uevent->ps_name, ps_type, online);
- return;
- }
- } else {
- return;
- }
- /* allow battery to be managed in the supply list but make it not
- * contribute to online power supplies. */
- if (!battery) {
- //online : 1 -> 0
- if (was_online && !online)
- charger->num_supplies_online--;
- //online: 0 -> 1
- else if (supply && !was_online && online)
- charger->num_supplies_online++;
- }
- if(usb && !online){
- charger->num_supplies_online = 0;
- }
- LOGI("power supply %s (%s) %s (action=%s num_online=%d num_supplies=%d)\n",
- uevent->ps_name, ps_type, battery ? "" : online ? "online" : "offline",
- uevent->action, charger->num_supplies_online, charger->num_supplies);
- }
7)handle_power_supply_state函数
- static void handle_power_supply_state(struct charger *charger, int64_t now)
- {
- //充电源数量为0
- 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;
- }
- }