編輯:關於Android編程
這周繼續我的Blog,前面幾篇博文簡單的介紹了閱讀Android FW的源碼所需要的基礎知識,主要和C++相關。從這篇博文開始將會和大家一起學習並總結SurfaceFlinger模塊在Android中的相關內容,本文主要描述的是SurfaceFlinger的詳細啟動流程。
1.SurfaceFlinger在哪裡啟動?
在android系統中一個核心的Service都有ServiceManager管理,核心Service啟動一般是在SystemServer來啟動,但是比較重要的Service會在Zygote啟動前,由init進程來負責直接啟動。故SurfaceFlinger作為一個核心Service,一般有下面2種啟動方式。
a.在systemserver中如何啟動。
源碼目錄/android/frameworks/base/cmds/system_server/library/system_init.cpp.
extern C status_t system_init() { ALOGI(Entered system_init()); spproc(ProcessState::self()); sp sm = defaultServiceManager(); ALOGI(ServiceManager: %p , sm.get()); sp grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get(system_init.startsurfaceflinger, propBuf, 1); if (strcmp(propBuf, 1) == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } property_get(system_init.startsensorservice, propBuf, 1); if (strcmp(propBuf, 1) == 0) { // Start the sensor service SensorService::instantiate(); } ...... }
在這裡可以看到在systemserver的啟動過程中,property_get通過獲取system_init.startsurfaceflinger的屬性值,這個屬性值一般在init.rc中進配置,如果該數值為0,則賦值propBuf=1,故以此會使用system_init中來啟動SF。
b.相對比上面的啟動,另一種啟動就是直接像ServiceManager一樣,作為init進程中的一個Service來啟動。
在init.rc中添加如下配置代碼:
# Set this property so surfaceflinger is not started by system_init
setprop system_init.startsurfaceflinger 0
啟動SurfaceFlinger的過程:
469 service surfaceflinger /system/bin/surfaceflinger 470 class main 471 user system 472 group graphics drmrpc 473 onrestart restart zygote 474
對於Service如何啟動,可以查看Blog:android系統啟動流程啟動畫面學習之init和init.rc分析的相關內容即可理解。
2.以第二種方式啟動來進一步分析SF,看看SurfaceFlinger的main函數源碼。
路徑:android/frameworks/native/cmds/surfaceflinger/main_surfaceflinger.cpp
int main(int argc, char** argv) { SurfaceFlinger::publishAndJoinThreadPool(true); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); return 0; }
要開始結束SurfaceFlinger的函數處理過程時,有必要先進SF的基本UML圖提出來,如下所示:
step1: 調用publishAndJoinThreadPool函數:
該函數是C++裡一個帶默認參數的函數的,這裡傳入的參數的true。
static void publishAndJoinThreadPool(bool allowIsolated = false) { spsm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
這裡會涉及到和ServerManger的交互,變量sm是SM在當前進程的一個代理proxy,用於Binder驅動的交互,而addService正是將SurfaceFlinger做為一個核心的系統服務注冊到SM當中。隨後就是當前進程由ProcessState通過依次調用會新run起來一個thread如下所示,Poolthread繼承與Thread類,故一旦run起來就運行thread的run函數故而依舊前面介紹的thread類是依次會執行PoolThread類的readyToRun和threadLoop;
void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { int32_t s = android_atomic_add(1, &mThreadPoolSeq); char buf[16]; snprintf(buf, sizeof(buf), Binder_%X, s); ALOGV(Spawning new pooled thread, name=%s , buf); spt = new PoolThread(isMain); t->run(buf); } }
在對應的threadLoop裡面可以找到IPCThreadState::self()->joinThreadPool(mIsMain);即新建一個IPCThreadState進程間通信的線程狀態類,該類的函數joinThreadPool
即是與Binder驅動交互的接口,核心是和內核Binder驅動進行talkWithDriver()以及executeCommand(), 因為當前的SurfaceFlinger已經進入了正常的運行狀態。
當然在本主線程也會 調用IPCThreadState::self()->joinThreadPool();進行Binder間的通信,確保通信的穩定性。
step2: 回歸SurfaceFlinger對象的創建
作為繼承了public BinderService
sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
new SERVICE() = new SurfaceFlinger().從這裡該進入SF的創建和相關初始化了
SF類的定義和初始化成員函數的文件目錄:
源文件/android/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp;頭文件/android/frameworks/native/services/surfaceflinger/SurfaceFlinger.h;
如下是SF的狗構造函數,首先對基類BnSurfaceComposer、Thread進行初始化
SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), mRepaintEverything(0), mBootTime(systemTime()), mVisibleRegionsDirty(false), mHwWorkListDirty(false), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), mDebugDisableTransformHint(0), mDebugInSwapBuffers(0), mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false)
這裡乘熱打鐵來看thread類,很容易知道必然有地方會run起thread類所屬的線程,好吧接下去揭開謎底所在,來看這個:
void SurfaceFlinger::onFirstRef() { mEventQueue.init(this); run(SurfaceFlinger, PRIORITY_URGENT_DISPLAY);//啟動一個新的thread線程,調用thread類的run函數 // Wait for the main thread to be done with its initialization mReadyToRunBarrier.wait();//等待線程完成相關的初始化 }
OK這個onFirstRef似乎特別熟悉,的確在Android FrameWork中的SP、RefBase、weakref_impl,Thread類裡面詳細說明了他的由來,其實也就是和RefBase的關系特別密切。一般new一個SP的模板類,會最終調用該類對象對Refase重載的onFirstRef()。這裡就可以看到進行了mEventQueue(在介紹SF的消息機制時再深入分析)的初始化以及啟動一個run函數。故最終調用SF的readyToRun和threadLoop。
Android L: 昨天凌晨Google剛剛確認Android L就是Android Lollipop(5.0)
去年的優酷HD版有過這樣一種菜單,如下圖:應用打開之後,先是三個弧形的三級菜單,點擊實體鍵menu之後,這三個菜單依次旋轉退出,再點擊實體鍵menu之後,一級菜單會旋轉進
網絡收集的原因如下,以及解決辦法:我補充總結一下:解決辦法一:在操作網絡類(socket連接)的activity的protected void onCreate(Bund
記得第一次見到ViewPager這個控件,瞬間愛不釋手,做東西的主界面通通ViewPager,以及圖片切換也拋棄了ImageSwitch之類的,開始讓Vie