Android上电到现实充电画面,android 电池(二):android关机充电流程、充电画面显示(一)...

上一篇我们讲了锂电池的充放电的流程和电池的一些特性,这一节我们重点说一下android关机充电是怎么、充电画面显示是怎么实现的,这个在工作中也比较有用,我们开始做这一块的时候也走了不少的弯路。我记得我们做adnroid2.3的时候,关机状态和充电logo显示是在uboot中做的。应该是有两种做法,回头我再看下uboot中做画面显示那一块是怎么做的,这一节我们重点说系统中的充电logo显示。

一、android正常开机流程、关机充电流程

在写这篇文章之前我们先看两个流程:正常开机流程,关机充电系统启动流程

1、正常开机流程,按开机键。

可大致分成三部分

(1)、OS_level:UBOOT、kenrel、init这三步完成系统启动;

(2)、Android_level:这部分完成android部的初始化;

(3)、Home Screen:这部分就是我们看到的launcher部分。

a4c26d1e5885305701be709a3d33442f.png

2、关机充电系统启动流程

与前面相比,这个流程只走到init这一部分,就没有往后走了,这部分我们会在后面的代码中分析。

a4c26d1e5885305701be709a3d33442f.png

二、关机充电逻辑硬件逻辑

1、插入DC,charger IC从硬件上唤醒系统,相当于长按开机键开机。

a4c26d1e5885305701be709a3d33442f.png

下面这部分是charger IC连接系统的控制部分。

a4c26d1e5885305701be709a3d33442f.png

三、软件逻辑。

DC插入,其实相当于关机状态下“按开机键”开机。第一步要走UBOOT、kernel 、android

init这一流程。

1、UBOOT

UBOOT启动代码我们不在这里详细分析,这里我们只要注意二个问题:

a:如何判断是DC插入;

b:设定setenv("bootargs", "androidboot.mode=charger"),androidboot.mode这个参数相当重要,这个参数决定系统是正常启动、还是关机充电状态。

Uboot/board/samsung/smdk4212/smkd4212.c

intboard_late_init (void)

