内核源代码目录:/Volumes/android-kernel/source/goldfish
Android源代码目录:/Volumes/android/source
一、开机画面的简单介绍
网上有许多资料都提到,Android设备的开机画面分为三个画面,即:Linux内核Logo,Android启动Logo,Android动态画面。经过研究分析,Android设备默认只显示Android动画,那么如何显示内核Logo和启动Logo呢?和两条编译配置有关:
- CONFIG_FRAMEBUFFER_CONSOLE:打开该配置选项,就可以显示Android启动Logo。但出现问题:默认情况下是Android文字和Android动画交替闪烁。
- CONFIG_LOGO:打开该配置选项,并且CONFIG_FRAMEBUFFER_CONSOLE也开启的情况下,可以显示内核Logo。此项无问题。
这样的情况下,制作出来的Android内核不只是在启动时出现闪烁,而且运行后也会么一直这么闪烁,本文后面将介绍如何解决这个问题。
二、定制内核Logo
内核Logo默认是一个Linux企鹅图标,该图标只支持224种颜色,图标格式为:ppm。在Android内核源代码中的路径为:drivers/video/logo/logo_linux_clut224.ppm。所以,我们只需要替换此图标,则重新编译即可。
2.1、安装netpbm工具
Mac OS
  X下没有直接生成PPM格式图片的工具,可用netpbm转换。要安装netpbm工具,请先安装MacPorts,本文不描述如何安装和使用MacPorts,可在网上搜索安装和使用教程。
sudo port selfupdtae是让MacPorts先自我更新,sudo port install netpbm安装netpbm。
 # sudo port selfupdate
# sudo port install netpbm2.2、PPM图片转换
将预先做好的图片(假定为:MyLinux.png),转换为logo_linux_clut224.ppm格式:
# pngtopnm MyLinux.png > logo_linux_clut.pnm
# pnmquant 224 logo_linux_clut.pnm > logo_linux_clut224.pnm
# pnmtoplainpnm logo_linux_clut224.pnm > logo_linux_clut224.ppm
# cp logo_linux_clut224.ppm /Volumes/android-kernel/source/goldfish/drivers/video/logo/2.3、配置
许多教程中描述了使用make
  menuconfig来定制CONFIG_FRAMEBUFFER_CONSOLE和CONFIG_LOGO两个变量,这是一种方法,但在Mac环境中,make
  menuconfig不能正常运行,总是出现ncurses的相关库找不到,折腾了很久之后,放弃使用make menuconfig。
还有一种方法是使用make config,但这种方法要按N次回车,并仔细对比选项,太费事了。这里介绍一种快速的方法:
在编译内核的时候,我们使用了make goldfish_armv7_defconfig来配置的,只要将该默认配置修改一下,加入上面两个配置项至这个默认配置中,重新运行即可。命令如下:
# cd /Volumes/android-kernel/source/goldfish
# vi arch/arm/configs/goldfish_armv7_defconfig
在文件末尾加入:
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y按 wq 保存退出。
2.4、去掉光标
开启FRAME_BUFFER_CONSOLE后,会显示光标,需要修改源码解决,网上的方案比较复杂,经研究,这里介绍一个简单方法:
# vi drivers/video/console/softcursor.c
找到soft_cursor(...)函数,只留最后一句:return 0; 其他行注释掉:
int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
/*      struct fbcon_ops *ops = info->fbcon_par;
        unsigned int scan_align = info->pixmap.scan_align - 1;
        unsigned int buf_align = info->pixmap.buf_align - 1;
        unsigned int i, size, dsize, s_pitch, d_pitch;
        struct fb_image *image;
        u8 *src, *dst;
...
        fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
        image->data = dst;
        info->fbops->fb_imageblit(info, image);
*/      return 0;
}2.5、编译
# export PATH=/Volumes/android/source/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.7/bin/:$PATH
# make goldfish_armv7_defconfig
# make -j16
编译完成后,会在最后显示如下内容:
...
  OBJCOPY arch/arm/boot/zImage
  Kernel: arch/arm/boot/zImage is ready2.6、运行
