Android系统Surface机制的SurfaceFlinger服务的启动过程分析
? ? ? ?在前面一篇文章中,我們簡要介紹了Android系統Surface機制中的SurfaceFlinger服務。SurfaceFlinger服務是在System進程中啟動的,并且負責統一管理設備的幀緩沖區。SurfaceFlinger服務在啟動的過程中,會創建兩個線程,其中一個線程用來監控控制臺事件,而另外一個線程用來渲染系統的UI。在本文中,我們就將詳細分析SurfaceFlinger服務的啟動過程。
? ? ? ?從前面Android系統進程Zygote啟動過程的源代碼分析一文可以知道,System進程是由Zygote進程啟動的,并且是以Java層的SystemServer類的靜態成員函數main為入口函數的。因此,接下來我們就從SystemServer類的靜態成員函數main開始,分析SurfaceFlinger服務的啟動過程,如圖1所示。
圖1 SurfaceFlinger服務的啟動過程
? ? ? SurfaceFlinger服務的啟動過程可以劃分為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);}...... }? ? ? ?這個函數定義在文件frameworks/base/services/java/com/android/server/SystemServer.java中。
? ? ? ?SystemServer類的靜態成員函數main首先將android_servers庫加載到System進程中來,接著調用另外一個靜態成員函數init1來啟動那些使用C++語言來實現的系統服務。
? ? ? ?SystemServer類的靜態成員函數init1是一個JNI方法,它是由C++層的函數android_server_SystemServer_init1來實現的,接下來我們就繼續分析它的實現。
? ? ? ?Step 2. SystemServer.init1
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz) {system_init(); }? ? ? 這個函數定義在文件frameworks/base/services/jni/com_android_server_SystemServer.cpp 中。
? ? ? SystemServer類的靜態成員函數init1調用另外一個函數system_init來啟動那些使用C++語言來實現的系統服務,它的實現在文件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; }? ? ? 函數首先獲得System進程中的一個ProcessState單例,并且保存在變量proc中,后面會通過調用它的成員函數supportsProcesses來判斷系統是否支持Binder進程間通信機制。我們知道,在Android系統中,每一個需要使用Binder進程間通信機制的進程內部都有一個ProcessState單例,它是用來和Binder驅動程序建立連接的,具體可以參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文。
? ? ? 函數接下來就檢查系統中是否存在一個名稱為“system_init.startsurfaceflinger”的屬性。如果存在的話,就將它的值獲取回來,并且保存在緩沖區proBuf中。如果不存在的話,那么函數property_get就會將緩沖區proBuf的值設置為“1”。當緩沖區proBuf的值等于“1”的時候,就表示需要在System進程中將SurfaceFlinger服務啟動起來,這是通過調用SurfaceFlinger類的靜態成員函數instantiate來實現的。
? ? ? 函數最后檢查系統是否支持Binder進程間通信機制。如果支持的話,那么接下來就會調用當前進程中的ProcessState單例的成員函數startThreadPool來啟動一個Binder線程池,并且調用當前線程中的IPCThreadState單例來將當前線程加入到前面所啟動的Binder線程池中去。從前面Android系統進程Zygote啟動過程的源代碼分析和Android應用程序進程啟動過程的源代碼分析兩篇文章可以知道,System進程前面在初始化運行時庫的過程中,已經調用過當前進程中的ProcessState單例的成員函數startThreadPool來啟動Binder線程池了,因此,這里其實只是將當前線程加入到這個Binder線程池中去。有了這個Binder線程池之后,SurfaceFlinger服務在啟動完成之后,就可以為系統中的其他組件或者進程提供服務了。
? ? ? 假設系統存在一個名稱為“system_init.startsurfaceflinger”的屬性,并且它的值等于“1”,接下來我們就繼續分析SurfaceFlinger類的靜態成員函數instantiate的實現,以便可以了解SurfaceFlinger服務的啟動過程。由于SurfaceFlinger類的靜態成員函數instantiate是從父類BinderService繼承下來的,因此,接下來我們要分析的實際上是BinderService類的靜態成員函數instantiate的實現。
? ? ? Step 3. BinderService.instantiate
template<typename SERVICE> class BinderService { public:......static void instantiate() { publish(); }...... };? ? ? 這個函數定義在文件frameworks/base/include/binder/BinderService.h中。
? ? ? BinderService類的靜態成員函數instantiate的實現很簡單,它只是調用BinderService類的另外一個靜態成員函數publish來繼續執行啟動SurfaceFlinger服務的操作。
? ? ? 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());}...... };? ? ? 這個函數定義在文件frameworks/base/include/binder/BinderService.h中。
? ? ? BinderService是一個模板類,它有一個模板參數SERVICE。當BinderService類被SurfaceFlinger類繼承時,模板參數SERVICE的值就等于SurfaceFlinger。因此,BinderService類的靜態成員函數publish所執行的操作就是創建一個SurfaceFlinger實例,用來作為系統的SurfaceFlinger服務,并且將這個服務注冊到Service Manager中去,這樣系統中的其它組件或者進程就可以通過Service Manager來獲得SurfaceFlinger服務的Binder代理對象,進而使用它所提供的服務。Binder進程間通信機制中的服務對象的注冊過程可以參考Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析一文。
? ? ? 接下來,我們就繼續分析SurfaceFlinger服務的創建過程。
? ? ? Step 5. new SurfaceFlinger
SurfaceFlinger::SurfaceFlinger(): BnSurfaceComposer(), Thread(false),...... {init(); }? ? ? 這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? 從前面Android系統Surface機制的SurfaceFlinger服務簡要介紹和學習計劃一文可以知道,SurfaceFlinger類繼承了BnSurfaceComposer類,而后者是一個實現了ISurfaceComposer接口的Binder本地對象類。此外,SurfaceFlinger類還繼承了Thread類,后者是用來創建一個線程的,這個線程就是我們在Android系統Surface機制的SurfaceFlinger服務簡要介紹和學習計劃一文中提到的UI渲染線程,它的線程執行體函數為SurfaceFlinger類的成員函數threadLoop。后面在分析SurfaceFlinger服務渲染UI的過程時,我們再分析SurfaceFlinger類的成員函數threadLoop的實現。注意,在初始化SurfaceFlinger的父類Thread時,傳進去的參數為false,表示先不要將SurfaceFlinger服務的UI渲染線程啟動起來,等到后面再啟動。
? ? ? SurfaceFlinger服務在創建的過程中,會調用SurfaceFlinger類的成員函數init來執行初始化的操作,接下來,我們就繼續分析它的實現。
? ? ? 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"); }? ? ? ?這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? ?SurfaceFlinger類的成員函數init的實現很簡單,它分別獲得系統中兩個名稱為“debug.sf.showupdates”和“debug.sf.showbackground”的屬性的值,并且分別保存在SurfaceFlinger類的成員變量mDebugRegion和mDebugBackground中。這兩個成員變量是與調試相關的,我們不關心。
? ? ? ?這一步執行完成之后,返回到前面的Step 4中,即BinderService類的靜態成員函數publish中,這時候在前面的Step 5中所創建的一個SurfaceFlinger實例就會被注冊到Service Manager中,這是通過調用Service Manager的Binder代理對象的成員函數addService來實現的。由于Service Manager的Binder代理對象的成員函數addService的第二個參數是一個類型為IBinder的強指針引用。從前面Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析一文可以知道,當一個對象第一次被一個強指針引用時,那么這個對象的成員函數onFirstRef就會被調用。因此,接下來前面所創建的SurfaceFlinger實例的成員函數onFirstRef就會被調用,以便可以繼續執行初始化操作。
? ? ? ?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>? ? ? 這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。
? ? ? 函數首先調用從父類繼承下來的成員函數run來啟動一個名秒為“SurfaceFlinger”的線程,用來執行UI渲染操作。這就是前面我們所說的UI渲染線程了。這個UI渲染線程創建完成之后,首先會調用SurfaceFlinger類的成員函數readyToRun來執行一些初始化操作,接著再循環調用SurfaceFlinger類的成員函數threadLoop來作為線程的執行體。
? ? ? mReadyToRunBarrier是SurfaceFlinger類的一個成員變量,它的類型是Barrier,用來描述一個屏障,是通過條件變量來實現的。我們可以把它看作是一個線程同步工具,即阻塞當前線程,直到SurfaceFlinger服務的UI渲染線程執行完成初始化操作為止。
? ? ? 接下來,我們就繼續分析SurfaceFlinger類的成員函數readyToRun的實現,以便可以了解SurfaceFlinger服務的UI渲染線程的初始化過程。
? ? ? Step 8. SurfaceFlinger.oreadyToRun
? ? ? 這個函數定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp文件中,用來初始化SurfaceFlinger服務的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);}? ? ? ?這段代碼首先創建了一個DisplayHardware對象hw,用來描述設備的顯示屏,并且用這個DisplayHardware對象來初始化SurfaceFlinger類的成員變量mGraphicPlanes所描述的一個GraphicPlane數組的第一個元素。在DisplayHardware對象hw的創建過程中,會創建另外一個線程,用來監控控制臺事件,即監控硬件幀緩沖區的睡眠和喚醒事件。在后面一篇文章中介紹SurfaceFlinger服務是如何管理硬件幀緩沖區時,我們就會看到這個控制臺事件監控線程的創建過程。
? ? ? 我們接著往下閱讀代碼:
// 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;? ? ? 這段代碼首先創建了一塊大小為4096,即4KB的匿名共享內存,接著將這塊匿名共享內存結構化為一個surface_flinger_cblk_t對象來訪問。這個surface_flinger_cblk_t對象就保存在SurfaceFlinger類的成員變量mServerCblk中。
? ? ? 這塊匿名共享內存用來保存設備顯示屏的屬性信息,例如,寬度、高度、密度和每秒多少幀等信息,后面我們就會看到這塊匿名共享內存的初始化過程。為什么會使用匿名共享內存來保存設備顯示屏的屬性信息呢?這是為了方便將這些信息傳遞給系統中的其它進程訪問的。系統中的其它進程可以通過調用調用SurfaceFlinger服務的代理對象的成員函數getCblk來獲得這塊匿名共享內存的內容。
? ? ? 我們再接著往下閱讀代碼:
// 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數組的第一個元素plane,接著再設置它的寬度、長度和像素格式等作息,最后再調用它里面的一個DisplayHardware對象hw的成員函數makeCurrent來將它作為系統的主顯示屏。這個DisplayHardware對象hw是在前面第一段代碼中創建的,在創建的過程中,它會執行一些初始化操作,這里將它設置為系統主顯示屏之后,后面就可以將系統的UI渲染在它上面了。在后面一篇文章中介紹SurfaceFlinger服務是如何管理硬件幀緩沖區時,我們再分析DisplayHardware類的成員函數makeCurrent的實現。
? ? ? 我們繼續往下閱讀代碼:
// 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();? ? ? 這段代碼將系統主顯示屏的屬性信息保存在前面所創建的一塊匿名共享內存中,以便可以將系統主顯示屏的屬性信息返回給系統中的其它進程訪問。
? ? ? 我們再繼續往下閱讀代碼:
// 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服務是通過OpenGL庫提供的API來渲染系統的UI的。這里我們就不詳細分析OpenGL庫的初始化過程中,有興趣的讀者可以參考官方網站:http://cn.khronos.org/。
? ? ? ?我們再繼續往下閱讀最后一段代碼:
LayerDim::initDimmer(this, w, h);mReadyToRunBarrier.open();/** We're now ready to accept clients...*/// start boot animationproperty_set("ctl.start", "bootanim");return NO_ERROR; }? ? ? ?這段代碼做了三件事情。
? ? ? ?第一件事情是調用LayerDim類的靜態成員函數initDimmer來初始化LayerDim類。LayerDim類是用來描述一個具有顏色漸變功能的Surface的,這種類型的Surface與普通的Surface不一樣,前者是在后者的基礎上創建和渲染的。
? ? ? ?第二件事情是調用SurfaceFlinger類的成員變量mReadyToRunBarrier所描述的一個屏障的成員函數open來告訴System進程的主線程,即在前面的Step 7中正在等待的線程,SurfaceFlinger服務的UI渲染線程已經創建并且初始化完成了,這時候System進程的主線程就可以繼續向前執行其它操作了。
? ? ? 第三件事情是調用函數property_set來設置系統中名稱為“ctl.start”的屬性,即將它的值設置為“bootanim”。從前面Android系統的開機畫面顯示過程分析一文可以知道,ctl.start是Android系統的一個控制屬性,當它的值等于““bootanim”的時候,就表示要啟動Android系統的開機動畫。從這里就可以看出,當我們看到Android系統的開機動畫時,就說明Android系統的SurfaceFlinger服務已經啟動起來了。
? ? ? 至此,我們就分析完成SurfaceFlinger服務的啟動過程中了。在分析過程中,有兩個比較重要的知識點:第一個知識點是系統主顯示屏的創建和初始化過程,第二個知識點是UI渲染線程的執行過程。在接下來的第一篇文章中,我們將詳細分析第一個知識點。在分析第一個知識點的過程中,會涉及到SurfaceFlinger服務的控制臺事件監控線程的創建過程,因此,結合Step 2提到的Binder線程,以及Step 7提到的UI渲染線程,我們將在接下來的第二篇文章中,綜合描述SurfaceFlinger服務的線程協作模型。有了前面的基礎知識之后,在接下來的第三篇文章中,我們就將詳細分析第二個知識點。敬請關注!
老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關注!
轉載于:https://blog.51cto.com/shyluo/1242466
總結
以上是生活随笔為你收集整理的Android系统Surface机制的SurfaceFlinger服务的启动过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读《瓦尔登湖》,寂寞的共鸣
- 下一篇: 大叔手记(10):别再让面试官问你单例