Android系统的开机画面显示过程分析(8)
生活随笔
收集整理的這篇文章主要介紹了
Android系统的开机画面显示过程分析(8)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??? ?3. 第三個開機畫面的顯示過程 ?? ? ? ?第三個開機畫面是由應用程序bootanimation來負責顯示的。應用程序bootanimation在啟動腳本init.rc中被配置成了一個服務,如下所示: service?bootanim?/system/bin/bootanimation?? ????user?graphics?? ????group?graphics?? ????disabled?? ????oneshot?? ?? ? ? 應用程序bootanimation的用戶和用戶組名稱分別被設置為graphics。注意,?用來啟動應用程序bootanimation的服務是disable的,即init進程在啟動的時候,不會主動將應用程序bootanimation啟動起來。當SurfaceFlinger服務啟動的時候,它會通過修改系統屬性ctl.start的值來通知init進程啟動應用程序bootanimation,以便可以顯示第三個開機畫面,而當System進程將系統中的關鍵服務都啟動起來之后,ActivityManagerService服務就會通知SurfaceFlinger服務來修改系統屬性ctl.stop的值,以便可以通知init進程停止執行應用程序bootanimation,即停止顯示第三個開機畫面。接下來我們就分別分析第三個開機畫面的顯示過程和停止過程。 ?? ? ?從前面Android系統進程Zygote啟動過程的源代碼分析一文可以知道,Zygote進程在啟動的過程中,會將System進程啟動起來,而從前面Android應用程序安裝過程源代碼分析一文又可以知道,System進程在啟動的過程(Step 3)中,會調用SurfaceFlinger類的靜態成員函數instantiate來啟動SurfaceFlinger服務。Sytem進程在啟動SurfaceFlinger服務的過程中,首先會創建一個SurfaceFlinger實例,然后再將這個實例注冊到Service Manager中去。在注冊的過程,前面創建的SurfaceFlinger實例會被一個sp指針引用。從前面Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析一文可以知道,當一個對象第一次被智能指針引用的時候,這個對象的成員函數onFirstRef就會被調用。由于SurfaceFlinger重寫了父類RefBase的成員函數onFirstRef,因此,在注冊SurfaceFlinger服務的過程中,將會調用SurfaceFlinger類的成員函數onFirstRef。在調用的過程,就會創建一個線程來啟動第三個開機畫面。 ?? ? ??SurfaceFlinger類實現在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp 中,它的成員函數onFirstRef的實現如下所示: void?SurfaceFlinger::onFirstRef()?? {?? ????run("SurfaceFlinger",?PRIORITY_URGENT_DISPLAY);?? ?? ????//?Wait?for?the?main?thread?to?be?done?with?its?initialization?? ????mReadyToRunBarrier.wait();?? }?? ?? ? ? ?SurfaceFlinger類繼承了Thread類,當它的成員函數run被調用的時候,系統就會創建一個新的線程。這個線程在第一次運行之前,會調用SurfaceFlinger類的成員函數readyToRun來通知SurfaceFlinger,它準備就緒了。當這個線程準備就緒之后,它就會循環執行SurfaceFlinger類的成員函數threadLoop,直到這個成員函數的返回值等于false為止。 ?? ? ? ?注意,SurfaceFlinger類的成員函數onFirstRef是在System進程的主線程中調用的,它需要等待前面創建的線程準備就緒之后,再繼續往前執行,這個通過調用SurfaceFlinger類的成員變量mReadytoRunBarrier所描述的一個Barrier對象的成員函數wait來實現的。每一個Barrier對象內問都封裝了一個條件變量(Condition Variable),而條件變量是用來同步線程的。 ?? ? ? ?接下來,我們繼續分析SurfaceFlinger類的成員函數readyToRun的實現,如下所示: status_t?SurfaceFlinger::readyToRun()?? {?? ????LOGI(???"SurfaceFlinger's?main?thread?ready?to?run.?"?? ????????????"Initializing?graphics?H/W...");?? ?????? ????......?? ?? ????mReadyToRunBarrier.open();?? ?? ????/*? ?????*??We're?now?ready?to?accept?clients...? ?????*/?? ?? ????//?start?boot?animation?? ????property_set("ctl.start",?"bootanim");?? ?? ????return?NO_ERROR;?? }??
?? ? ? 前面創建的線程用作SurfaceFlinger的主線程。這個線程在啟動的時候,會對設備主屏幕以及OpenGL庫進行初始化。初始化完成之后,接著就會調用SurfaceFlinger類的成員變量mReadyToRunBarrier所描述的一個Barrier對象的成員函數open來喚醒System進程的主線程,以便它可以繼續往前執行。最后,SurfaceFlinger類的成員函數readyToRun的成員函數會調用函數property_set來將系統屬性“ctl.start”的值設置為“bootanim”,表示要將應用程序bootanimation啟動起來,以便可以顯示第三個開機畫面。 ?? ? ? 前面在介紹第二個開機畫面的時候提到,當系統屬性發生改變時,init進程就會接收到一個系統屬性變化通知,這個通知最終是由在init進程中的函數handle_property_set_fd來處理的。 ?? ? ? 函數handle_property_set_fd實現在文件system/core/init/property_service.c中,如下所示: void?handle_property_set_fd()?? {?? ????prop_msg?msg;?? ????int?s;?? ????int?r;?? ????int?res;?? ????struct?ucred?cr;?? ????struct?sockaddr_un?addr;?? ????socklen_t?addr_size?=?sizeof(addr);?? ????socklen_t?cr_size?=?sizeof(cr);?? ?? ????if?((s?=?accept(property_set_fd,?(struct?sockaddr?*)?&addr,?&addr_size))?<?0)?{?? ????????return;?? ????}?? ?? ????/*?Check?socket?options?here?*/?? ????if?(getsockopt(s,?SOL_SOCKET,?SO_PEERCRED,?&cr,?&cr_size)?<?0)?{?? ????????close(s);?? ????????ERROR("Unable?to?recieve?socket?options\n");?? ????????return;?? ????}?? ?? ????r?=?recv(s,?&msg,?sizeof(msg),?0);?? ????close(s);?? ????if(r?!=?sizeof(prop_msg))?{?? ????????ERROR("sys_prop:?mis-match?msg?size?recieved:?%d?expected:?%d\n",?? ??????????????r,?sizeof(prop_msg));?? ????????return;?? ????}?? ?? ????switch(msg.cmd)?{?? ????case?PROP_MSG_SETPROP:?? ????????msg.name[PROP_NAME_MAX-1]?=?0;?? ????????msg.value[PROP_VALUE_MAX-1]?=?0;?? ?? ????????if(memcmp(msg.name,"ctl.",4)?==?0)?{?? ????????????if?(check_control_perms(msg.value,?cr.uid,?cr.gid))?{?? ????????????????handle_control_message((char*)?msg.name?+?4,?(char*)?msg.value);?? ????????????}?else?{?? ????????????????ERROR("sys_prop:?Unable?to?%s?service?ctl?[%s]?uid:?%d?pid:%d\n",?? ????????????????????????msg.name?+?4,?msg.value,?cr.uid,?cr.pid);?? ????????????}?? ????????}?else?{?? ????????????if?(check_perms(msg.name,?cr.uid,?cr.gid))?{?? ????????????????property_set((char*)?msg.name,?(char*)?msg.value);?? ????????????}?else?{?? ????????????????ERROR("sys_prop:?permission?denied?uid:%d??name:%s\n",?? ??????????????????????cr.uid,?msg.name);?? ????????????}?? ????????}?? ????????break;?? ?? ????default:?? ????????break;?? ????}?? }??
?? ? ? ?init進程是通過一個socket來接收系統屬性變化事件的。每一個系統屬性變化事件的內容都是通過一個prop_msg對象來描述的。在prop_msg對象對,成員變量name用來描述發生變化的系統屬性的名稱,而成員變量value用來描述發生變化的系統屬性的值。系統屬性分為兩種類型,一種是普通類型的系統屬性,另一種是控制類型的系統屬性(屬性名稱以“ctl.”開頭)??刂祁愋偷南到y屬性在發生變化時,會觸發init進程執行一個命令,而普通類型的系統屬性就不具有這個特性。注意,改變系統屬性是需要權限,因此,函數handle_property_set_fd在處理一個系統屬性變化事件之前,首先會檢查修改系統屬性的進程是否具有相應的權限,這是通過調用函數check_control_perms或者check_perms來實現的。 ?? ? ? ?從前面的調用過程可以知道,當前發生變化的系統屬性的名稱為“ctl.start”,它的值被設置為“bootanim”。由于這是一個控制類型的系統屬性,因此,在通過了權限檢查之后,另外一個函數handle_control_message就會被調用,以便可以執行一個名稱為“bootanim”的命令。
本文轉自 Luoshengyang 51CTO博客,原文鏈接:http://blog.51cto.com/shyluo/967040,如需轉載請自行聯系原作者
?? ? ? 前面創建的線程用作SurfaceFlinger的主線程。這個線程在啟動的時候,會對設備主屏幕以及OpenGL庫進行初始化。初始化完成之后,接著就會調用SurfaceFlinger類的成員變量mReadyToRunBarrier所描述的一個Barrier對象的成員函數open來喚醒System進程的主線程,以便它可以繼續往前執行。最后,SurfaceFlinger類的成員函數readyToRun的成員函數會調用函數property_set來將系統屬性“ctl.start”的值設置為“bootanim”,表示要將應用程序bootanimation啟動起來,以便可以顯示第三個開機畫面。 ?? ? ? 前面在介紹第二個開機畫面的時候提到,當系統屬性發生改變時,init進程就會接收到一個系統屬性變化通知,這個通知最終是由在init進程中的函數handle_property_set_fd來處理的。 ?? ? ? 函數handle_property_set_fd實現在文件system/core/init/property_service.c中,如下所示:
?? ? ? ?init進程是通過一個socket來接收系統屬性變化事件的。每一個系統屬性變化事件的內容都是通過一個prop_msg對象來描述的。在prop_msg對象對,成員變量name用來描述發生變化的系統屬性的名稱,而成員變量value用來描述發生變化的系統屬性的值。系統屬性分為兩種類型,一種是普通類型的系統屬性,另一種是控制類型的系統屬性(屬性名稱以“ctl.”開頭)??刂祁愋偷南到y屬性在發生變化時,會觸發init進程執行一個命令,而普通類型的系統屬性就不具有這個特性。注意,改變系統屬性是需要權限,因此,函數handle_property_set_fd在處理一個系統屬性變化事件之前,首先會檢查修改系統屬性的進程是否具有相應的權限,這是通過調用函數check_control_perms或者check_perms來實現的。 ?? ? ? ?從前面的調用過程可以知道,當前發生變化的系統屬性的名稱為“ctl.start”,它的值被設置為“bootanim”。由于這是一個控制類型的系統屬性,因此,在通過了權限檢查之后,另外一個函數handle_control_message就會被調用,以便可以執行一個名稱為“bootanim”的命令。
本文轉自 Luoshengyang 51CTO博客,原文鏈接:http://blog.51cto.com/shyluo/967040,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的Android系统的开机画面显示过程分析(8)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jq localStorage
- 下一篇: Android GridView Lru