运行如下指令:
运行可以成功显示开机Logo,但出现Android文字和Android动画交替闪烁的情况。
 # emulator -kernel arch/arm/boot/zImage
这个问题是由于启用CONFIG_FRAMEBUFFER_CONSOLE编译项后,init进程如果找不到“initlogo.rle”,就会进入text
   console模式,而后面的第三屏为动画的图形模式,从而造成两个界面交替闪烁的情况。分析过程如下:
先进入Android源代码根目录,注意不是内核目录。
找到console_init_action函数,这个是console启动函数,代码如下:先进入Android源代码根目录,注意不是内核目录。
# vi /Volumes/android/source/system/core/init/init.c...
static int console_init_action(int nargs, char **args)
{
    int fd;
    if (console[0]) {
        snprintf(console_name, sizeof(console_name), "/dev/%s", console);
    }
    fd = open(console_name, O_RDWR);
    if (fd >= 0)
        have_console = 1;
    close(fd);
    if( load_565rle_image(INIT_IMAGE_FILE) ) {
        fd = open("/dev/tty0", O_WRONLY);
        if (fd >= 0) {
            const char *msg;
                msg = "\n"
            "\n"
            "\n"
            "\n"
            "\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);
        }
    }
    return 0;
}
可以看到console_init_action函数会调用load_565rle_image函数来装入initlogo.rle文件,load_565rle_image函数在system/core/init/logo.c中。打开后的代码如下:
...
/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
int load_565rle_image(char *fn)
{
    struct FB fb;
    struct stat s;
    unsigned short *data, *bits, *ptr;
    unsigned count, max;
    int fd;
    if (vt_set_mode(1))
        return -1;
    fd = open(fn, O_RDONLY);
    if (fd < 0) {
        ERROR("cannot open '%s'\n", fn);
        goto fail_restore_text;
    }
...
    munmap(data, s.st_size);
    fb_update(&fb);
    fb_close(&fb);
    close(fd);
    unlink(fn);
    return 0;
fail_unmap_data:
    munmap(data, s.st_size);
fail_close_file:
    close(fd);
fail_restore_text:
    vt_set_mode(0);
    return -1;
}
由上面的代码可以看出,当装入initlogo.rle失败后,就走到fail_restore_text了,然后调用vt_set_mode(0),恢复成文本模式了。
现在问题找到了,是因为找不到initlogo.rle,系统回到text模式了。解决问题的方案有两个:- 制作initlogo.rle,即Android启动静态画面,见后文。
- 如果我不想要initlogo.rle怎么办呢?很简单,修改源代码。注释掉上面代码中的fail_restore_text:
    后面一句vt_set_mode(0);这样即使找不到initlogo.rle,也会进入图形模式,重新make,问题解决。
 # cd /Volumes/android/source # vi system/core/init/logo.c... /* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ int load_565rle_image(char *fn) { ... munmap(data, s.st_size); fb_update(&fb); fb_close(&fb); close(fd); unlink(fn); return 0; fail_unmap_data: munmap(data, s.st_size); fail_close_file: close(fd); fail_restore_text: /*vt_set_mode(0)*/; return -1; }# make -j16
