Android 4.2充电画面关键代码分析

系统进入充电模式时,显示 充电画面,充电画面的代码在/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函数

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














你可能感兴趣的:(C/C++,Android,Linux)