当前位置:   article > 正文

Android关机充电流程_安卓充电阶段uboot

安卓充电阶段uboot
平台信息:
内核:linux2.6/linux3.0
系统:android/android4.0 

平台:S5PV310(samsungexynos 4210)


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

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

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

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

可大致分成三部分

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

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

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


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

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


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

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


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


三、软件逻辑。

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

1、UBOOT

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

a:如何判断是DC插入;

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

Uboot/board/samsung/smdk4212/smkd4212.c

  1. int board_late_init (void)  
  2. {  
  3.     int keystate = 0;  
  4.     printf("check start mode\n");  
  5.   if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212)  
  6. || (*(int *)0x10020808==0x19721212)) //(1)、检查是否有DC插入;  
  7. {  
  8.     setenv ("bootargs""");//(2)、没有DC插入;  
  9.   } else  {//DC插入  
  10.         int tmp=*(int *)0x11000c08;  
  11.     *(int *)0x10020800=*(int *)0x10020804=0x19721212;  
  12.     *(int *)0x11000c08=(tmp&(~0xc000))|0xc000;  
  13.     udelay(10000);  
  14.     if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {  
  15.         setenv ("bootargs""androidboot.mode=charger");//(3)、设定bootargs为charger状态  
  16.         printf("charger mode\n");  
  17.     } else {  
  18.         setenv ("bootargs""");  
  19.     }  
  20.     *(int *)0x11000c08=tmp;  
  21.   }  
  22. #ifdef CONFIG_CPU_EXYNOS4X12  
  23.     int charge_status=CheckBatteryLow();//(4)、检查电池电量;  
  24.     keystate=board_key_check();//(5)、检查按键状态;  
  25.     // fuse bootloader  
  26.     if(second_boot_info != 0) {  
  27.         boot_symbol=1;  
  28.         INF_REG2_REG =0x8;  
  29.         run_command(CONFIG_BOOTCMD_FUSE_BOOTLOADER, NULL);  
  30.     }  
  31.     if((INF_REG4_REG == 0xd)) {  
  32.         // reboot default  
  33.         char buf[10];  
  34.         sprintf(buf, "%d", CONFIG_BOOTDELAY);  
  35.         setenv ("bootdelay", buf);  
  36.         setenv ("reserved", NULL);  
  37.         saveenv();  
  38.     } else if((INF_REG4_REG == 0xe) || keystate == (0x1 | 0x2)) {//(6)、按键进入fastboot模式;  
  39.         // reboot bootloader  
  40.         boot_symbol=1;  
  41.         INF_REG2_REG =0x8;  
  42.         printf("BOOTLOADER - FASTBOOT\n");  
  43.         setenv ("reserved""fastboot");  
  44.         setenv ("bootdelay""0");  
  45.     } else if((INF_REG4_REG == 0xf) || keystate == (0x1 | 0x2 | 0x4)) {//(7)、按键进入recovery模式;  
  46.         // reboot recovery  
  47.         printf("BOOTLOADER - RECOVERY\n");  
  48.         boot_symbol=1;  
  49.         INF_REG2_REG =0x8;  
  50.         setenv ("reserved", CONFIG_BOOTCMD_RECOVERY);  
  51.         setenv ("bootdelay""0");  
  52.     } else  
  53.     if(keystate == (0x1 | 0x4) || second_boot_info != 0 || partition_check()) {//(8)、按键进入卡升级模式;  
  54.         // 2nd boot  
  55.         printf("BOOTLOADER - 2ND BOOT DEVICE\n");  
  56.         boot_symbol=1;  
  57.         INF_REG2_REG =0x8;  
  58.         setenv ("bootcmd", CONFIG_BOOTCOMMAND);  
  59.         setenv ("reserved", CONFIG_BOOTCMD_FUSE_RELEASE);  
  60.         setenv ("bootdelay""0");  
  61.     } else {//(9)、正常启动;  
  62.         // normal case  
  63.         char buf[10];  
  64.         sprintf(buf, "%d", CONFIG_BOOTDELAY);  
  65.         setenv ("bootdelay", buf);  
  66.     }  
  67.     INF_REG4_REG = 0;  
  68.     return 0;  
  69. }  
  1. int board_late_init (void)
  2. {
  3. int keystate = 0;
  4. printf("check start mode\n");
  5. if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212)
  6. || (*(int *)0x10020808==0x19721212)) //(1)、检查是否有DC插入;
  7. {
  8. setenv ("bootargs", "");//(2)、没有DC插入;
  9. } else {//DC插入
  10. int tmp=*(int *)0x11000c08;
  11. *(int *)0x10020800=*(int *)0x10020804=0x19721212;
  12. *(int *)0x11000c08=(tmp&(~0xc000))|0xc000;
  13. udelay(10000);
  14. if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {
  15. setenv ("bootargs", "androidboot.mode=charger");//(3)、设定bootargs为charger状态
  16. printf("charger mode\n");
  17. } else {
  18. setenv ("bootargs", "");
  19. }
  20. *(int *)0x11000c08=tmp;
  21. }
  22. #ifdef CONFIG_CPU_EXYNOS4X12
  23. int charge_status=CheckBatteryLow();//(4)、检查电池电量;
  24. keystate=board_key_check();//(5)、检查按键状态;
  25. // fuse bootloader
  26. if(second_boot_info != 0) {
  27. boot_symbol=1;
  28. INF_REG2_REG =0x8;
  29. run_command(CONFIG_BOOTCMD_FUSE_BOOTLOADER, NULL);
  30. }
  31. if((INF_REG4_REG == 0xd)) {
  32. // reboot default
  33. char buf[10];
  34. sprintf(buf, "%d", CONFIG_BOOTDELAY);
  35. setenv ("bootdelay", buf);
  36. setenv ("reserved", NULL);
  37. saveenv();
  38. } else if((INF_REG4_REG == 0xe) || keystate == (0x1 | 0x2)) {//(6)、按键进入fastboot模式;
  39. // reboot bootloader
  40. boot_symbol=1;
  41. INF_REG2_REG =0x8;
  42. printf("BOOTLOADER - FASTBOOT\n");
  43. setenv ("reserved", "fastboot");
  44. setenv ("bootdelay", "0");
  45. } else if((INF_REG4_REG == 0xf) || keystate == (0x1 | 0x2 | 0x4)) {//(7)、按键进入recovery模式;
  46. // reboot recovery
  47. printf("BOOTLOADER - RECOVERY\n");
  48. boot_symbol=1;
  49. INF_REG2_REG =0x8;
  50. setenv ("reserved", CONFIG_BOOTCMD_RECOVERY);
  51. setenv ("bootdelay", "0");
  52. } else
  53. if(keystate == (0x1 | 0x4) || second_boot_info != 0 || partition_check()) {//(8)、按键进入卡升级模式;
  54. // 2nd boot
  55. printf("BOOTLOADER - 2ND BOOT DEVICE\n");
  56. boot_symbol=1;
  57. INF_REG2_REG =0x8;
  58. setenv ("bootcmd", CONFIG_BOOTCOMMAND);
  59. setenv ("reserved", CONFIG_BOOTCMD_FUSE_RELEASE);
  60. setenv ("bootdelay", "0");
  61. } else {//(9)、正常启动;
  62. // normal case
  63. char buf[10];
  64. sprintf(buf, "%d", CONFIG_BOOTDELAY);
  65. setenv ("bootdelay", buf);
  66. }
  67. INF_REG4_REG = 0;
  68. return 0;
  69. }

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

  1. if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212)  
  2.  (*(int *)0x10020808==0x19721212))   
  1. if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212)
  2. || (*(int *)0x10020808==0x19721212))

