日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android系统的开机画面显示过程分析(8)

發布時間:2023/12/9 Android 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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,如需轉載請自行聯系原作者

    總結

    以上是生活随笔為你收集整理的Android系统的开机画面显示过程分析(8)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。