【Android車載體系】四、Activity啟動到渲染到SurfaceFlinger流程

1 Activity的創(chuàng)建
??ActivityThread對于App進(jìn)程來說鹰晨,它是App的入口绿淋。此外ActivityThread還實(shí)現(xiàn)了創(chuàng)建主線程Looper闷畸、dump應(yīng)用內(nèi)存使用情況、獲取應(yīng)用包名等接口躬它。我們看看ActivityThread對于四大組件的作用腾啥,一句話概括,ActivityThread管理著四大組件的生命周期方法的調(diào)用冯吓。
??AMS服務(wù)進(jìn)程發(fā)出信號觸發(fā)App內(nèi)的ActivityThread通過反射實(shí)例化Activity并啟動Activity倘待,然后調(diào)用activity的attach()方法。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //...
   ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // 通過反射創(chuàng)建Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }


    //調(diào)用activity的attach方法
   activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);

    //...
}

然后開始了Activity的生命周期组贺。執(zhí)行onCreate()-onStart()-onResume()凸舵,onResume()執(zhí)行時(shí)頁面還不可見,onResume()完全執(zhí)行完之后的第一個(gè)VSYNC信號后頁面才可見失尖。onResume()將DecorView添加到WindowManagerGlobal中啊奄。

 @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        // ...
        // The window is now visible if it has been added, we are not
        // simply finishing, and we are not starting another activity.
        if (r.window == null && !a.mFinished && willBeVisible) {
            // 獲取到PhoneWindow和DecorView
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    // wm是WindowManagerImpl,
                    // 將DecorView add到App的單例WindowManagerGlobal中
                    wm.addView(decor, l);
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
    }


2 Activity的渲染
??Activity的attach()方法內(nèi)會初始化一個(gè)PhoneWindow對象(一個(gè)Activity對應(yīng)一個(gè)PhoneWindow對象)。
??Android系統(tǒng)AMS服務(wù)通過Binder與ActivityThread進(jìn)行通訊掀潮,ActivityThread將App內(nèi)所有Activity的頁面進(jìn)行管理菇夸。每個(gè)Activity中有一個(gè)對應(yīng)的PhoneWindow,每個(gè)PhoneWindow有對應(yīng)的DecorView仪吧,DecorView是布局內(nèi)layout的容器


image.png

3 WindowManagerGlobal
??每個(gè)App都只有一個(gè)WindowManagerGlobal對象庄新,App層的單例對象。ActivityThread通過WindowManagerImpl與WindowManagerGlobal實(shí)現(xiàn)通訊薯鼠,WindowManagerGlobal用于緩存所有頁面的PhoneWindow择诈、DecorView、ViewRootImpl等界面相關(guān)的數(shù)據(jù)出皇。
??WindowManagerGlobal內(nèi)部有addView()羞芍、removeView()等增刪查的所有方法都是通過遍歷的形式進(jìn)行邏輯處理,對外提供服務(wù)郊艘。
??主要給WMS提供管理所有View的便利荷科。由于與WMS是SystemServer進(jìn)程中唯咬,和App屬于不同進(jìn)程,所有使用的是Binder進(jìn)程間通訊步做。


image.png

4 WindowManagerService
??WindowManagerService窗口管理服務(wù)簡稱WMS副渴,一臺設(shè)備只有一個(gè)WMS。WMS管理所有App的全部PhoneWindow全度。
??WindowManagerGlobal利用Session跨進(jìn)程通過WMS與SurfaceFlinger通訊。根據(jù)每個(gè)不同的應(yīng)用一一對應(yīng)創(chuàng)建一個(gè)Surface斥滤,用于該應(yīng)用的渲染将鸵。
image.png

5 建立Surface和SurfaceFlinger連接

SurfaceFlinger服務(wù)主要實(shí)現(xiàn)了兩個(gè)Binder service用于App連接:
1) SurfaceFlinger
??派生自BnSurfaceComposer,是SurfaceFlinger程序的主服務(wù)佑颇,在程序啟動時(shí)就被構(gòu)造并添加到servicemanager顶掉,相關(guān)代碼在main_surfaceflinger.cpp,服務(wù)名為”SurfaceFlinger”
2) Client
??派生自BnSurfaceComposerClient挑胸,在SurfaceFlinger:: createConnection的時(shí)候被創(chuàng)建痒筒,對應(yīng)一個(gè)App Client連接

