最近手头上开始倒腾smdk4412 android的开发,以前都是研究S5PC110 android2.3,拿到样机就发现logo和以前有很多的不一样的,这一次kernel的logo差不多是在程序一进入kernel就显示了,而第二张logo是系统下的*.lre文件,之后才是动画,尤其是充电的logo更是和以前不一样了,以前android2.3的时候我都是在uboot的时候初始化LCD之后,将图片转换成数组的形式然后一个个的点去填充。然后就对比了下当前系统是如何实现的,首先简单的看下系统关于充电logo显示的流程图,看这个应该一目了然了吧1、 首先对uboot当前检测mode看下代码,在smdk4212.c文件的 int board_late_init (void)函数点击(此处)折叠或打开printf("check start mode\n");//-->antaur  if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212)|| (*(int *)0x10020808==0x19721212)) {    setenv ("bootargs", "");  } else {    int tmp=*(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"); ////检测到有DC插入        printf("charger mode\n");    } else {        setenv ("bootargs", "");    }    *(int *)0x11000c08=tmp;  }     当前我的PMU是MAX77686,支持关机状态下插入DC自动开机,这里 setenv ("bootargs", "androidboot.mode=charger");这句很重要,设置了androidboot.mode=charger,这个到时在init.c文件读取,你就理解为将这个变量写到某个文件中去了(你可以尝试打开/proc/cmdline),好了,uboot的话注意这里就可以了之后kernel正常启动,2、 接着我们进入system/core/init/init.c点击(此处)折叠或打开int main(int argc, char **argv){        // 下面的代码开始建立各种用户空间的目录,如/dev、/proc、/sys等    mkdir("/dev", 0755);    mkdir("/proc", 0755);    mkdir("/sys", 0755);        // 处理内核命令行,关于bootmode变量会在这里得到相应的值    import_kernel_cmdline(0, import_kernel_nv);     chmod("/proc/cmdline", 0440);    get_hardware_name(hardware, &revision);    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);     queue_builtin_action(console_init_action, "console_init"); //显示initlogo.rle,也就是android第二张图片;    queue_builtin_action(set_init_properties_action, "set_init_properties");     // 在charger模式下略过mount文件系统的工作    if (strcmp(bootmode, "charger") != 0) {       。。。。。。。    }      if (!strcmp(bootmode, "charger")){//如果为charger,则调用charger.c        action_for_each_trigger("charger",action_add_queue_tail);    } 3、 如果检测到当前mode为charger mode的话,调用system/core/charger/charger.c点击(此处)折叠或打开int main(int argc, char **argv){      list_init(&charger->supplies);    klog_init();    klog_set_level(CHARGER_KLOG_LEVEL);    dump_last_kmsg();    gr_init();//初始化graphics    gr_font_size(&char_width, &char_height);//初始化buf大小    ev_init(input_callback, charger);//初始化按键,相关代码可以在bootable/recovery/minui/event.c    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");    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++) {  //显示充电logo        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);    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); //循环函数,主要就是更新logo、以及检测按键状态    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);//检测按键是否有按下,里面有个函数process_key        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);//刷充电logo        wait_next_event(charger, now);    }}看下对按键是如何做处理的点击(此处)折叠或打开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); //检测到长按power key 重启机器            } 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)                kick_animation(charger->batt_anim);        }    }    key->pending = false;}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 handle_power_supply_state(struct charger *charger, int64_t now){    if (charger->num_supplies_online == 0) {        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);  //如果拔掉了DC则系统关机        } 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;    }}好了,大致的流程代码里面应该都有叙述了,等下得分析下为何一进入kernel就可以显示logo了附:关于如何更换系统*.lre的logo,从别人那里复制了过来:1). 制作当前屏幕像素的图片(模拟器默认为1024*768) 使用PS制作一张1024*168的图片,保存时选“保存为 Web 所用格式”,然后在弹开的窗口上,“预设”项选择“PNG-24”,保存为android_logo.png(注:好像只支持png-24,其他格式生成的rle文件显示不正常,有兴趣大家可以再验证一下。2). 将图片转换为raw格式 使用linux下的ImageMagick自带的convert命令,进行raw格式转换,命令为:  convert -depth 8 android_logo.png rgb:android_logo.raw注:ubuntu 10.04 默认已经安装ImgageMagick工具,如果当前系统没有安装,可以执行下面的命令安装:  sudo apt-get install imagemagick3). 将raw格式转化为rle文件 需要用到android编译后的rgb2565工具,在android/out/host/linux-x86/bin目录下(android为当前源码所在目录),转换命令如下: rgb2565-rle initlogo.rle4).修改:tcc8923_20120127/device/telechips/m805_892x/device.mk添加下面一行:PRODUCT_COPY_FILES += \device/telechips/common/initlogo.rle:root/initlogo.rle意思是复制rle文件到ramdisk.img5、替换文件device\telechips\common\initlogo.rle;同时删除out\target\product\tcc8900\ramdisk.img,ramdisk-recovery.img,再重新编译,就可以了第二种方法:到目前为止,启动需要显示的图像已经做好了,就是initlogo.rle,注意文件名必须是这个,如果想改文件名,需要修改android/system/core/init/init.h中的宏: #define INIT_IMAGE_FILE "/initlogo.rle"============================================================================================下面需要将initlogo.rle加入的android文件系统中以下的4,5,6,7,需要先进行如下设置,把initlogo.rle放入device\telechips\common\,删除ramdisk.img之类的相关的文件重新make即可。4). 找到ramdisk.img文件(android/out/target/product/generic/ramdisk.img),将文件名改为ramdisk.img.gz,然后使用下面的命令解压: gunzip ramdisk.img.gz 解压后得到ramdisk.img,可能有人要问,怎么文件名又改回去了?其实不然,使用file ramdisk.img查看一下就知道了: 解压前:ramdisk.img: gzip compressed data, from Unix 解压后:ramdisk.img: ASCII cpio archive (SVR4 with no CRC) 跑题了,还是说正事儿。5). 使用cpio提取文件: 新建一个temp目录: mkdir temp cd temp cpio -i -F ../ramdisk.img6). 导出文件列表: cpio -i -t -F ../ramdisk.img > list注:list是一个文本文件,里面存储了ramdisk.img的文件结构,我们需要在这个文件中加入initlogo.rle这一行,修改后的文件如下 datadefault.propdevinitinit.goldfish.rcinit.rcinitlogo.rleprocsbinsbin/adbdsyssystem7). 生成ramdisk.img cpio -o -H newc -O ramdisk.img注:根据list文件的描述,生成ramdisk.img文件8). 用ramdisk.img覆盖sdk目录下的ramdisk.img(android-sdk-windows/platforms/android-2.1/images/ramdisk.img),最好先备份一下。
11-02 12:12