这部分检查寄存器的值。

(2)、没有DC插入;

(3)、设定bootargs为charger状态

  1. if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {  
  2.         setenv ("bootargs""androidboot.mode=charger");  
  1. if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) {
  2. 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

  1. int main(int argc, char **argv)  
  2. {  
  3.     ………………  
  4.     action_for_each_trigger("early-init", action_add_queue_tail);  
  5.   
  6.     queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");  
  7.     queue_builtin_action(property_init_action, "property_init");  
  8.     queue_builtin_action(keychord_init_action, "keychord_init");  
  9.     queue_builtin_action(console_init_action, "console_init");  //(1)、显示initlogo.rle,也就是android第二张图片;  
  10.     queue_builtin_action(set_init_properties_action, "set_init_properties");  
  11.   
  12.     /* execute all the boot actions to get us started */  
  13.     action_for_each_trigger("init", action_add_queue_tail);  
  14.   
  15.     /* skip mounting filesystems in charger mode */  
  16.     if (strcmp(bootmode, "charger") != 0) {//(2)、这里就是UBOOT中设定的bootmode,如果是charger模式,跳过下面初始化;  
  17.         action_for_each_trigger("early-fs", action_add_queue_tail);  
  18.         action_for_each_trigger("fs", action_add_queue_tail);  
  19.         action_for_each_trigger("post-fs", action_add_queue_tail);  
  20.         action_for_each_trigger("post-fs-data", action_add_queue_tail);  
  21.     }  
  22.   
  23.     queue_builtin_action(property_service_init_action, "property_service_init");  
  24.     queue_builtin_action(signal_init_action, "signal_init");  
  25.     queue_builtin_action(check_startup_action, "check_startup");  
  26.   
  27.     if (!strcmp(bootmode, "charger")) {//(3)、如果为charger,则调用charger.c。  
  28.         action_for_each_trigger("charger", action_add_queue_tail);  
  29.     } else {  
  30.         action_for_each_trigger("early-boot", action_add_queue_tail);  
  31.         action_for_each_trigger("boot", action_add_queue_tail);  
  32.     }  
  33. ……………………  
  34. }  
  1. int main(int argc, char **argv)
  2. {
  3. ………………
  4. action_for_each_trigger("early-init", action_add_queue_tail);
  5. queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
  6. queue_builtin_action(property_init_action, "property_init");
  7. queue_builtin_action(keychord_init_action, "keychord_init");
  8. queue_builtin_action(console_init_action, "console_init"); //(1)、显示initlogo.rle,也就是android第二张图片;
  9. queue_builtin_action(set_init_properties_action, "set_init_properties");
  10. /* execute all the boot actions to get us started */
  11. action_for_each_trigger("init", action_add_queue_tail);
  12. /* skip mounting filesystems in charger mode */
  13. if (strcmp(bootmode, "charger") != 0) {//(2)、这里就是UBOOT中设定的bootmode,如果是charger模式,跳过下面初始化;
  14. action_for_each_trigger("early-fs", action_add_queue_tail);
  15. action_for_each_trigger("fs", action_add_queue_tail);
  16. action_for_each_trigger("post-fs", action_add_queue_tail);
  17. action_for_each_trigger("post-fs-data", action_add_queue_tail);
  18. }
  19. queue_builtin_action(property_service_init_action, "property_service_init");
  20. queue_builtin_action(signal_init_action, "signal_init");
  21. queue_builtin_action(check_startup_action, "check_startup");
  22. if (!strcmp(bootmode, "charger")) {//(3)、如果为charger,则调用charger.c。
  23. action_for_each_trigger("charger", action_add_queue_tail);
  24. } else {
  25. action_for_each_trigger("early-boot", action_add_queue_tail);
  26. action_for_each_trigger("boot", action_add_queue_tail);
  27. }
  28. ……………………
  29. }

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

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

  1. static int console_init_action(int nargs, char **args)  
  2. {  
  3.     int fd;  
  4.     char tmp[PROP_VALUE_MAX];  
  5.     if (console[0]) {  
  6.         snprintf(tmp, sizeof(tmp), "/dev/%s", console);  
  7.         console_name = strdup(tmp);  
  8.     }  
  9.     fd = open(console_name, O_RDWR);  
  10.     if (fd >= 0)  
  11.         have_console = 1;  
  12.     close(fd);  
  13.     if( load_565rle_image(INIT_IMAGE_FILE) ) {//这里定义rle文件的名称#define INIT_IMAGE_FILE "/initlogo.rle"  
  14.         fd = open("/dev/tty0", O_WRONLY);  
  15.         if (fd >= 0) {//如果没有这张图片,就显示android字样,在屏幕左上角;  
  16.             const char *msg;  
  17.                 msg = "\n"  
  18.             "\n"  
  19.             "\n"  // console is 40 cols x 30 lines  
  20.             "\n"  
  21.             "\n"  
  22.             "\n"  
  23.             "\n"  
  24.             "\n"  
  25.             "\n"  
  26.             "\n"  
  27.             "             A N D R O I D ";  
  28.             write(fd, msg, strlen(msg));  
  29.             close(fd);  
  30.         }  
  31.     }  
  32.     return 0;  
  33. }  
  1. static int console_init_action(int nargs, char **args)
  2. {
  3. int fd;
  4. char tmp[PROP_VALUE_MAX];
  5. if (console[0]) {
  6. snprintf(tmp, sizeof(tmp), "/dev/%s", console);
  7. console_name = strdup(tmp);
  8. }
  9. fd = open(console_name, O_RDWR);
  10. if (fd >= 0)
  11. have_console = 1;
  12. close(fd);
  13. if( load_565rle_image(INIT_IMAGE_FILE) ) {//这里定义rle文件的名称#define INIT_IMAGE_FILE "/initlogo.rle"
  14. fd = open("/dev/tty0", O_WRONLY);
  15. if (fd >= 0) {//如果没有这张图片,就显示android字样,在屏幕左上角;
  16. const char *msg;
  17. msg = "\n"
  18. "\n"
  19. "\n" // console is 40 cols x 30 lines
  20. "\n"
  21. "\n"
  22. "\n"
  23. "\n"
  24. "\n"
  25. "\n"
  26. "\n"
  27. " A N D R O I D ";
  28. write(fd, msg, strlen(msg));
  29. close(fd);
  30. }
  31. }
  32. return 0;
  33. }

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

  1. /* skip mounting filesystems in charger mode */  
  2. if (strcmp(bootmode, "charger") != 0) {  
  3.     action_for_each_trigger("early-fs", action_add_queue_tail);  
  4.     action_for_each_trigger("fs", action_add_queue_tail);  
  5.     action_for_each_trigger("post-fs", action_add_queue_tail);  
  6.     action_for_each_trigger("post-fs-data", action_add_queue_tail);  
  7. }  
  1. /* skip mounting filesystems in charger mode */
  2. if (strcmp(bootmode, "charger") != 0) {
  3. action_for_each_trigger("early-fs", action_add_queue_tail);
  4. action_for_each_trigger("fs", action_add_queue_tail);
  5. action_for_each_trigger("post-fs", action_add_queue_tail);
  6. action_for_each_trigger("post-fs-data", action_add_queue_tail);
  7. }

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

  1. action_for_each_trigger("charger", action_add_queue_tail);  
action_for_each_trigger("charger", action_add_queue_tail);

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

4、charger.c

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

system\core\charger\charger.c

  1. int main(int argc, char **argv)  
  2. {  
  3. ………………  
  4.     klog_set_level(CHARGER_KLOG_LEVEL);  
  5.     dump_last_kmsg();  
  6.     LOGI("--------------- STARTING CHARGER MODE ---------------\n");  
  7.   
  8.     gr_init();  
  9.     gr_font_size(&char_width, &char_height); //(1)、初始化graphics,包括buf大小;  
  10.   
  11.     ev_init(input_callback, charger);//(2)初始化按键;  
  12.      
  13. fd = uevent_open_socket(64*1024, true);  
  14.     if (fd >= 0) {  
  15.         fcntl(fd, F_SETFL, O_NONBLOCK);  
  16.         ev_add_fd(fd, uevent_callback, charger);  
  17.     }  
  18.   
  19.     charger->uevent_fd = fd;  
  20.     coldboot(charger, "/sys/class/power_supply""add");//(3)、创建/sys/class/power_supply结点,把socket信息通知应用层;  
  21.       
  22. ret = res_create_surface("charger/battery_fail", &charger->surf_unknown);  
  23.     if (ret < 0) {  
  24.         LOGE("Cannot load image\n");  
  25.         charger->surf_unknown = NULL;  
  26.     }  
  27.     for (i = 0; i < charger->batt_anim->num_frames; i++) {//(4)、这里是显示charger logo,res_create_surface显示图片函数;  
  28.         struct frame *frame = &charger->batt_anim->frames[i];  
  29.         ret = res_create_surface(frame->name, &frame->surface);  
  30.         if (ret < 0) {  
  31.             LOGE("Cannot load image %s\n", frame->name);  
  32.             /* TODO: free the already allocated surfaces... */  
  33.             charger->batt_anim->num_frames = 0;  
  34.             charger->batt_anim->num_cycles = 1;  
  35.             break;  
  36.         }  
  37.     }  
  38. ev_sync_key_state(set_key_callback, charger);  
  39.     gr_fb_blank(true);  
  40.   
  41.     charger->next_screen_transition = now - 1;  
  42.     charger->next_key_check = -1;  
  43.     charger->next_pwr_check = -1;  
  44.     reset_animation(charger->batt_anim);  
  45.     kick_animation(charger->batt_anim);  
  46.     event_loop(charger);//(5)、event_loop循环,电池状态,检测按键是否按下;  
  47.     return 0;  
  48.   
  49. }  
  1. int main(int argc, char **argv)
  2. {
  3. ………………
  4. klog_set_level(CHARGER_KLOG_LEVEL);
  5. dump_last_kmsg();
  6. LOGI("--------------- STARTING CHARGER MODE ---------------\n");
  7. gr_init();
  8. gr_font_size(&char_width, &char_height); //(1)、初始化graphics,包括buf大小;
  9. ev_init(input_callback, charger);//(2)初始化按键;
  10. fd = uevent_open_socket(64*1024, true);
  11. if (fd >= 0) {
  12. fcntl(fd, F_SETFL, O_NONBLOCK);
  13. ev_add_fd(fd, uevent_callback, charger);
  14. }
  15. charger->uevent_fd = fd;
  16. coldboot(charger, "/sys/class/power_supply", "add");//(3)、创建/sys/class/power_supply结点,把socket信息通知应用层;
  17. ret = res_create_surface("charger/battery_fail", &charger->surf_unknown);
  18. if (ret < 0) {
  19. LOGE("Cannot load image\n");
  20. charger->surf_unknown = NULL;
  21. }
  22. for (i = 0; i < charger->batt_anim->num_frames; i++) {//(4)、这里是显示charger logo,res_create_surface显示图片函数;
  23. struct frame *frame = &charger->batt_anim->frames[i];
  24. ret = res_create_surface(frame->name, &frame->surface);
  25. if (ret < 0) {
  26. LOGE("Cannot load image %s\n", frame->name);
  27. /* TODO: free the already allocated surfaces... */
  28. charger->batt_anim->num_frames = 0;
  29. charger->batt_anim->num_cycles = 1;
  30. break;
  31. }
  32. }
  33. ev_sync_key_state(set_key_callback, charger);
  34. gr_fb_blank(true);
  35. charger->next_screen_transition = now - 1;
  36. charger->next_key_check = -1;
  37. charger->next_pwr_check = -1;
  38. reset_animation(charger->batt_anim);
  39. kick_animation(charger->batt_anim);
  40. event_loop(charger);//(5)、event_loop循环,电池状态,检测按键是否按下;
  41. return 0;
  42. }

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

android/bootable/recovery/minui/graphics.c

gr_init():minui/graphics.c[settty0 to graphic mode, open fb0],设制tty0为图形模式,打开fb0;

  1. int gr_init(void)  
  2. {  
  3.     gglInit(&gr_context);  
  4.     GGLContext *gl = gr_context;  
  5.     gr_init_font();  
  6.     gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);  
  7.     if (gr_vt_fd < 0) {  
  8.         // This is non-fatal; post-Cupcake kernels don't have tty0.  
  9.         perror("can't open /dev/tty0");  
  10.   
  11.     } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {  
  12.         // However, if we do open tty0, we expect the ioctl to work.  
  13.         perror("failed KDSETMODE to KD_GRAPHICS on tty0");  
  14.         gr_exit();  
  15.         return -1;  
  16.     }  
  17.     gr_fb_fd = get_framebuffer(gr_framebuffer);  
  18.     if (gr_fb_fd < 0) {  
  19.         gr_exit();  
  20.         return -1;  
  21.     }  
  22.     get_memory_surface(&gr_mem_surface);  
  23.     fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",  
  24.             gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);  
  25.         /* start with 0 as front (displayed) and 1 as back (drawing) */  
  26.     gr_active_fb = 0;  
  27.     set_active_framebuffer(0);  
  28.     gl->colorBuffer(gl, &gr_mem_surface);  
  29.     gl->activeTexture(gl, 0);  
  30.     gl->enable(gl, GGL_BLEND);  
  31.     gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);  
  32.     gr_fb_blank(true);  
  33.     gr_fb_blank(false);  
  34.     return 0;  
  35.   
  36. }  
  1. int gr_init(void)
  2. {
  3. gglInit(&gr_context);
  4. GGLContext *gl = gr_context;
  5. gr_init_font();
  6. gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);
  7. if (gr_vt_fd < 0) {
  8. // This is non-fatal; post-Cupcake kernels don't have tty0.
  9. perror("can't open /dev/tty0");
  10. } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {
  11. // However, if we do open tty0, we expect the ioctl to work.
  12. perror("failed KDSETMODE to KD_GRAPHICS on tty0");
  13. gr_exit();
  14. return -1;
  15. }
  16. gr_fb_fd = get_framebuffer(gr_framebuffer);
  17. if (gr_fb_fd < 0) {
  18. gr_exit();
  19. return -1;
  20. }
  21. get_memory_surface(&gr_mem_surface);
  22. fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",
  23. gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);
  24. /* start with 0 as front (displayed) and 1 as back (drawing) */
  25. gr_active_fb = 0;
  26. set_active_framebuffer(0);
  27. gl->colorBuffer(gl, &gr_mem_surface);
  28. gl->activeTexture(gl, 0);
  29. gl->enable(gl, GGL_BLEND);
  30. gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);
  31. gr_fb_blank(true);
  32. gr_fb_blank(false);
  33. return 0;
  34. }

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

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

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

  1. int ev_init(ev_callback input_cb, void *data)  
  2. {  
  3.     DIR *dir;  
  4.     struct dirent *de;  
  5.     int fd;  
  6.     dir = opendir("/dev/input");//打开驱动结点;  
  7.     if(dir != 0) {  
  8.         while((de = readdir(dir))) {  
  9.             unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];  
  10. //            fprintf(stderr,"/dev/input/%s\n", de->d_name);  
  11.             if(strncmp(de->d_name,"event",5)) continue;  
  12.             fd = openat(dirfd(dir), de->d_name, O_RDONLY);  
  13.             if(fd < 0) continue;  
  14.             /* read the evbits of the input device */  
  15.             if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {  
  16.                 close(fd);  
  17.                 continue;  
  18.             }  
  19.             /* TODO: add ability to specify event masks. For now, just assume 
  20.              * that only EV_KEY and EV_REL event types are ever needed. */  
  21.             if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {  
  22.                 close(fd);  
  23.                 continue;  
  24.             }  
  25.             ev_fds[ev_count].fd = fd;  
  26.             ev_fds[ev_count].events = POLLIN;  
  27.             ev_fdinfo[ev_count].cb = input_cb;  
  28.             ev_fdinfo[ev_count].data = data;  
  29.             ev_count++;  
  30.             ev_dev_count++;  
  31.             if(ev_dev_count == MAX_DEVICES) break;  
  32.         }  
  33.     }  
  34.     return 0;  
  35. }  
  1. int ev_init(ev_callback input_cb, void *data)
  2. {
  3. DIR *dir;
  4. struct dirent *de;
  5. int fd;
  6. dir = opendir("/dev/input");//打开驱动结点;
  7. if(dir != 0) {
  8. while((de = readdir(dir))) {
  9. unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
  10. // fprintf(stderr,"/dev/input/%s\n", de->d_name);
  11. if(strncmp(de->d_name,"event",5)) continue;
  12. fd = openat(dirfd(dir), de->d_name, O_RDONLY);
  13. if(fd < 0) continue;
  14. /* read the evbits of the input device */
  15. if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
  16. close(fd);
  17. continue;
  18. }
  19. /* TODO: add ability to specify event masks. For now, just assume
  20. * that only EV_KEY and EV_REL event types are ever needed. */
  21. if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
  22. close(fd);
  23. continue;
  24. }
  25. ev_fds[ev_count].fd = fd;
  26. ev_fds[ev_count].events = POLLIN;
  27. ev_fdinfo[ev_count].cb = input_cb;
  28. ev_fdinfo[ev_count].data = data;
  29. ev_count++;
  30. ev_dev_count++;
  31. if(ev_dev_count == MAX_DEVICES) break;
  32. }
  33. }
  34. return 0;
  35. }

