这句很重要,设置了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 imagemagick
3). 将raw格式转化为rle文件
需要用到android编译后的rgb2565工具,在android/out/host/linux-x86/bin目录下(android为当前源码所在目录),转换命令如下:
rgb2565
-rle < android_logo.raw > initlogo.rle
4).
修改:tcc8923_20120127/device/telechips/m805_892x/device.mk
添加下面一行:
PRODUCT_COPY_FILES += \
device/telechips/common/initlogo.rle:root/initlogo.rle
意思是复制rle文件到ramdisk.img
5、替换文件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.img
6). 导出文件列表:
cpio -i -t -F ../ramdisk.img > list
注:list是一个文本文件,里面存储了ramdisk.img的文件结构,我们需要在这个文件中加入initlogo.rle这一行,修改后的文件如下
data
default.prop
dev
init
init.goldfish.rc
init.rc
initlogo.rle
proc
sbin
sbin/adbd
sys
system
7). 生成ramdisk.img
cpio -o -H newc -O ramdisk.img < list
注:根据list文件的描述,生成ramdisk.img文件
8). 用ramdisk.img覆盖sdk目录下的ramdisk.img(android-sdk-windows/platforms/android-2.1/images/ramdisk.img),最好先备份一下。