Android系统Surface机制的SurfaceFlinger服务的启动过程分析
? ? ? ?在前面一篇文章中,我們簡要介紹了Android系統(tǒng)Surface機制中的SurfaceFlinger服務(wù)。SurfaceFlinger服務(wù)是在System進程中啟動的,并且負(fù)責(zé)統(tǒng)一管理設(shè)備的幀緩沖區(qū)。SurfaceFlinger服務(wù)在啟動的過程中,會創(chuàng)建兩個線程,其中一個線程用來監(jiān)控控制臺事件,而另外一個線程用來渲染系統(tǒng)的UI。在本文中,我們就將詳細分析SurfaceFlinger服務(wù)的啟動過程。
? ? ? ?從前面Android系統(tǒng)進程Zygote啟動過程的源代碼分析一文可以知道,System進程是由Zygote進程啟動的,并且是以Java層的SystemServer類的靜態(tài)成員函數(shù)main為入口函數(shù)的。因此,接下來我們就從SystemServer類的靜態(tài)成員函數(shù)main開始,分析SurfaceFlinger服務(wù)的啟動過程,如圖1所示。
圖1 SurfaceFlinger服務(wù)的啟動過程
? ? ? SurfaceFlinger服務(wù)的啟動過程可以劃分為8個步驟,接下來我們就詳細分析每一個步驟。
? ? ? Step 1. SystemServer.main
public class SystemServer {......native public static void init1(String[] args);public static void main(String[] args) {......System.loadLibrary("android_servers");init1(args);}...... }? ? ? ?這個函數(shù)定義在文件frameworks/base/services/java/com/android/server/SystemServer.java中。
? ? ? ?SystemServer類的靜態(tài)成員函數(shù)main首先將android_servers庫加載到System進程中來,接著調(diào)用另外一個靜態(tài)成員函數(shù)init1來啟動那些使用C++語言來實現(xiàn)的系統(tǒng)服務(wù)。
? ? ? ?SystemServer類的靜態(tài)成員函數(shù)init1是一個JNI方法,它是由C++層的函數(shù)android_server_SystemServer_init1來實現(xiàn)的,接下來我們就繼續(xù)分析它的實現(xiàn)。
? ? ? ?Step 2. SystemServer.init1
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) {system_init(); }? ? ? 這個函數(shù)定義在文件frameworks/base/services/jni/com_android_server_SystemServer.cpp 中。
? ? ? SystemServer類的靜態(tài)成員函數(shù)init1調(diào)用另外一個函數(shù)system_init來啟動那些使用C++語言來實現(xiàn)的系統(tǒng)服務(wù),它的實現(xiàn)在文件frameworks/base/cmds/system_server/library/system_init.cpp中,如下所示:
extern "C" status_t system_init() {LOGI("Entered system_init()");sp<ProcessState> proc(ProcessState::self());......char propBuf[PROPERTY_VALUE_MAX];property_get("system_init.startsurfaceflinger", propBuf, "1");if (strcmp(propBuf, "1") == 0) {// Start the SurfaceFlingerSurfaceFlinger::instantiate();}......if (proc->supportsProcesses()) {LOGI("System server: entering thread pool.\n");ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();LOGI("System server: exiting thread pool.\n");}return NO_ERROR; }? ? ? 函數(shù)首先獲得System進程中的一個ProcessState單例,并且保存在變量proc中,后面會通過調(diào)用它的成員函數(shù)supportsProcesses來判斷系統(tǒng)是否支持Binder進程間通信機制。我們知道,在Android系統(tǒng)中,每一個需要使用Binder進程間通信機制的進程內(nèi)部都有一個ProcessState單例,它是用來和Binder驅(qū)動程序建立連接的,具體可以參考Android系統(tǒng)進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文。
? ? ? 函數(shù)接下來就檢查系統(tǒng)中是否存在一個名稱為“system_init.startsurfaceflinger”的屬性。如果存在的話,就將它的值獲取回來,并且保存在緩沖區(qū)proBuf中。如果不存在的話,那么函數(shù)property_get就會將緩沖區(qū)proBuf的值設(shè)置為“1”。當(dāng)緩沖區(qū)proBuf的值等于“1”的時候,就表示需要在System進程中將SurfaceFlinger服務(wù)啟動起來,這是通過調(diào)用SurfaceFlinger類的靜態(tài)成員函數(shù)instantiate來實現(xiàn)的。
? ? ? 函數(shù)最后檢查系統(tǒng)是否支持Binder進程間通信機制。如果支持的話,那么接下來就會調(diào)用當(dāng)前進程中的ProcessState單例的成員函數(shù)startThreadPool來啟動一個Binder線程池,并且調(diào)用當(dāng)前線程中的IPCThreadState單例來將當(dāng)前線程加入到前面所啟動的Binder線程池中去。從前面Android系統(tǒng)進程Zygote啟動過程的源代碼分析和Android應(yīng)用程序進程啟動過程的源代碼分析兩篇文章可以知道,System進程前面在初始化運行時庫的過程中,已經(jīng)調(diào)用過當(dāng)前進程中的ProcessState單例的成員函數(shù)startThreadPool來啟動Binder線程池了,因此,這里其實只是將當(dāng)前線程加入到這個Binder線程池中去。有了這個Binder線程池之后,SurfaceFlinger服務(wù)在啟動完成之后,就可以為系統(tǒng)中的其他組件或者進程提供服務(wù)了。
? ? ? 假設(shè)系統(tǒng)存在一個名稱為“system_init.startsurfaceflinger”的屬性,并且它的值等于“1”,接下來我們就繼續(xù)分析SurfaceFlinger類的靜態(tài)成員函數(shù)instantiate的實現(xiàn),以便可以了解SurfaceFlinger服務(wù)的啟動過程。由于SurfaceFlinger類的靜態(tài)成員函數(shù)instantiate是從父類BinderService繼承下來的,因此,接下來我們要分析的實際上是BinderService類的靜態(tài)成員函數(shù)instantiate的實現(xiàn)。
? ? ? Step 3. BinderService.instantiate
template<typename SERVICE> class BinderService { public:......static void instantiate() { publish(); }...... };? ? ? 這個函數(shù)定義在文件frameworks/base/include/binder/BinderService.h中。
? ? ? BinderService類的靜態(tài)成員函數(shù)instantiate的實現(xiàn)很簡單,它只是調(diào)用BinderService類的另外一個靜態(tài)成員函數(shù)publish來繼續(xù)執(zhí)行啟動SurfaceFlinger服務(wù)的操作。
? ? ? Step 4. BinderService.publish
template<typename SERVICE> class BinderService { public:static status_t publish() {sp<IServiceManager> sm(defaultServiceManager());return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());}...... };? ? ? 這個函數(shù)定義在文件frameworks/base/include/binder/BinderService.h中。
? ? ? BinderService是一個模板類,它有一個模板參數(shù)SERVICE。當(dāng)BinderService類被SurfaceFlinger類繼承時,模板參數(shù)SERVICE的值就等于SurfaceFlinger。因此,BinderService類的靜態(tài)成員函數(shù)publish所執(zhí)行的操作就是創(chuàng)建一個SurfaceFlinger實例,用來作為系統(tǒng)的SurfaceFlinger服務(wù),并且將這個服務(wù)注冊到Service Manager中去,這樣系統(tǒng)中的其它組件或者進程就可以通過Service Manager來獲得SurfaceFlinger服務(wù)的Binder代理對象,進而使用它所提供的服務(wù)。Binder進程間通信機制中的服務(wù)對象的注冊過程可以參考Android系統(tǒng)進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文。
? ? ? 接下來,我們就繼續(xù)分析SurfaceFlinger服務(wù)的創(chuàng)建過程。
? ? ? Step 5. new SurfaceFlinger
SurfaceFlinger::SurfaceFlinger(): BnSurfaceComposer(), Thread(false),...... {init(); }? ? ? 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? 從前面Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)簡要介紹和學(xué)習(xí)計劃一文可以知道,SurfaceFlinger類繼承了BnSurfaceComposer類,而后者是一個實現(xiàn)了ISurfaceComposer接口的Binder本地對象類。此外,SurfaceFlinger類還繼承了Thread類,后者是用來創(chuàng)建一個線程的,這個線程就是我們在Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)簡要介紹和學(xué)習(xí)計劃一文中提到的UI渲染線程,它的線程執(zhí)行體函數(shù)為SurfaceFlinger類的成員函數(shù)threadLoop。后面在分析SurfaceFlinger服務(wù)渲染UI的過程時,我們再分析SurfaceFlinger類的成員函數(shù)threadLoop的實現(xiàn)。注意,在初始化SurfaceFlinger的父類Thread時,傳進去的參數(shù)為false,表示先不要將SurfaceFlinger服務(wù)的UI渲染線程啟動起來,等到后面再啟動。
? ? ? SurfaceFlinger服務(wù)在創(chuàng)建的過程中,會調(diào)用SurfaceFlinger類的成員函數(shù)init來執(zhí)行初始化的操作,接下來,我們就繼續(xù)分析它的實現(xiàn)。
? ? ? Step 6. SurfaceFlinger.init
void SurfaceFlinger::init() {LOGI("SurfaceFlinger is starting");// debugging stuff...char value[PROPERTY_VALUE_MAX];property_get("debug.sf.showupdates", value, "0");mDebugRegion = atoi(value);property_get("debug.sf.showbackground", value, "0");mDebug atoi(value);LOGI_IF(mDebugRegion, "showupdates enabled");LOGI_IF(mDebugBackground, "showbackground enabled"); }? ? ? ?這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? ?SurfaceFlinger類的成員函數(shù)init的實現(xiàn)很簡單,它分別獲得系統(tǒng)中兩個名稱為“debug.sf.showupdates”和“debug.sf.showbackground”的屬性的值,并且分別保存在SurfaceFlinger類的成員變量mDebugRegion和mDebugBackground中。這兩個成員變量是與調(diào)試相關(guān)的,我們不關(guān)心。
? ? ? ?這一步執(zhí)行完成之后,返回到前面的Step 4中,即BinderService類的靜態(tài)成員函數(shù)publish中,這時候在前面的Step 5中所創(chuàng)建的一個SurfaceFlinger實例就會被注冊到Service Manager中,這是通過調(diào)用Service Manager的Binder代理對象的成員函數(shù)addService來實現(xiàn)的。由于Service Manager的Binder代理對象的成員函數(shù)addService的第二個參數(shù)是一個類型為IBinder的強指針引用。從前面Android系統(tǒng)的智能指針(輕量級指針、強指針和弱指針)的實現(xiàn)原理分析一文可以知道,當(dāng)一個對象第一次被一個強指針引用時,那么這個對象的成員函數(shù)onFirstRef就會被調(diào)用。因此,接下來前面所創(chuàng)建的SurfaceFlinger實例的成員函數(shù)onFirstRef就會被調(diào)用,以便可以繼續(xù)執(zhí)行初始化操作。
? ? ? ?Step 7. SurfaceFlinger.onFirstRef
void SurfaceFlinger::onFirstRef() {run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);// Wait for the main thread to be done with its initializationmReadyToRunBarrier.wait(); }<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;"> </span></span>? ? ? 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? 函數(shù)首先調(diào)用從父類繼承下來的成員函數(shù)run來啟動一個名秒為“SurfaceFlinger”的線程,用來執(zhí)行UI渲染操作。這就是前面我們所說的UI渲染線程了。這個UI渲染線程創(chuàng)建完成之后,首先會調(diào)用SurfaceFlinger類的成員函數(shù)readyToRun來執(zhí)行一些初始化操作,接著再循環(huán)調(diào)用SurfaceFlinger類的成員函數(shù)threadLoop來作為線程的執(zhí)行體。
? ? ? mReadyToRunBarrier是SurfaceFlinger類的一個成員變量,它的類型是Barrier,用來描述一個屏障,是通過條件變量來實現(xiàn)的。我們可以把它看作是一個線程同步工具,即阻塞當(dāng)前線程,直到SurfaceFlinger服務(wù)的UI渲染線程執(zhí)行完成初始化操作為止。
? ? ? 接下來,我們就繼續(xù)分析SurfaceFlinger類的成員函數(shù)readyToRun的實現(xiàn),以便可以了解SurfaceFlinger服務(wù)的UI渲染線程的初始化過程。
? ? ? Step 8. SurfaceFlinger.oreadyToRun
? ? ? 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中,用來初始化SurfaceFlinger服務(wù)的UI渲染線程,我們分段來閱讀:
status_t SurfaceFlinger::readyToRun() {LOGI( "SurfaceFlinger's main thread ready to run. ""Initializing graphics H/W...");// we only support one display currentlyint dpy = 0;{// initialize the main displayGraphicPlane& plane(graphicPlane(dpy));DisplayHardware* const hw = new DisplayHardware(this, dpy);plane.setDisplayHardware(hw);}? ? ? ?這段代碼首先創(chuàng)建了一個DisplayHardware對象hw,用來描述設(shè)備的顯示屏,并且用這個DisplayHardware對象來初始化SurfaceFlinger類的成員變量mGraphicPlanes所描述的一個GraphicPlane數(shù)組的第一個元素。在DisplayHardware對象hw的創(chuàng)建過程中,會創(chuàng)建另外一個線程,用來監(jiān)控控制臺事件,即監(jiān)控硬件幀緩沖區(qū)的睡眠和喚醒事件。在后面一篇文章中介紹SurfaceFlinger服務(wù)是如何管理硬件幀緩沖區(qū)時,我們就會看到這個控制臺事件監(jiān)控線程的創(chuàng)建過程。
? ? ? 我們接著往下閱讀代碼:
// create the shared control-block mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap"); LOGE_IF(mServerHeap==0, "can't create shared memory dealer"); mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase()); LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); new(mServerCblk) surface_flinger_cblk_t;? ? ? 這段代碼首先創(chuàng)建了一塊大小為4096,即4KB的匿名共享內(nèi)存,接著將這塊匿名共享內(nèi)存結(jié)構(gòu)化為一個surface_flinger_cblk_t對象來訪問。這個surface_flinger_cblk_t對象就保存在SurfaceFlinger類的成員變量mServerCblk中。
? ? ? 這塊匿名共享內(nèi)存用來保存設(shè)備顯示屏的屬性信息,例如,寬度、高度、密度和每秒多少幀等信息,后面我們就會看到這塊匿名共享內(nèi)存的初始化過程。為什么會使用匿名共享內(nèi)存來保存設(shè)備顯示屏的屬性信息呢?這是為了方便將這些信息傳遞給系統(tǒng)中的其它進程訪問的。系統(tǒng)中的其它進程可以通過調(diào)用調(diào)用SurfaceFlinger服務(wù)的代理對象的成員函數(shù)getCblk來獲得這塊匿名共享內(nèi)存的內(nèi)容。
? ? ? 我們再接著往下閱讀代碼:
// initialize primary screen // (other display should be initialized in the same manner, but // asynchronously, as they could come and go. None of this is supported // yet). const GraphicPlane& plane(graphicPlane(dpy)); const DisplayHardware& hw = plane.displayHardware(); const uint32_t w = hw.getWidth(); const uint32_t h = hw.getHeight(); const uint32_t f = hw.getFormat(); hw.makeCurrent();? ? ? ?這段代碼首先獲得SurfaceFlinger類的成員變量mGraphicPlanes所描述的一個GraphicPlane數(shù)組的第一個元素plane,接著再設(shè)置它的寬度、長度和像素格式等作息,最后再調(diào)用它里面的一個DisplayHardware對象hw的成員函數(shù)makeCurrent來將它作為系統(tǒng)的主顯示屏。這個DisplayHardware對象hw是在前面第一段代碼中創(chuàng)建的,在創(chuàng)建的過程中,它會執(zhí)行一些初始化操作,這里將它設(shè)置為系統(tǒng)主顯示屏之后,后面就可以將系統(tǒng)的UI渲染在它上面了。在后面一篇文章中介紹SurfaceFlinger服務(wù)是如何管理硬件幀緩沖區(qū)時,我們再分析DisplayHardware類的成員函數(shù)makeCurrent的實現(xiàn)。
? ? ? 我們繼續(xù)往下閱讀代碼:
// initialize the shared control block mServerCblk->connected |= 1<<dpy; display_cblk_t* dcblk = mServerCblk->displays + dpy; memset(dcblk, 0, sizeof(display_cblk_t)); dcblk->w = plane.getWidth(); dcblk->h = plane.getHeight(); dcblk->format = f; dcblk->orientation = ISurfaceComposer::eOrientationDefault; dcblk->xdpi = hw.getDpiX(); dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); dcblk->density = hw.getDensity();? ? ? 這段代碼將系統(tǒng)主顯示屏的屬性信息保存在前面所創(chuàng)建的一塊匿名共享內(nèi)存中,以便可以將系統(tǒng)主顯示屏的屬性信息返回給系統(tǒng)中的其它進程訪問。
? ? ? 我們再繼續(xù)往下閱讀代碼:
// Initialize OpenGL|ES glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); glEnable(GL_SCISSOR_TEST); glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_CULL_FACE); const uint16_t g0 = pack565(0x0F,0x1F,0x0F); const uint16_t g1 = pack565(0x17,0x2f,0x17); const uint16_t textureData[4] = { g0, g1, g1, g0 }; glGenTextures(1, &mWormholeTexName); glBindTexture(GL_TEXTURE_2D, mWormholeTexName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(0, w, h, 0, 0, 1); ? ? ? ?這段代碼用來初始化OpenGL庫,因為SurfaceFlinger服務(wù)是通過OpenGL庫提供的API來渲染系統(tǒng)的UI的。這里我們就不詳細分析OpenGL庫的初始化過程中,有興趣的讀者可以參考官方網(wǎng)站:http://cn.khronos.org/。
? ? ? ?我們再繼續(xù)往下閱讀最后一段代碼:
LayerDim::initDimmer(this, w, h);mReadyToRunBarrier.open();/** We're now ready to accept clients...*/// start boot animationproperty_set("ctl.start", "bootanim");return NO_ERROR; }? ? ? ?這段代碼做了三件事情。
? ? ? ?第一件事情是調(diào)用LayerDim類的靜態(tài)成員函數(shù)initDimmer來初始化LayerDim類。LayerDim類是用來描述一個具有顏色漸變功能的Surface的,這種類型的Surface與普通的Surface不一樣,前者是在后者的基礎(chǔ)上創(chuàng)建和渲染的。
? ? ? ?第二件事情是調(diào)用SurfaceFlinger類的成員變量mReadyToRunBarrier所描述的一個屏障的成員函數(shù)open來告訴System進程的主線程,即在前面的Step 7中正在等待的線程,SurfaceFlinger服務(wù)的UI渲染線程已經(jīng)創(chuàng)建并且初始化完成了,這時候System進程的主線程就可以繼續(xù)向前執(zhí)行其它操作了。
? ? ? 第三件事情是調(diào)用函數(shù)property_set來設(shè)置系統(tǒng)中名稱為“ctl.start”的屬性,即將它的值設(shè)置為“bootanim”。從前面Android系統(tǒng)的開機畫面顯示過程分析一文可以知道,ctl.start是Android系統(tǒng)的一個控制屬性,當(dāng)它的值等于““bootanim”的時候,就表示要啟動Android系統(tǒng)的開機動畫。從這里就可以看出,當(dāng)我們看到Android系統(tǒng)的開機動畫時,就說明Android系統(tǒng)的SurfaceFlinger服務(wù)已經(jīng)啟動起來了。
? ? ? 至此,我們就分析完成SurfaceFlinger服務(wù)的啟動過程中了。在分析過程中,有兩個比較重要的知識點:第一個知識點是系統(tǒng)主顯示屏的創(chuàng)建和初始化過程,第二個知識點是UI渲染線程的執(zhí)行過程。在接下來的第一篇文章中,我們將詳細分析第一個知識點。在分析第一個知識點的過程中,會涉及到SurfaceFlinger服務(wù)的控制臺事件監(jiān)控線程的創(chuàng)建過程,因此,結(jié)合Step 2提到的Binder線程,以及Step 7提到的UI渲染線程,我們將在接下來的第二篇文章中,綜合描述SurfaceFlinger服務(wù)的線程協(xié)作模型。有了前面的基礎(chǔ)知識之后,在接下來的第三篇文章中,我們就將詳細分析第二個知識點。敬請關(guān)注!
老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關(guān)注!
轉(zhuǎn)載于:https://blog.51cto.com/shyluo/1242466
總結(jié)
以上是生活随笔為你收集整理的Android系统Surface机制的SurfaceFlinger服务的启动过程分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读《瓦尔登湖》,寂寞的共鸣
- 下一篇: Android Virtual Devi