{

intkeystate = 0;

printf("check start mode\n");

if((*(int*)0x10020800==0x19721212) || (*(int*)0x10020804==0x19721212)

|| (*(int*)0x10020808==0x19721212))//(1)、检查是否有DC插入;

{

setenv ("bootargs","");//(2)、没有DC插入;

} else{//DC插入

inttmp=*(int*)0x11000c08;

*(int*)0x10020800=*(int*)0x10020804=0x19721212;

*(int*)0x11000c08=(tmp&(~0xc000))|0xc000;

udelay(10000);

if((*(int*)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {

setenv ("bootargs","androidboot.mode=charger");//(3)、设定bootargs为charger状态

printf("charger mode\n");

} else{

setenv ("bootargs","");

}

*(int*)0x11000c08=tmp;

}

#ifdef CONFIG_CPU_EXYNOS4X12

intcharge_status=CheckBatteryLow();//(4)、检查电池电量;

keystate=board_key_check();//(5)、检查按键状态;

// fuse bootloader

if(second_boot_info != 0) {

boot_symbol=1;

INF_REG2_REG =0x8;

run_command(CONFIG_BOOTCMD_FUSE_BOOTLOADER, NULL);

}

if((INF_REG4_REG == 0xd)) {

// reboot default

charbuf[10];

sprintf(buf, "%d", CONFIG_BOOTDELAY);

setenv ("bootdelay", buf);

setenv ("reserved", NULL);

saveenv();

} elseif((INF_REG4_REG == 0xe) || keystate == (0x1 | 0x2)) {//(6)、按键进入fastboot模式;

// reboot bootloader

boot_symbol=1;

INF_REG2_REG =0x8;

printf("BOOTLOADER - FASTBOOT\n");

setenv ("reserved","fastboot");

setenv ("bootdelay","0");

} elseif((INF_REG4_REG == 0xf) || keystate == (0x1 | 0x2 | 0x4)) {//(7)、按键进入recovery模式;

// reboot recovery

printf("BOOTLOADER - RECOVERY\n");

boot_symbol=1;

INF_REG2_REG =0x8;

setenv ("reserved", CONFIG_BOOTCMD_RECOVERY);

setenv ("bootdelay","0");

} else

if(keystate == (0x1 | 0x4) || second_boot_info != 0 || partition_check()) {//(8)、按键进入卡升级模式;

// 2nd boot

printf("BOOTLOADER - 2ND BOOT DEVICE\n");

boot_symbol=1;

INF_REG2_REG =0x8;

setenv ("bootcmd", CONFIG_BOOTCOMMAND);

setenv ("reserved", CONFIG_BOOTCMD_FUSE_RELEASE);

setenv ("bootdelay","0");

} else{//(9)、正常启动;

// normal case

charbuf[10];

sprintf(buf, "%d", CONFIG_BOOTDELAY);

setenv ("bootdelay", buf);

}

INF_REG4_REG = 0;

return0;

}

(1)、检查是否有DC插入;

if((*(int*)0x10020800==0x19721212) || (*(int*)0x10020804==0x19721212)

(*(int*)0x10020808==0x19721212))

这部分检查寄存器的值。

(2)、没有DC插入;

(3)、设定bootargs为charger状态

if((*(int*)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {

setenv ("bootargs","androidboot.mode=charger");

这是这部分的重点,如果能过寄存器判断是DC插入,把androidboot.mode设定为charger状态。

以下这部分根据需要加入,通过判断不同的情况进入不同的功能,如fastboot\revovery…………,这部分不做详细解释。

(4)、检查电池电量;

这个在正常开机状态下,如果检测电量太低,则不开机,这部分代码就不做分析。

(5)、检查按键状态;

我们这个平台有几种模式:fastboot\recovery\卡升级等……

(6)、按键进入fastboot模式;

(7)、按键进入recovery模式;

(8)、按键进入卡升级模式

(9)、正常启动;

2、kernel

这部分和正常启动是一样的。

3、init

前面所有的描述其实只有一点和正常启动不太一样,那就是在UBOOT中把androidboot.mode设定为charger状态,内核正常流程启动,然后到init时要对charger这种状态处理。

system\core\init\init.c

intmain(intargc,char**argv)

{

………………

action_for_each_trigger("early-init", action_add_queue_tail);

queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");

queue_builtin_action(property_init_action, "property_init");

queue_builtin_action(keychord_init_action, "keychord_init");

queue_builtin_action(console_init_action, "console_init");//(1)、显示initlogo.rle,也就是android第二张图片;

queue_builtin_action(set_init_properties_action, "set_init_properties");

action_for_each_trigger("init", action_add_queue_tail);

if(strcmp(bootmode,"charger") != 0) {//(2)、这里就是UBOOT中设定的bootmode,如果是charger模式,跳过下面初始化;

action_for_each_trigger("early-fs", action_add_queue_tail);

action_for_each_trigger("fs", action_add_queue_tail);

action_for_each_trigger("post-fs", action_add_queue_tail);

action_for_each_trigger("post-fs-data", action_add_queue_tail);

}

queue_builtin_action(property_service_init_action, "property_service_init");

queue_builtin_action(signal_init_action, "signal_init");

queue_builtin_action(check_startup_action, "check_startup");

if(!strcmp(bootmode,"charger")) {//(3)、如果为charger,则调用charger.c。

action_for_each_trigger("charger", action_add_queue_tail);

} else{

action_for_each_trigger("early-boot", action_add_queue_tail);

action_for_each_trigger("boot", action_add_queue_tail);

}

……………………

}

(1)、显示initlogo.rle,也就是android第二张图片;

queue_builtin_action(console_init_action,"console_init");调用console_init_action

staticintconsole_init_action(intnargs,char**args)

{

intfd;

chartmp[PROP_VALUE_MAX];

if(console[0]) {

snprintf(tmp, sizeof(tmp),"/dev/%s", console);

console_name = strdup(tmp);

}

fd = open(console_name, O_RDWR);

if(fd >= 0)

have_console = 1;

close(fd);

if( load_565rle_image(INIT_IMAGE_FILE) ) {//这里定义rle文件的名称#define INIT_IMAGE_FILE "/initlogo.rle"

fd = open("/dev/tty0", O_WRONLY);

if(fd >= 0) {//如果没有这张图片,就显示android字样,在屏幕左上角;

constchar*msg;

msg = "\n"

"\n"

"\n"// console is 40 cols x 30 lines

"\n"

"\n"

"\n"

"\n"

"\n"

"\n"

"\n"

" A N D R O I D ";

write(fd, msg, strlen(msg));

close(fd);

}

}

return0;

}

(2)、这里就是UBOOT中设定的bootmode,如果是charger模式,跳过下面初始化;

if(strcmp(bootmode,"charger") != 0) {

action_for_each_trigger("early-fs", action_add_queue_tail);

action_for_each_trigger("fs", action_add_queue_tail);

action_for_each_trigger("post-fs", action_add_queue_tail);

action_for_each_trigger("post-fs-data", action_add_queue_tail);

}

(3)、如果为charger,则调用charger.c

action_for_each_trigger("charger", action_add_queue_tail);

我们在后面细分charger这部分。

4、charger.c

这部分就是我们充电部分,充电画面显示的实现。

system\core\charger\charger.c

intmain(intargc,char**argv)

{

………………

klog_set_level(CHARGER_KLOG_LEVEL);

dump_last_kmsg();

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

gr_init();

gr_font_size(&char_width, &char_height); //(1)、初始化graphics,包括buf大小;

ev_init(input_callback, charger);//(2)初始化按键;

fd = uevent_open_socket(64*1024, true);

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");//(3)、创建/sys/class/power_supply结点,把socket信息通知应用层;

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

if(ret 

LOGE("Cannot load image\n");

charger->surf_unknown = NULL;

}

for(i = 0; i batt_anim->num_frames; i++) {//(4)、这里是显示charger logo,res_create_surface显示图片函数;

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

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

if(ret 

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

charger->batt_anim->num_frames = 0;

charger->batt_anim->num_cycles = 1;

break;

}

}

ev_sync_key_state(set_key_callback, charger);

gr_fb_blank(true);

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);//(5)、event_loop循环,电池状态,检测按键是否按下;

return0;

}

(1)、初始化graphics,包括buf大小

android/bootable/recovery/minui/graphics.c

gr_init():minui/graphics.c[settty0 to graphic mode, open

fb0],设制tty0为图形模式,打开fb0;

intgr_init(void)

{

gglInit(&gr_context);

GGLContext *gl = gr_context;

gr_init_font();

gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);

if(gr_vt_fd 

// This is non-fatal; post-Cupcake kernels don't have tty0.

perror("can't open /dev/tty0");

} elseif(ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {

// However, if we do open tty0, we expect the ioctl to work.

perror("failed KDSETMODE to KD_GRAPHICS on tty0");

gr_exit();

return-1;

}

gr_fb_fd = get_framebuffer(gr_framebuffer);

if(gr_fb_fd 

gr_exit();

return-1;

}

get_memory_surface(&gr_mem_surface);

fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",

gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);

gr_active_fb = 0;

set_active_framebuffer(0);

gl->colorBuffer(gl, &gr_mem_surface);

gl->activeTexture(gl, 0);

gl->enable(gl, GGL_BLEND);

gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);

gr_fb_blank(true);

gr_fb_blank(false);

return0;

}

(2)android/bootable/recovery/minui/events.c

ev_init():minui/events.c[open /dev/input/event*]打开

/dev/input/event*

这部分是在,充电状态下,按键操作的初始化,比如:短按显示充电logo,长按开机,初始化代码如下。

intev_init(ev_callback input_cb,void*data)

{

DIR *dir;

structdirent *de;

intfd;

dir = opendir("/dev/input");//打开驱动结点;

if(dir != 0) {

while((de = readdir(dir))) {

unsigned longev_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 

if(ioctl(fd, EVIOCGBIT(0,sizeof(ev_bits)), ev_bits) 

close(fd);

continue;

}

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;

}

}

return0;

}

(3)、创建/sys/class/power_supply结点,把socket信息通知应用层

uevent_open_socket这个函数是通过kobject_uevent的方式通知的应用层,就是往一个socket广播一个消息,只需要在应用层打开socket监听NETLINK_KOBJECT_UEVENT组的消息,就可以收到了,主要是创建了socket接口获得uevent的文件描述符,然后触发/sys/class/power_supply目录及其子目录下的uevent,然后接受并创建设备节点,至此设备节点才算创建。

(4)、这里显示charger logo,res_create_surface显示图片函数;

res_create_surface:minui/resource.c[create surfaces for all bitmaps

used later, include icons, bmps]

创建surface为所以的位图,包括图标、位图。 这些图片的位置为:system\core\charger\images

a4c26d1e5885305701be709a3d33442f.png

(5)、event_loop循环,电池状态,检测按键是否按下;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值