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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發(fā)布時(shí)間:2023/12/9 Android 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android系统的开机画面显示过程分析(8) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
??? ?3. 第三個(gè)開機(jī)畫面的顯示過程 ?? ? ? ?第三個(gè)開機(jī)畫面是由應(yīng)用程序bootanimation來負(fù)責(zé)顯示的。應(yīng)用程序bootanimation在啟動腳本init.rc中被配置成了一個(gè)服務(wù),如下所示:
  • service?bootanim?/system/bin/bootanimation??
  • ????user?graphics??
  • ????group?graphics??
  • ????disabled??
  • ????oneshot??
  • ?? ? ? 應(yīng)用程序bootanimation的用戶和用戶組名稱分別被設(shè)置為graphics。注意,?用來啟動應(yīng)用程序bootanimation的服務(wù)是disable的,即init進(jìn)程在啟動的時(shí)候,不會主動將應(yīng)用程序bootanimation啟動起來。當(dāng)SurfaceFlinger服務(wù)啟動的時(shí)候,它會通過修改系統(tǒng)屬性ctl.start的值來通知init進(jìn)程啟動應(yīng)用程序bootanimation,以便可以顯示第三個(gè)開機(jī)畫面,而當(dāng)System進(jìn)程將系統(tǒng)中的關(guān)鍵服務(wù)都啟動起來之后,ActivityManagerService服務(wù)就會通知SurfaceFlinger服務(wù)來修改系統(tǒng)屬性ctl.stop的值,以便可以通知init進(jìn)程停止執(zhí)行應(yīng)用程序bootanimation,即停止顯示第三個(gè)開機(jī)畫面。接下來我們就分別分析第三個(gè)開機(jī)畫面的顯示過程和停止過程。 ?? ? ?從前面Android系統(tǒng)進(jìn)程Zygote啟動過程的源代碼分析一文可以知道,Zygote進(jìn)程在啟動的過程中,會將System進(jìn)程啟動起來,而從前面Android應(yīng)用程序安裝過程源代碼分析一文又可以知道,System進(jìn)程在啟動的過程(Step 3)中,會調(diào)用SurfaceFlinger類的靜態(tài)成員函數(shù)instantiate來啟動SurfaceFlinger服務(wù)。Sytem進(jìn)程在啟動SurfaceFlinger服務(wù)的過程中,首先會創(chuàng)建一個(gè)SurfaceFlinger實(shí)例,然后再將這個(gè)實(shí)例注冊到Service Manager中去。在注冊的過程,前面創(chuàng)建的SurfaceFlinger實(shí)例會被一個(gè)sp指針引用。從前面Android系統(tǒng)的智能指針(輕量級指針、強(qiáng)指針和弱指針)的實(shí)現(xiàn)原理分析一文可以知道,當(dāng)一個(gè)對象第一次被智能指針引用的時(shí)候,這個(gè)對象的成員函數(shù)onFirstRef就會被調(diào)用。由于SurfaceFlinger重寫了父類RefBase的成員函數(shù)onFirstRef,因此,在注冊SurfaceFlinger服務(wù)的過程中,將會調(diào)用SurfaceFlinger類的成員函數(shù)onFirstRef。在調(diào)用的過程,就會創(chuàng)建一個(gè)線程來啟動第三個(gè)開機(jī)畫面。 ?? ? ??SurfaceFlinger類實(shí)現(xiàn)在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp 中,它的成員函數(shù)onFirstRef的實(shí)現(xiàn)如下所示:
  • void?SurfaceFlinger::onFirstRef()??
  • {??
  • ????run("SurfaceFlinger",?PRIORITY_URGENT_DISPLAY);??
  • ??
  • ????//?Wait?for?the?main?thread?to?be?done?with?its?initialization??
  • ????mReadyToRunBarrier.wait();??
  • }??
  • ?? ? ? ?SurfaceFlinger類繼承了Thread類,當(dāng)它的成員函數(shù)run被調(diào)用的時(shí)候,系統(tǒng)就會創(chuàng)建一個(gè)新的線程。這個(gè)線程在第一次運(yùn)行之前,會調(diào)用SurfaceFlinger類的成員函數(shù)readyToRun來通知SurfaceFlinger,它準(zhǔn)備就緒了。當(dāng)這個(gè)線程準(zhǔn)備就緒之后,它就會循環(huán)執(zhí)行SurfaceFlinger類的成員函數(shù)threadLoop,直到這個(gè)成員函數(shù)的返回值等于false為止。 ?? ? ? ?注意,SurfaceFlinger類的成員函數(shù)onFirstRef是在System進(jìn)程的主線程中調(diào)用的,它需要等待前面創(chuàng)建的線程準(zhǔn)備就緒之后,再繼續(xù)往前執(zhí)行,這個(gè)通過調(diào)用SurfaceFlinger類的成員變量mReadytoRunBarrier所描述的一個(gè)Barrier對象的成員函數(shù)wait來實(shí)現(xiàn)的。每一個(gè)Barrier對象內(nèi)問都封裝了一個(gè)條件變量(Condition Variable),而條件變量是用來同步線程的。 ?? ? ? ?接下來,我們繼續(xù)分析SurfaceFlinger類的成員函數(shù)readyToRun的實(shí)現(xiàn),如下所示:
  • 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;??
  • }??

  • ?? ? ? 前面創(chuàng)建的線程用作SurfaceFlinger的主線程。這個(gè)線程在啟動的時(shí)候,會對設(shè)備主屏幕以及OpenGL庫進(jìn)行初始化。初始化完成之后,接著就會調(diào)用SurfaceFlinger類的成員變量mReadyToRunBarrier所描述的一個(gè)Barrier對象的成員函數(shù)open來喚醒System進(jìn)程的主線程,以便它可以繼續(xù)往前執(zhí)行。最后,SurfaceFlinger類的成員函數(shù)readyToRun的成員函數(shù)會調(diào)用函數(shù)property_set來將系統(tǒng)屬性“ctl.start”的值設(shè)置為“bootanim”,表示要將應(yīng)用程序bootanimation啟動起來,以便可以顯示第三個(gè)開機(jī)畫面。
    ?? ? ? 前面在介紹第二個(gè)開機(jī)畫面的時(shí)候提到,當(dāng)系統(tǒng)屬性發(fā)生改變時(shí),init進(jìn)程就會接收到一個(gè)系統(tǒng)屬性變化通知,這個(gè)通知最終是由在init進(jìn)程中的函數(shù)handle_property_set_fd來處理的。 ?? ? ? 函數(shù)handle_property_set_fd實(shí)現(xiàn)在文件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進(jìn)程是通過一個(gè)socket來接收系統(tǒng)屬性變化事件的。每一個(gè)系統(tǒng)屬性變化事件的內(nèi)容都是通過一個(gè)prop_msg對象來描述的。在prop_msg對象對,成員變量name用來描述發(fā)生變化的系統(tǒng)屬性的名稱,而成員變量value用來描述發(fā)生變化的系統(tǒng)屬性的值。系統(tǒng)屬性分為兩種類型,一種是普通類型的系統(tǒng)屬性,另一種是控制類型的系統(tǒng)屬性(屬性名稱以“ctl.”開頭)。控制類型的系統(tǒng)屬性在發(fā)生變化時(shí),會觸發(fā)init進(jìn)程執(zhí)行一個(gè)命令,而普通類型的系統(tǒng)屬性就不具有這個(gè)特性。注意,改變系統(tǒng)屬性是需要權(quán)限,因此,函數(shù)handle_property_set_fd在處理一個(gè)系統(tǒng)屬性變化事件之前,首先會檢查修改系統(tǒng)屬性的進(jìn)程是否具有相應(yīng)的權(quán)限,這是通過調(diào)用函數(shù)check_control_perms或者check_perms來實(shí)現(xiàn)的。
    ?? ? ? ?從前面的調(diào)用過程可以知道,當(dāng)前發(fā)生變化的系統(tǒng)屬性的名稱為“ctl.start”,它的值被設(shè)置為“bootanim”。由于這是一個(gè)控制類型的系統(tǒng)屬性,因此,在通過了權(quán)限檢查之后,另外一個(gè)函數(shù)handle_control_message就會被調(diào)用,以便可以執(zhí)行一個(gè)名稱為“bootanim”的命令。



    本文轉(zhuǎn)自 Luoshengyang 51CTO博客,原文鏈接:http://blog.51cto.com/shyluo/967040,如需轉(zhuǎn)載請自行聯(lián)系原作者

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。