編輯:關於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());
sp proc(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) {
sp sm(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);
sp t = 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——Material Design詳解(視圖和陰影)
Android L: 昨天凌晨Google剛剛確認Android L就是Android Lollipop(5.0)
Android自定義控件之仿優酷菜單
去年的優酷HD版有過這樣一種菜單,如下圖:應用打開之後,先是三個弧形的三級菜單,點擊實體鍵menu之後,這三個菜單依次旋轉退出,再點擊實體鍵menu之後,一級菜單會旋轉進
Android 關於“NetworkOnMainThreadException”問題的原因分析及解決辦法
網絡收集的原因如下,以及解決辦法:我補充總結一下:解決辦法一:在操作網絡類(socket連接)的activity的protected void onCreate(Bund
Android 自定義 ViewPager 打造千變萬化的圖片切換效果
記得第一次見到ViewPager這個控件,瞬間愛不釋手,做東西的主界面通通ViewPager,以及圖片切換也拋棄了ImageSwitch之類的,開始讓Vie