然后App啟動后,需要通過如下操作和SurfaceFlinger建立會話:
1)通過servicemanager獲取服務(wù)SurfaceFlinger的BpBinder茬贵,然后轉(zhuǎn)換成BpSurfaceComposer
2)調(diào)用BpsurfaceComposer.createConnection建立連接簿透,然后將返回的BpBinder轉(zhuǎn)換成BpSurfaceComposeClient

Android接著提供了兩個(gè)類用于簡化App端的操作,主要包括:
1)ComposerService
??單列類解藻,主要封裝跟SurfaceFlinger的連接老充,在構(gòu)造時(shí)調(diào)用connectlocaked成員函數(shù)連接
“SurfaceFlinger”然后將BpSurfaceCompose保存到成員變量mComposerService
2)SurfaceComposerClient
??封裝跟SurfaceFlinger建立會話連接的操作,在onFirstRef時(shí)調(diào)用createConnection建立
會話并將BpSurfaceComposerClient保存到成員變量mClient
3)Composer
??單列類螟左,主要封裝對Layer數(shù)據(jù)配置相關(guān)操作

接下去基于代碼來分析啡浊,封裝好后,App初始化連接很簡單

sp<SurfaceComposerClient> session= new SurfaceComposerClient();

就一行代碼胶背,接著看構(gòu)造函數(shù)

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT), mComposer(Composer::getInstance()){
}

獲取Composer單例對象并保存到mComposer巷嚣,由于SurfaceComposerClient派生自RefBase

class SurfaceComposerClient : public RefBase

所以在其構(gòu)造時(shí),會調(diào)用incStrong第一次增加強(qiáng)引用計(jì)數(shù)钳吟,同時(shí)onFirstRef會被調(diào)用

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

這個(gè)函數(shù)完成了連接的最終操作廷粒,先是通過ComposerService::getComposerService()生成
ComposeService單列,并調(diào)用其connectLocked連接SurfaceFlinger返回BpSurfaceComposer砸抛,接著調(diào)用sm->createConnection()創(chuàng)建會話并保存到mClient评雌。接下來看看SurfaceFlinger.createConnection的代碼

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        bclient = client;
    }
    return bclient;
}

很簡單,就是創(chuàng)建Client本地對象并返回

到這里直焙,App跟SurfaceFlinger的初始化連接已經(jīng)結(jié)束景东,接下去就是基于會話對象,創(chuàng)建繪圖表面了

6 流程圖


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奔誓,一起剝皮案震驚了整個(gè)濱河市斤吐,隨后出現(xiàn)的幾起案子搔涝,更是在濱河造成了極大的恐慌,老刑警劉巖和措,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庄呈,死亡現(xiàn)場離奇詭異,居然都是意外死亡派阱,警方通過查閱死者的電腦和手機(jī)诬留,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贫母,“玉大人文兑,你說我怎么就攤上這事∠倭樱” “怎么了绿贞?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長橘原。 經(jīng)常有香客問我籍铁,道長,這世上最難降的妖魔是什么趾断? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任拒名,我火速辦了婚禮,結(jié)果婚禮上歼冰,老公的妹妹穿的比我還像新娘靡狞。我一直安慰自己,他們只是感情好隔嫡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布甸怕。 她就那樣靜靜地躺著,像睡著了一般腮恩。 火紅的嫁衣襯著肌膚如雪梢杭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天秸滴,我揣著相機(jī)與錄音武契,去河邊找鬼。 笑死荡含,一個(gè)胖子當(dāng)著我的面吹牛咒唆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播释液,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼全释,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了误债?” 一聲冷哼從身側(cè)響起浸船,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤妄迁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后李命,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體登淘,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年封字,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了黔州。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阔籽,死狀恐怖辩撑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仿耽,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布各薇,位于F島的核電站项贺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏峭判。R本人自食惡果不足惜开缎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望林螃。 院中可真熱鬧奕删,春花似錦、人聲如沸疗认。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽横漏。三九已至谨设,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缎浇,已是汗流浹背扎拣。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留素跺,地道東北人二蓝。 一個(gè)月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像指厌,于是被迫代替她去往敵國和親刊愚。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容