Android启动画面

来源:互联网 发布:.net 微商城源码 编辑:程序博客网 时间:2024/05/16 09:44

Android有三种启动画面

1. 在kernel framebuffer驱动中的logo, 具体参见kernel/drivers/video/fbmem.c,这是最早的静态启动画面

2. init进程加载的启动画面,具体参考android/system/core/init/init.c 中load_565rle_image的实现

3. bootanimation动画,一般来说init.rc中会有下面一段:

service bootanim /system/bin/bootanimation
    user graphics
    group graphics
    disabled
    oneshot

bootanimation的实现参考frameworks/base/cmds/bootanimation/目录,这个进程会显示一段动画


这里要描述的是第二种开机画面

1 load_565rle_image源码

[html] view plaincopy
  1. 105 int load_565rle_image(char *fn)  
  2. 106 {  
  3. 107     struct FB fb;  
  4. 108     struct stat s;  
  5. 109     unsigned short *data, *bits, *ptr;  
  6. 110     unsigned count, max;  
  7. 111     int fd;  
  8. 112  
  9. 113     if (vt_set_mode(1))  
  10. 114         return -1;  
  11. 115  
  12. 116     fd = open(fn, O_RDONLY);  
  13. 117     if (fd < 0) {  
  14. 118         ERROR("cannot open '%s'\n", fn);  
  15. 119         goto fail_restore_text;  
  16. 120     }  
  17. 121  
  18. 122     if (fstat(fd, &s) < 0) {  
  19. 123         goto fail_close_file;  
  20. 124     }  
  21. 125  
  22. 126     data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);  
  23. 127     if (data == MAP_FAILED)  
  24. 128         goto fail_close_file;  
  25. 129  
  26. 130     if (fb_open(&fb))  
  27. 131         goto fail_unmap_data;  
  28. 132  
  29. 133     max = fb_width(&fb) * fb_height(&fb);  
  30. 134     ptr = data;  
  31. 135     count = s.st_size;  
  32. 136     bits = fb.bits;  
  33. 137     while (count > 3) {  
  34. 138         unsigned n = ptr[0];  
  35. 139         if (n > max)  
  36. 140             break;  
  37. 141         android_memset16(bits, ptr[1], n << 1);  
  38. 142         bits += n;  
  39. 143         max -n;  
  40. 144         ptr += 2;  
  41. 145         count -4;  
  42. 146     }  
  43. 147  
  44. 148     munmap(data, s.st_size);  
  45. 149     fb_update(&fb);  
  46. 150     fb_close(&fb);  
  47. 151     close(fd);  
  48. 152     unlink(fn);  
  49. 153     return 0;  
  50. 154  
  51. 155 fail_unmap_data:  
  52. 156     munmap(data, s.st_size);  
  53. 157 fail_close_file:  
  54. 158     close(fd);  
  55. 159 fail_restore_text:  
  56. 160     vt_set_mode(0);  
  57. 161     return -1;  
  58. 162 }  
  59. 163   


2 rle图像文件格式

load_565rle_image 函数的输入参数是一个rle文件,该函数会把这个文件内容转换为rgb565,写入framebuffer。

以下百度百科来的rle简介 http://baike.baidu.com/view/18819.htm?fromTaglist

--------------------

RLE全称(run-length encoding),翻译为游程编码,又译行程长度编码,又称变动长度编码法(run coding),在控制论中对于二值图像而言是一种编码方法,对连续的黑、白像素数(游程)以不同的码字进行编码。游程编码是一种简单的非破坏性资料压缩法,其好处是加压缩和解压缩都非常快。其方法是计算连续出现的资料长度压缩之。

-------------------

RLE文件格式为 [count(2 bytes), color(2 bytes)], count最大为65535;color为RGB565, 当然也可以是YUV422,我觉得只要是2bytes以下的都可以,但是由于最终我们写入到framebuffer中的都是RGB565,从效率的角度,rle文件的color值为RGB565最好。

3 写入framebuffer

load_565rel_image 源码第141行:写入n个像素点,像素点的color值是rle中的原始数据,这对于rgb565的framebuffer没有问题,但是如果framebuffer是RGB32(ARGB),就无法工作了。解决办法是做个转换,把2bytes的RGB565转换为4 bytes的ARGB 即可。

上代码

[html] view plaincopy
  1. #define rgb32_r(rle) (((rle & 0xf800) >> 11) << 3)  
  2. #define rgb32_g(rle) (((rle & 0x07e0) >> 5 << 2))  
  3. #define rgb32_b(rle) (((rle & 0x001f) << 3))  
  4. #define rgb32(rle) (rgb32_r(rle) << 16 | rgb32_g(rle) << 8 | rgb32_b(rle) << 0)   
  5.   
  6.   
  7.         unsigned int *bits;  
  8.         bits = (unsigned int *)fb.bits;  
  9.         while (count > 3) {  
  10.             unsigned n = ptr[0];  
  11.             if (n > max)  
  12.                 break;  
  13.             out = rgb32(ptr[1]);  
  14.             android_memset32(bits, out, n << 2);  
  15.             bits += n;  
  16.             max -n;  
  17.             ptr += 2;  
  18.             count -4;  

4 现在再回去,看看怎么得到rle格式的文件,一般来说分两步走,先把原始图片转为RGB565,然后再把RGB565转为rle(当然不是必需的,如果有个能把png直接转为rle的工具)。

a) 先用GMIP生成一个800X480的png文件,为什么是800x480,图片大小必须和屏大小一致,至于是不是png无所谓,只要有工具能转为RGB565即可

b) convert命令png为RGB565: convert -depth 8 android_logo.png rgb:android_logo.raw

c) 转换RGB565为rle文件:rgb2565 -rle < android_logo.raw > initlogo.rle 

5. 替换ramdisk中的initlogo.rle,重新启动即可看到新的启动画面


注意load_565rle_image 152行 unlink(fn)会删除initlogo.rle文件,进入系统后,会发现/initlogo.rle文件已经被删除了,这样可以节约一点ramdisk文件系统的内存空间,

对于ramdisk做rootfs,这没有问题,因为ramdisk镜像本身并没有被修改

但是如果根文件系统是其他文件系统,就需要把unlink(fn)注释掉,以防止initlog.rle被永久删除。


android/system/core/init/logo.c 可扩展性并不是很好,代码假定framebuffer是RGB565,实际上我接触到的就有其他格式的FB,比如YUYV和ARGB,如果碰到这种情况就要对这个文件代码做修改

原创粉丝点击