(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

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

5、event_loop

       这个函数判断按键状态,DC是否插拔。如果长按开机:执行android_reboot(ANDROID_RB_RESTART,0, 0);如果拔出DC:执行android_reboot(ANDROID_RB_POWEROFF,0, 0);

  1. static void event_loop(struct charger *charger)  
  2. {  
  3.     int ret;  
  4.     while (true) {  
  5.         int64_t now = curr_time_ms();//(1)、获得当前时间;  
  6.         LOGV("[%lld] event_loop()\n", now);  
  7.         handle_input_state(charger, now);//(2)、检查按键状态;  
  8.         handle_power_supply_state(charger, now);// (3)、检查DC是否拔出;   
  9.         /* do screen update last in case any of the above want to start 
  10.          * screen transitions (animations, etc) 
  11.          */  
  12.         update_screen_state(charger, now);//(4)、对按键时间状态标志位的判断,显示不同电量的充电logo;   
  13.         wait_next_event(charger, now);  
  14.     }  
  15. }  
  1. static void event_loop(struct charger *charger)
  2. {
  3. int ret;
  4. while (true) {
  5. int64_t now = curr_time_ms();//(1)、获得当前时间;
  6. LOGV("[%lld] event_loop()\n", now);
  7. handle_input_state(charger, now);//(2)、检查按键状态;
  8. handle_power_supply_state(charger, now);// (3)、检查DC是否拔出;
  9. /* do screen update last in case any of the above want to start
  10. * screen transitions (animations, etc)
  11. */
  12. update_screen_state(charger, now);//(4)、对按键时间状态标志位的判断,显示不同电量的充电logo;
  13. wait_next_event(charger, now);
  14. }
  15. }

(1)、获得当前时间;

   int64_t now = curr_time_ms();

       这个时间来判断,有没有屏幕超时,如果超时关闭屏幕充电logo显示。

(2)、检查按键状态;

  1. static void handle_input_state(struct charger *charger, int64_t now)  
  2. {  
  3.     process_key(charger, KEY_POWER, now);  
  4.     if (charger->next_key_check != -1 && now > charger->next_key_check)  
  5.         charger->next_key_check = -1;  
  6. }  
  7. 我们再看下:process_key(charger, KEY_POWER, now);  
  8. static void process_key(struct charger *charger, int code, int64_t now)  
  9. {  
  10. ………………  
  11.     if (code == KEY_POWER) {  
  12.         if (key->down) {  
  13.             int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;  
  14.             if (now >= reboot_timeout) {//如果长按power键,就重新启动,也就是重启开机;  
  15.                 LOGI("[%lld] rebooting\n", now);  
  16.                 android_reboot(ANDROID_RB_RESTART, 0, 0);//重启命令;  
  17.             }  
  18.     ………………  
  19.     }  
  20.   
  21.     key->pending = false;  
  22. }  
  1. static void handle_input_state(struct charger *charger, int64_t now)
  2. {
  3. process_key(charger, KEY_POWER, now);
  4. if (charger->next_key_check != -1 && now > charger->next_key_check)
  5. charger->next_key_check = -1;
  6. }
  7. 我们再看下:process_key(charger, KEY_POWER, now);
  8. static void process_key(struct charger *charger, int code, int64_t now)
  9. {
  10. ………………
  11. if (code == KEY_POWER) {
  12. if (key->down) {
  13. int64_t reboot_timeout = key->timestamp + POWER_ON_KEY_TIME;
  14. if (now >= reboot_timeout) {//如果长按power键,就重新启动,也就是重启开机;
  15. LOGI("[%lld] rebooting\n", now);
  16. android_reboot(ANDROID_RB_RESTART, 0, 0);//重启命令;
  17. }
  18. ………………
  19. }
  20. key->pending = false;
  21. }

(3)、检查DC是否拔出;

handle_power_supply_state(charger, now); 

  1. static void handle_power_supply_state(struct charger *charger, int64_t now)  
  2. {  
  3.     if (charger->num_supplies_online == 0) {  
  4.         if (charger->next_pwr_check == -1) {  
  5.             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;  
  6.             LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n",  
  7.                  now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);  
  8.         } else if (now >= charger->next_pwr_check) {  
  9.             LOGI("[%lld] shutting down\n", now);  
  10.             android_reboot(ANDROID_RB_POWEROFF, 0, 0);//如果DC拔出,则关机;  
  11.         }   
  12. ………………  
  13. }  
  1. static void handle_power_supply_state(struct charger *charger, int64_t now)
  2. {
  3. if (charger->num_supplies_online == 0) {
  4. if (charger->next_pwr_check == -1) {
  5. charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
  6. LOGI("[%lld] device unplugged: shutting down in %lld (@ %lld)\n",
  7. now, UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);
  8. } else if (now >= charger->next_pwr_check) {
  9. LOGI("[%lld] shutting down\n", now);
  10. android_reboot(ANDROID_RB_POWEROFF, 0, 0);//如果DC拔出,则关机;
  11. }
  12. ………………
  13. }

(4)、对按键时间状态标志位的判断,显示不同电量的充电logo;

  update_screen_state(charger, now);

这个函数比较长了,其实做用就是:我们在状态的过程中,充电logo的电量是要增加的,比如电量是20%时,要从第一格开始闪烁;如果是80%时,则要从第三格开始闪烁,电量显示就是通过这个函数来计算实现的。

  1. static void update_screen_state(struct charger *charger, int64_t now)  
  2. {  
  3.     struct animation *batt_anim = charger->batt_anim;  
  4.     int cur_frame;  
  5.     int disp_time;  
  6.   
  7.     if (!batt_anim->run || now < charger->next_screen_transition)  
  8.         return;  
  9.   
  10.     /* animation is over, blank screen and leave */  
  11.     if (batt_anim->cur_cycle == batt_anim->num_cycles) {  
  12.         reset_animation(batt_anim);  
  13.         charger->next_screen_transition = -1;  
  14.         gr_fb_blank(true);  
  15.         LOGV("[%lld] animation done\n", now);  
  16.         return;  
  17.     }  
  18.   
  19.     disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;  
  20.   
  21.     /* animation starting, set up the animation */  
  22.     if (batt_anim->cur_frame == 0) {  
  23.         int batt_cap;  
  24.         int ret;  
  25.   
  26.         LOGV("[%lld] animation starting\n", now);  
  27.         batt_cap = get_battery_capacity(charger);  
  28.         if (batt_cap >= 0 && batt_anim->num_frames != 0) {  
  29.             int i;  
  30.   
  31.             /* find first frame given current capacity */  
  32.             for (i = 1; i < batt_anim->num_frames; i++) {  
  33.                 if (batt_cap < batt_anim->frames[i].min_capacity)  
  34.                     break;  
  35.             }  
  36.             batt_anim->cur_frame = i - 1;  
  37.   
  38.             /* show the first frame for twice as long */  
  39.             disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;  
  40.         }  
  41.   
  42.         batt_anim->capacity = batt_cap;  
  43.     }  
  44.   
  45.     /* unblank the screen  on first cycle */  
  46.     if (batt_anim->cur_cycle == 0)  
  47.         gr_fb_blank(false);  
  48.   
  49.     /* draw the new frame (@ cur_frame) */  
  50.     redraw_screen(charger);  
  51.   
  52.     /* if we don't have anim frames, we only have one image, so just bump 
  53.      * the cycle counter and exit 
  54.      */  
  55.     if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {  
  56.         LOGV("[%lld] animation missing or unknown battery status\n", now);  
  57.         charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;  
  58.         batt_anim->cur_cycle++;  
  59.         return;  
  60.     }  
  61.   
  62.     /* schedule next screen transition */  
  63.     charger->next_screen_transition = now + disp_time;  
  64.   
  65.     /* advance frame cntr to the next valid frame 
  66.      * if necessary, advance cycle cntr, and reset frame cntr 
  67.      */  
  68.     batt_anim->cur_frame++;  
  69.   
  70.     /* if the frame is used for level-only, that is only show it when it's 
  71.      * the current level, skip it during the animation. 
  72.      */  
  73.     while (batt_anim->cur_frame < batt_anim->num_frames &&  
  74.            batt_anim->frames[batt_anim->cur_frame].level_only)  
  75.         batt_anim->cur_frame++;  
  76.     if (batt_anim->cur_frame >= batt_anim->num_frames) {  
  77.         batt_anim->cur_cycle++;  
  78.         batt_anim->cur_frame = 0;  
  79.   
  80.         /* don't reset the cycle counter, since we use that as a signal 
  81.          * in a test above to check if animation is over 
  82.          */  
  83.     }  
  84. }  
  1. static void update_screen_state(struct charger *charger, int64_t now)
  2. {
  3. struct animation *batt_anim = charger->batt_anim;
  4. int cur_frame;
  5. int disp_time;
  6. if (!batt_anim->run || now < charger->next_screen_transition)
  7. return;
  8. /* animation is over, blank screen and leave */
  9. if (batt_anim->cur_cycle == batt_anim->num_cycles) {
  10. reset_animation(batt_anim);
  11. charger->next_screen_transition = -1;
  12. gr_fb_blank(true);
  13. LOGV("[%lld] animation done\n", now);
  14. return;
  15. }
  16. disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;
  17. /* animation starting, set up the animation */
  18. if (batt_anim->cur_frame == 0) {
  19. int batt_cap;
  20. int ret;
  21. LOGV("[%lld] animation starting\n", now);
  22. batt_cap = get_battery_capacity(charger);
  23. if (batt_cap >= 0 && batt_anim->num_frames != 0) {
  24. int i;
  25. /* find first frame given current capacity */
  26. for (i = 1; i < batt_anim->num_frames; i++) {
  27. if (batt_cap < batt_anim->frames[i].min_capacity)
  28. break;
  29. }
  30. batt_anim->cur_frame = i - 1;
  31. /* show the first frame for twice as long */
  32. disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
  33. }
  34. batt_anim->capacity = batt_cap;
  35. }
  36. /* unblank the screen on first cycle */
  37. if (batt_anim->cur_cycle == 0)
  38. gr_fb_blank(false);
  39. /* draw the new frame (@ cur_frame) */
  40. redraw_screen(charger);
  41. /* if we don't have anim frames, we only have one image, so just bump
  42. * the cycle counter and exit
  43. */
  44. if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {
  45. LOGV("[%lld] animation missing or unknown battery status\n", now);
  46. charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
  47. batt_anim->cur_cycle++;
  48. return;
  49. }
  50. /* schedule next screen transition */
  51. charger->next_screen_transition = now + disp_time;
  52. /* advance frame cntr to the next valid frame
  53. * if necessary, advance cycle cntr, and reset frame cntr
  54. */
  55. batt_anim->cur_frame++;
  56. /* if the frame is used for level-only, that is only show it when it's
  57. * the current level, skip it during the animation.
  58. */
  59. while (batt_anim->cur_frame < batt_anim->num_frames &&
  60. batt_anim->frames[batt_anim->cur_frame].level_only)
  61. batt_anim->cur_frame++;
  62. if (batt_anim->cur_frame >= batt_anim->num_frames) {
  63. batt_anim->cur_cycle++;
  64. batt_anim->cur_frame = 0;
  65. /* don't reset the cycle counter, since we use that as a signal
  66. * in a test above to check if animation is over
  67. */
  68. }
  69. }

下面是不能容量时显示logo的函数:

  1. static struct frame batt_anim_frames[] = {  
  2.     {  
  3.         .name = "charger/battery_0",  
  4.         .disp_time = 750,  
  5.         .min_capacity = 0,  
  6.     },  
  7.     {  
  8.         .name = "charger/battery_1",  
  9.         .disp_time = 750,  
  10.         .min_capacity = 20,  
  11.     },  
  12.     {  
  13.         .name = "charger/battery_2",  
  14.         .disp_time = 750,  
  15.         .min_capacity = 40,  
  16.     },  
  17.     {  
  18.         .name = "charger/battery_3",  
  19.         .disp_time = 750,  
  20.         .min_capacity = 60,  
  21.     },  
  22.     {  
  23.         .name = "charger/battery_4",  
  24.         .disp_time = 750,  
  25.         .min_capacity = 80,  
  26.         .level_only = true,  
  27.     },  
  28.     {  
  29.         .name = "charger/battery_5",  
  30.         .disp_time = 750,  
  31.         .min_capacity = BATTERY_FULL_THRESH,  
  32.     },  
  33. }; 


转载自xubin341719,感谢xubin341719无私的奉献


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/945199
推荐阅读
相关标签
  

闽ICP备14008679号