中文字幕交换系列在线_一级黄片亚洲第一_午夜视频精品视在线播放_国产真人做受免费视频

始創(chuàng)于2000年 股票代碼:831685
咨詢熱線:0371-60135900 注冊(cè)有禮 登錄
  • 掛牌上市企業(yè)
  • 60秒人工響應(yīng)
  • 99.99%連通率
  • 7*24h人工
  • 故障100倍補(bǔ)償
全部產(chǎn)品
您的位置: 網(wǎng)站首頁(yè) > 幫助中心>文章內(nèi)容

Android系統(tǒng)的開(kāi)機(jī)畫(huà)面顯示過(guò)程分析

發(fā)布時(shí)間:  2012/8/30 17:29:52
好幾個(gè)月都沒(méi)有更新過(guò)博客了,從今天開(kāi)始,老羅將嘗試對(duì)Android系統(tǒng)的UI實(shí)現(xiàn)作一個(gè)系統(tǒng)的分析,也算是落實(shí)之前所作出的承諾。提到Android系統(tǒng)的UI,我們最先接觸到的便是系統(tǒng)在啟動(dòng)過(guò)程中所出現(xiàn)的畫(huà)面了。Android系統(tǒng)在啟動(dòng)的過(guò)程中,最多可以出現(xiàn)三個(gè)畫(huà)面,每一個(gè)畫(huà)面都用來(lái)描述一個(gè)不同的啟動(dòng)階段。本文將詳細(xì)分析這三個(gè)開(kāi)機(jī)畫(huà)面的顯示過(guò)程,以便可以開(kāi)啟我們對(duì)Android系統(tǒng)UI實(shí)現(xiàn)的分析之路。
        第一個(gè)開(kāi)機(jī)畫(huà)面是在內(nèi)核啟動(dòng)的過(guò)程中出現(xiàn)的,它是一個(gè)靜態(tài)的畫(huà)面。第二個(gè)開(kāi)機(jī)畫(huà)面是在init進(jìn)程啟動(dòng)的過(guò)程中出現(xiàn)的,它也是一個(gè)靜態(tài)的畫(huà)面。第三個(gè)開(kāi)機(jī)畫(huà)面是在系統(tǒng)服務(wù)啟動(dòng)的過(guò)程中出現(xiàn)的,它是一個(gè)動(dòng)態(tài)的畫(huà)面。無(wú)論是哪一個(gè)畫(huà)面,它們都是在一個(gè)稱為幀緩沖區(qū)(frame buffer,簡(jiǎn)稱fb)的硬件設(shè)備上進(jìn)行渲染的。接下來(lái),我們就分別分析這三個(gè)畫(huà)面是如何在fb上顯示的。
        1. 第一個(gè)開(kāi)機(jī)畫(huà)面的顯示過(guò)程
        Android系統(tǒng)的第一個(gè)開(kāi)機(jī)畫(huà)面其實(shí)是Linux內(nèi)核的啟動(dòng)畫(huà)面。在默認(rèn)情況下,這個(gè)畫(huà)面是不會(huì)出現(xiàn)的,除非我們?cè)诰幾g內(nèi)核的時(shí)候,啟用以下兩個(gè)編譯選項(xiàng):
        CONFIG_FRAMEBUFFER_CONSOLE
        CONFIG_LOGO
        第一個(gè)編譯選項(xiàng)表示內(nèi)核支持幀緩沖區(qū)控制臺(tái),它對(duì)應(yīng)的配置菜單項(xiàng)為:Device Drivers ---> Graphics support ---> Console display driver support ---> Framebuffer Console support。第二個(gè)編譯選項(xiàng)表示內(nèi)核在啟動(dòng)的過(guò)程中,需要顯示LOGO,它對(duì)應(yīng)的配置菜單項(xiàng)為:Device Drivers ---> Graphics support ---> Bootup logo。配置Android內(nèi)核編譯選項(xiàng)可以參考在Ubuntu上下載、編譯和安裝Android最新內(nèi)核源代碼(Linux Kernel)一文。
        幀緩沖區(qū)硬件設(shè)備在內(nèi)核中有一個(gè)對(duì)應(yīng)的驅(qū)動(dòng)程序模塊fbmem,它實(shí)現(xiàn)在文件kernel/goldfish/drivers/video/fbmem.c中,它的初始化函數(shù)如下所示:
  1. /**  
  2.  *      fbmem_init - init frame buffer subsystem  
  3.  *  
  4.  *      Initialize the frame buffer subsystem.  
  5.  *  
  6.  *      NOTE: This function is _only_ to be called by drivers/char/mem.c.  
  7.  *  
  8.  */   
  9.    
  10. static int __init   
  11. fbmem_init(void)   
  12. {   
  13.         proc_create("fb", 0, NULL, &fb_proc_fops);   
  14.    
  15.         if (register_chrdev(FB_MAJOR,"fb",&fb_fops))   
  16.                 printk("unable to get major %d for fb devs\n", FB_MAJOR);   
  17.    
  18.         fb_class = class_create(THIS_MODULE, "graphics");   
  19.         if (IS_ERR(fb_class)) {   
  20.                 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));   
  21.                 fb_class = NULL;   
  22.         }   
  23.         return 0;   
  24. }   
        這個(gè)函數(shù)首先調(diào)用函數(shù)proc_create在/proc目錄下創(chuàng)建了一個(gè)fb文件,接著又調(diào)用函數(shù)register_chrdev來(lái)注冊(cè)了一個(gè)名稱為fb的字符設(shè)備,最后調(diào)用函數(shù)class_create在/sys/class目錄下創(chuàng)建了一個(gè)graphics目錄,用來(lái)描述內(nèi)核的圖形系統(tǒng)。

 

 
        模塊fbmem除了會(huì)執(zhí)行上述初始化工作之外,還會(huì)導(dǎo)出一個(gè)函數(shù)register_framebuffer:
  1. EXPORT_SYMBOL(register_framebuffer);   

 

        這個(gè)函數(shù)在內(nèi)核的啟動(dòng)過(guò)程會(huì)被調(diào)用,以便用來(lái)執(zhí)行注冊(cè)幀緩沖區(qū)硬件設(shè)備的操作,它的實(shí)現(xiàn)如下所示:
  1. /**  
  2.  *      register_framebuffer - registers a frame buffer device  
  3.  *      @fb_info: frame buffer info structure  
  4.  *  
  5.  *      Registers a frame buffer device @fb_info.  
  6.  *  
  7.  *      Returns negative errno on error, or zero for success.  
  8.  *  
  9.  */   
  10.    
  11. int   
  12. register_framebuffer(struct fb_info *fb_info)   
  13. {   
  14.         int i;   
  15.         struct fb_event event;   
  16.         ......   
  17.    
  18.         if (num_registered_fb == FB_MAX)   
  19.                 return -ENXIO;   
  20.    
  21.         ......   
  22.    
  23.         num_registered_fb++;   
  24.         for (i = 0 ; i < FB_MAX; i++)   
  25.                 if (!registered_fb[i])   
  26.                         break;   
  27.         fb_info->node = i;   
  28.         mutex_init(&fb_info->lock);   
  29.         fb_info->dev = device_create(fb_class, fb_info->device,   
  30.                                      MKDEV(FB_MAJOR, i), NULL"fb%d", i);   
  31.         if (IS_ERR(fb_info->dev)) {   
  32.                 /* Not fatal */   
  33.                 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));   
  34.                 fb_info->dev = NULL;   
  35.         } else   
  36.                 fb_init_device(fb_info);   
  37.    
  38.         ......   
  39.    
  40.         registered_fb[i] = fb_info;   
  41.    
  42.         event.info = fb_info;   
  43.         fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);   
  44.         return 0;   
  45. }   
        由于系統(tǒng)中可能會(huì)存在多個(gè)幀緩沖區(qū)硬件設(shè)備,因此,fbmem模塊使用一個(gè)數(shù)組registered_fb保存所有已經(jīng)注冊(cè)了的幀緩沖區(qū)硬件設(shè)備,其中,每一個(gè)幀緩沖區(qū)硬件都是使用一個(gè)結(jié)構(gòu)體fb_info來(lái)描述的。

 

 
        我們知道,在Linux內(nèi)核中,每一個(gè)硬件設(shè)備都有一個(gè)主設(shè)備號(hào)和一個(gè)從設(shè)備號(hào),它們用來(lái)唯一地標(biāo)識(shí)一個(gè)硬件設(shè)備。對(duì)于幀緩沖區(qū)硬件設(shè)備來(lái)說(shuō),它們的主設(shè)備號(hào)定義為FB_MAJOR(29),而從設(shè)備號(hào)則與注冊(cè)的順序有關(guān),它們的值依次等于0,1,2等。
        每一個(gè)被注冊(cè)的幀緩沖區(qū)硬件設(shè)備在/dev/graphics目錄下都有一個(gè)對(duì)應(yīng)的設(shè)備文件fb<minor>,其中,<minor>表示一個(gè)從設(shè)備號(hào)。例如,第一個(gè)被注冊(cè)的幀緩沖區(qū)硬件設(shè)備在/dev/graphics目錄下都有一個(gè)對(duì)應(yīng)的設(shè)備文件fb0。用戶空間的應(yīng)用程序通過(guò)這個(gè)設(shè)備文件就可以操作幀緩沖區(qū)硬件設(shè)備了,即將要顯示的畫(huà)面渲染到幀緩沖區(qū)硬件設(shè)備上去。
        這個(gè)函數(shù)最后會(huì)通過(guò)調(diào)用函數(shù)fb_notifier_call_chain來(lái)通知幀緩沖區(qū)控制臺(tái),有一個(gè)新的幀緩沖區(qū)設(shè)備被注冊(cè)到內(nèi)核中來(lái)了。
        幀緩沖區(qū)控制臺(tái)在內(nèi)核中對(duì)應(yīng)的驅(qū)動(dòng)程序模塊為fbcon,它實(shí)現(xiàn)在文件kernel/goldfish/drivers/video/console/fbcon.c中,它的初始化函數(shù)如下所示:
  1. static struct notifier_block fbcon_event_notifier = {   
  2.         .notifier_call  = fbcon_event_notify,   
  3. };   
  4.    
  5. ......   
  6.    
  7. static int __init fb_console_init(void)   
  8. {   
  9.         int i;   
  10.    
  11.         acquire_console_sem();   
  12.         fb_register_client(&fbcon_event_notifier);   
  13.         fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,   
  14.                                      "fbcon");   
  15.    
  16.         if (IS_ERR(fbcon_device)) {   
  17.                 printk(KERN_WARNING "Unable to create device "   
  18.                        "for fbcon; errno = %ld\n",   
  19.                        PTR_ERR(fbcon_device));   
  20.                 fbcon_device = NULL;   
  21.         } else   
  22.                 fbcon_init_device();   
  23.    
  24.         for (i = 0; i < MAX_NR_CONSOLES; i++)   
  25.                 con2fb_map[i] = -1;   
  26.    
  27.         release_console_sem();   
  28.         fbcon_start();   
  29.         return 0;   
  30. }   

 

        這個(gè)函數(shù)除了會(huì)調(diào)用函數(shù)device_create來(lái)創(chuàng)建一個(gè)類別為graphics的設(shè)備fbcon之外,還會(huì)調(diào)用函數(shù)fb_register_client來(lái)監(jiān)聽(tīng)?zhēng)彌_區(qū)硬件設(shè)備的注冊(cè)事件,這是由函數(shù)fbcon_event_notify來(lái)實(shí)現(xiàn)的,如下所示:
  1. static int fbcon_event_notify(struct notifier_block *self,   
  2.                               unsigned long action, void *data)   
  3. {   
  4.         struct fb_event *event = data;   
  5.         struct fb_info *info = event->info;   
  6.         ......   
  7.         int ret = 0;   
  8.    
  9.         ......   
  10.    
  11.         switch(action) {   
  12.         ......   
  13.         case FB_EVENT_FB_REGISTERED:   
  14.                 ret = fbcon_fb_registered(info);   
  15.                 break;   
  16.         ......   
  17.    
  18.         }   
  19.    
  20. done:   
  21.         return ret;   
  22. }   
     幀緩沖區(qū)硬件設(shè)備的注冊(cè)事件最終是由函數(shù)fbcon_fb_registered來(lái)處理的,它的實(shí)現(xiàn)如下所示:
  1. static int fbcon_fb_registered(struct fb_info *info)   
  2. {   
  3.         int ret = 0, i, idx = info->node;   
  4.    
  5.         fbcon_select_primary(info);   
  6.    
  7.         if (info_idx == -1) {   
  8.                 for (i = first_fb_vc; i <= last_fb_vc; i++) {   
  9.                         if (con2fb_map_boot[i] == idx) {   
  10.                                 info_idx = idx;   
  11.                                 break;   
  12.                         }   
  13.                 }   
  14.    
  15.                 if (info_idx != -1)   
  16.                         ret = fbcon_takeover(1);   
  17.         } else {   
  18.                 for (i = first_fb_vc; i <= last_fb_vc; i++) {   
  19.                         if (con2fb_map_boot[i] == idx)   
  20.                                 set_con2fb_map(i, idx, 0);   
  21.                 }   
  22.         }   
  23.    
  24.         return ret;   
  25. }   
        函數(shù)fbcon_select_primary用來(lái)檢查當(dāng)前注冊(cè)的幀緩沖區(qū)硬件設(shè)備是否是一個(gè)主幀緩沖區(qū)硬件設(shè)備。如果是的話,那么就將它的信息記錄下來(lái)。這個(gè)函數(shù)只有當(dāng)指定了CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY編譯選項(xiàng)時(shí)才有效,否則的話,它是一個(gè)空函數(shù)。

 

 
        在Linux內(nèi)核中,每一個(gè)控制臺(tái)和每一個(gè)幀緩沖區(qū)硬件設(shè)備都有一個(gè)從0開(kāi)始的編號(hào),它們的初始對(duì)應(yīng)關(guān)系保存在全局?jǐn)?shù)組con2fb_map_boot中?刂婆_(tái)和幀緩沖區(qū)硬件設(shè)備的初始對(duì)應(yīng)關(guān)系是可以通過(guò)設(shè)置內(nèi)核啟動(dòng)參數(shù)來(lái)初始化的。在模塊fbcon中,還有另外一個(gè)全局?jǐn)?shù)組con2fb_map,也是用來(lái)映射控制臺(tái)和幀緩沖區(qū)硬件設(shè)備的對(duì)應(yīng)關(guān)系,不過(guò)它映射的是控制臺(tái)和幀緩沖區(qū)硬件設(shè)備的實(shí)際對(duì)應(yīng)關(guān)系。
        全局變量first_fb_vc和last_fb_vc是全局?jǐn)?shù)組con2fb_map_boot和con2fb_map的索引值,用來(lái)指定系統(tǒng)當(dāng)前可用的控制臺(tái)編號(hào)范圍,它們也是可以通過(guò)設(shè)置內(nèi)核啟動(dòng)參數(shù)來(lái)初始化的。全局變量first_fb_vc的默認(rèn)值等于0,而全局變量last_fb_vc的默認(rèn)值等于MAX_NR_CONSOLES - 1。
        全局變量info_idx表示系統(tǒng)當(dāng)前所使用的幀緩沖區(qū)硬件的編號(hào)。如果它的值等于-1,那么就說(shuō)明系統(tǒng)當(dāng)前還沒(méi)有設(shè)置好當(dāng)前所使用的幀緩沖區(qū)硬件設(shè)備。在這種情況下,函數(shù)fbcon_fb_registered就會(huì)在全局?jǐn)?shù)組con2fb_map_boot中檢查是否存在一個(gè)控制臺(tái)編號(hào)與當(dāng)前所注冊(cè)的幀緩沖區(qū)硬件設(shè)備的編號(hào)idx對(duì)應(yīng)。如果存在的話,那么就會(huì)將當(dāng)前所注冊(cè)的幀緩沖區(qū)硬件設(shè)備編號(hào)idx保存在全局變量info_idx中。接下來(lái)還會(huì)調(diào)用函數(shù)fbcon_takeover來(lái)初始化系統(tǒng)所使用的控制臺(tái)。在調(diào)用函數(shù)fbcon_takeover的時(shí)候,傳進(jìn)去的參數(shù)為1,表示要顯示第一個(gè)開(kāi)機(jī)畫(huà)面。
        如果全局變量info_idx的值不等于-1,那么函數(shù)fbcon_fb_registered同樣會(huì)在全局?jǐn)?shù)組con2fb_map_boot中檢查是否存在一個(gè)控制臺(tái)編號(hào)與當(dāng)前所注冊(cè)的幀緩沖區(qū)硬件設(shè)備的編號(hào)idx對(duì)應(yīng)。如果存在的話,那么就會(huì)調(diào)用函數(shù)set_con2fb_map來(lái)調(diào)整當(dāng)前所注冊(cè)的幀緩沖區(qū)硬件設(shè)備與控制臺(tái)的映射關(guān)系,即調(diào)整數(shù)組con2fb_map_boot和con2fb_map的值。
        為了簡(jiǎn)單起見(jiàn),我們假設(shè)系統(tǒng)只有一個(gè)幀緩沖區(qū)硬件設(shè)備,這樣當(dāng)它被注冊(cè)的時(shí)候,全局變量info_idx的值就會(huì)等于-1。當(dāng)函數(shù)fbcon_fb_registered在全局?jǐn)?shù)組con2fb_map_boot中發(fā)現(xiàn)有一個(gè)控制臺(tái)的編號(hào)與這個(gè)幀緩沖區(qū)硬件設(shè)備的編號(hào)idx對(duì)應(yīng)時(shí),接下來(lái)就會(huì)調(diào)用函數(shù)fbcon_takeover來(lái)設(shè)置系統(tǒng)所使用的控制臺(tái)。
        函數(shù)fbcon_takeover的實(shí)現(xiàn)如下所示:
  1. static int fbcon_takeover(int show_logo)   
  2. {   
  3.         int err, i;   
  4.    
  5.         if (!num_registered_fb)   
  6.                 return -ENODEV;   
  7.    
  8.         if (!show_logo)   
  9.                 logo_shown = FBCON_LOGO_DONTSHOW;   
  10.    
  11.         for (i = first_fb_vc; i <= last_fb_vc; i++)   
  12.                 con2fb_map[i] = info_idx;   
  13.    
  14.         err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,   
  15.                                 fbcon_is_default);   
  16.    
  17.         if (err) {   
  18.                 for (i = first_fb_vc; i <= last_fb_vc; i++) {   
  19.                         con2fb_map[i] = -1;   
  20.                 }   
  21.                 info_idx = -1;   
  22.         }   
  23.    
  24.         return err;   
  25. }   

 

        全局變量logo_shown的初始值為FBCON_LOGO_CANSHOW,表示可以顯示第一個(gè)開(kāi)機(jī)畫(huà)面。但是當(dāng)參數(shù)show_logo的值等于0的時(shí)候,全局變量logo_shown的值會(huì)被重新設(shè)置為FBCON_LOGO_DONTSHOW,表示不可以顯示第一個(gè)開(kāi)機(jī)畫(huà)面。

 

 
        中間的for循環(huán)將當(dāng)前可用的控制臺(tái)的編號(hào)都映射到當(dāng)前正在注冊(cè)的幀緩沖區(qū)硬件設(shè)備的編號(hào)info_idx中去,表示當(dāng)前可用的控制臺(tái)與緩沖區(qū)硬件設(shè)備的實(shí)際映射關(guān)系。
        函數(shù)take_over_console用來(lái)初始化系統(tǒng)當(dāng)前所使用的控制臺(tái)。如果它的返回值不等于0,那么就表示初始化失敗。在這種情況下,最后的for循環(huán)就會(huì)將全局?jǐn)?shù)組con2fb_map的各個(gè)元素的值設(shè)置為-1,表示系統(tǒng)當(dāng)前可用的控制臺(tái)還沒(méi)有映射到實(shí)際的幀緩沖區(qū)硬件設(shè)備中去。這時(shí)候全局變量info_idx的值也會(huì)被重新設(shè)置為-1。
       調(diào)用函數(shù)take_over_console來(lái)初始化系統(tǒng)當(dāng)前所使用的控制臺(tái),實(shí)際上就是向系統(tǒng)注冊(cè)一系列回調(diào)函數(shù),以便系統(tǒng)可以通過(guò)這些回調(diào)函數(shù)來(lái)操作當(dāng)前所使用的控制臺(tái)。這些回調(diào)函數(shù)使用結(jié)構(gòu)體consw來(lái)描述。這里所注冊(cè)的結(jié)構(gòu)體consw是由全局變量fb_con來(lái)指定的,它的定義如下所示:
  1. /*  
  2.  *  The console `switch' structure for the frame buffer based console  
  3.  */   
  4.    
  5. static const struct consw fb_con = {   
  6.         .owner                  = THIS_MODULE,   
  7.         .con_startup            = fbcon_startup,   
  8.         .con_init               = fbcon_init,   
  9.         .con_deinit             = fbcon_deinit,   
  10.         .con_clear              = fbcon_clear,   
  11.         .con_putc               = fbcon_putc,   
  12.         .con_putcs              = fbcon_putcs,   
  13.         .con_cursor             = fbcon_cursor,   
  14.         .con_scroll             = fbcon_scroll,   
  15.         .con_bmove              = fbcon_bmove,   
  16.         .con_switch             = fbcon_switch,   
  17.         .con_blank              = fbcon_blank,   
  18.         .con_font_set           = fbcon_set_font,   
  19.         .con_font_get           = fbcon_get_font,   
  20.         .con_font_default       = fbcon_set_def_font,   
  21.         .con_font_copy          = fbcon_copy_font,   
  22.         .con_set_palette        = fbcon_set_palette,   
  23.         .con_scrolldelta        = fbcon_scrolldelta,   
  24.         .con_set_origin         = fbcon_set_origin,   
  25.         .con_invert_region      = fbcon_invert_region,   
  26.         .con_screen_pos         = fbcon_screen_pos,   
  27.         .con_getxy              = fbcon_getxy,   
  28.         .con_resize             = fbcon_resize,   
  29. };   

