萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 安卓開發 >> Android系統的開機畫面顯示過程是怎樣的

Android系統的開機畫面顯示過程是怎樣的

這是一篇介紹 Android系統的開機畫面顯示過程的文章,下面就讓我們一起來了解一下吧!

接下來我們就重點分析函數console_init_action的實現:

static int console_init_action(int nargs, char **args)

{

int fd;

char tmp[PROP_VALUE_MAX];

if (console[0]) {

snprintf(tmp, sizeof(tmp), "/dev/%s", console);

console_name = strdup(tmp);

}

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;

}

這個函數主要做了兩件事件:

A. 初始化控制台。init進程在啟動的時候,會解析內核的啟動參數(保存在文件/proc/cmdline中)。如果發現內核的啟動參數中包含有了一個名稱為“androidboot.console”的屬性,那麼就會將這個屬性的值保存在字符數組console中。這樣我們就可以通過設備文件/dev/來訪問系統的控制台。如果內核的啟動參數沒有包含名稱為“androidboot.console”的屬性,那麼默認就通過設備文件/dev/console來訪問系統的控制台。如果能夠成功地打開設備文件/dev/或者/dev/console,那麼就說明系統支持訪問控制台,因此,全局變量have_console的就會被設置為1。

B. 顯示第二個開機畫面。顯示第二個開機畫面是通過調用函數load_565rle_image來實現的。在調用函數load_565rle_image的時候,指定的開機畫面文件為INIT_IMAGE_FILE。INIT_IMAGE_FILE是一個宏,定義在system/core/init/init.h文件中,如下所示:

#define INIT_IMAGE_FILE "/initlogo.rle"

即第二個開機畫面的內容是由文件/initlogo.rle來指定的。如果文件/initlogo.rle不存在,或者在顯示它的過程中出現異常,那麼函數load_565rle_image的返回值就會等於-1,這時候函數console_init_action就以文本的方式來顯示第二個開機畫面,即向編號為0的控制台(/dev/tty0)輸出“ANDROID”這7個字符。

函數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;

}

if (fstat(fd, &s) < 0) {

goto fail_close_file;

}

data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);

if (data == MAP_FAILED)

goto fail_close_file;

if (fb_open(&fb))

goto fail_unmap_data;

max = fb_width(&fb) * fb_height(&fb);

ptr = data;

count = s.st_size;

bits = fb.bits;

while (count > 3) {

unsigned n = ptr[0];

if (n > max)

break;

android_memset16(bits, ptr[1], n << 1);

bits += n;

max -= n;

ptr += 2;

count -= 4;

}

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;

}

函數首先將控制台的顯示方式設置為圖形方式,這是通過調用函數vt_set_mode來實現的,如下所示:

static int vt_set_mode(int graphics)

{

int fd, r;

fd = open("/dev/tty0", O_RDWR | O_SYNC);

if (fd < 0)

return -1;

r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT));

close(fd);

return r;

}

函數vt_set_mode首先打開控制台設備文件/dev/tty0,接著再通過IO控制命令KDSETMODE來將控制台的顯示方式設置為文本方式或者圖形方式,取決於參數graphics的值。從前面的調用過程可以知道,參數graphics的值等於1,因此,這裡是將控制台的顯示方式設備為圖形方式。

回到函數load_565rle_image中,從前面的調用過程可以知道,參數fn的值等於“/initlogo.rle”,即指向目標設備上的initlogo.rle文件。函數load_565rle_image首先調用函數open打開這個文件,並且將獲得的文件描述符保存在變量fd中,接著再調用函數fstat來獲得這個文件的大小。有了這些信息之後,函數load_565rle_image就可以調用函數mmap來把文件/initlogo.rle映射到init進程的地址空間來了,以便可以讀取它的內容。

將文件/initlogo.rle映射到init進程的地址空間之後,接下來再調用函數fb_open來打開設備文件/dev/graphics/fb0。前面在介紹第一個開機畫面的顯示過程中提到,設備文件/dev/graphics/fb0是用來訪問系統的幀緩沖區硬件設備的,因此,打開了設備文件/dev/graphics/fb0之後,我們就可以將文件/initlogo.rle的內容輸出到幀緩沖區硬件設備中去了。

以上就是關於 Android系統的開機畫面顯示過程的介紹,希望對大家有所幫助!

copyright © 萬盛學電腦網 all rights reserved