Android啓動畫面

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,如果碰到這種情況就要對這個文件代碼做修改

發佈了11 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章