三、定制Android启动Logo
Android启动时的静态画面为initlogo.rle文件,具体制作过程如下:
3.1 安装ImageMagick工具
此工具用于将png图片转换成raw文件,安装过程如下:
# sudo port install ImageMagick
安装完成后,convert指令将可以使用。
3.2 编译to2565.c,生成rgb2565工具
to565.c是Android自带的工具,用于将raw文件转换为rle文件。编译过程如下:
# cd /Volumes/android/source/build/tools/rgb2565/
# gcc -O2 -Wall  -Wno-unused-parameter -o rgb2565 to565.c3.3 制作initlogo.rle文件
先用Photoshop等软件制作一张与手机分辨率相同大小的图片(模拟器的分辨率为320*480),假定保存的文件名为:initlogo.png。为了看到运行变化,initlogo.png不要和内核Logo的图片一样。
# cd initlogo.png目录
# convert  -depth 8  initlogo.png  rgb:initlogo.raw
# /Volumes/android/source/build/tools/rgb2565/rgb2565 -rle  <initlogo.raw>  initlogo.rle
# cp initlogo.rle /Volumes/android/source/out/target/product/generic/root/3.4 重新编译
为确保成功,先删除ramdisk.img。
# cd /Volumes/android/source
# rm out/target/product/generic/ramdisk.img
# make -j16
编译完成后,运行。
# cd /Volumes/android-kernel/source/golefish
# emulator -kernel arch/arm/boot/zImage
这时,你应该看到先启动内核Logo,再启动此静态画面,最后启动Android动画了。
四、定制Android开机动画
其实,默认情况下,前面的内核Logo和Andriod的启动Logo是看不见的,如果没有特别需要,是不需要定制的。但Android开机动画默认情况下是能看见的,因此,此动画定制的可能性要大的多。而且,定制开机动画也要容易,没有前面那么多复杂的步骤,这应该是谷歌考虑到此屏幕基本都要被定制才弄成这么简单吧。
4.1 仿Android自带的动画
即Android默认的动画,此动画由两张图片组成:android-logo-mask.png,android-logo-shine.png,mask是由空心的android文字组成,即一个黑色的块,中间用Android文字挖空,这张图片是作为遮罩放在前端。shine则是一个发光的图片,放在mask的后面,通过循环移动shine,就成为Android发光动画。
用Photoshop修改这两张图片,保存在frameworks/base/core/res/assets/images目录下,文件名不变,再make即可。这个涉及资源重新编译,编译过程比较长,耐心等待。
bootanimation.zip可以放在/system/media目录或者放在/data/local目录下,/data/local目录下的优先使用。这两个目录在播放上也稍有区别,/system/media可以无限播放,/data/local只能播放10秒。
bootanimation.zip解压后的结构如下:
第二行:p 1 0 part0 p为标志符,表示将part0目录里的图片,播放一次,间隔时间为0秒。
第三行:p 0 0 part1 p为标志符,表示将part1目录里的图片,重复播放,间隔时间为0秒。
上面的目录和文件准备好后,执行以下指令:
将打好的bootanimation.zip包,拷贝到/system/media目录,再用make snod重新生成。再运行查看效果。
4.2 帧动画
帧动画是指由多帧图片组成的动画。这个设置是最简单的,以致于手机ROOT后,就可以在手机里直接下载一个bootanimation.zip,替换掉/system/media/bootanimation.zip,就能换掉这个开机动画。bootanimation.zip可以放在/system/media目录或者放在/data/local目录下,/data/local目录下的优先使用。这两个目录在播放上也稍有区别,/system/media可以无限播放,/data/local只能播放10秒。
bootanimation.zip解压后的结构如下:
- desc.txt
- part0
  - 0000.png
  - 0001.png
  - ...
- part1
  - 0000.png
  - 0001.png
  - ...
part0,part1是两个存放动画帧系列图片的目录。desc.txt是一个文本文件,文件的内容如下:320    480    30
p      1      0      part0
p      0      0      part1
第一行:320  480 30 表示播放分辨率为320*480,30表示每秒播放30帧图片。第二行:p 1 0 part0 p为标志符,表示将part0目录里的图片,播放一次,间隔时间为0秒。
第三行:p 0 0 part1 p为标志符,表示将part1目录里的图片,重复播放,间隔时间为0秒。
上面的目录和文件准备好后,执行以下指令:
# cd bootanimation所在目录 # zip -0 -r ../bootanimation.zip ./* # cp ../bootanimation.zip /Volumes/android/source/out/target/product/generic/system/media/ # make snod先CD进入bootanimation目录后,再执行zip压缩指令,保证不会将bootanimation目录打进包内。-0 表示只存储,不压缩,-r 表示包括子目录
将打好的bootanimation.zip包,拷贝到/system/media目录,再用make snod重新生成。再运行查看效果。
# cd /Volumes/android-kernel/source/golefish
# emulator -kernel arch/arm/boot/zImage


 
没有评论:
发表评论