本文出自:億恩科技【xuefeilisp.com】

服務(wù)器租用/服務(wù)器托管中國(guó)五強(qiáng)!虛擬主機(jī)域名注冊(cè)頂級(jí)提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM]

  • 您可能在找
  • 億恩北京公司:
  • 經(jīng)營(yíng)性ICP/ISP證:京B2-20150015
  • 億恩鄭州公司:
  • 經(jīng)營(yíng)性ICP/ISP/IDC證:豫B1.B2-20060070
  • 億恩南昌公司:
  • 經(jīng)營(yíng)性ICP/ISP證:贛B2-20080012
  • 服務(wù)器/云主機(jī) 24小時(shí)售后服務(wù)電話:0371-60135900
  • 虛擬主機(jī)/智能建站 24小時(shí)售后服務(wù)電話:0371-60135900
  • 專注服務(wù)器托管17年
    掃掃關(guān)注-微信公眾號(hào)
    0371-60135900
    Copyright© 1999-2019 ENKJ All Rights Reserved 億恩科技 版權(quán)所有  地址:鄭州市高新區(qū)翠竹街1號(hào)總部企業(yè)基地億恩大廈  法律顧問(wèn):河南亞太人律師事務(wù)所郝建鋒、杜慧月律師   京公網(wǎng)安備41019702002023號(hào)
      0
     
     
     
     

    0371-60135900
    7*24小時(shí)客服服務(wù)熱線