4 Activity啟動到渲染到SurfaceFlinger流程

1 Activity的創(chuàng)建

ActivityThread對于App進程來說膊升,它是App的入口。此外ActivityThread還實現(xiàn)了創(chuàng)建主線程Looper铸磅、dump應(yīng)用內(nèi)存使用情況信卡、獲取應(yīng)用包名等接口。我們看看ActivityThread對于四大組件的作用煮剧,一句話概括,ActivityThread管理著四大組件的生命周期方法的調(diào)用将鸵。
??AMS服務(wù)進程發(fā)出信號觸發(fā)App內(nèi)的ActivityThread通過反射實例化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í)行時頁面還不可見,onResume()完全執(zhí)行完之后的第一個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)會初始化一個PhoneWindow對象(一個Activity對應(yīng)一個PhoneWindow對象)。
??Android系統(tǒng)AMS服務(wù)通過Binder與ActivityThread進行通訊簿透,ActivityThread將App內(nèi)所有Activity的頁面進行管理移袍。每個Activity中有一個對應(yīng)的PhoneWindow,每個PhoneWindow有對應(yīng)的DecorView老充,DecorView是布局內(nèi)layout的容器


9eeff571555d46b6a88636546eec6058.png

3 WindowManagerGlobal

每個App都只有一個WindowManagerGlobal對象葡盗,App層的單例對象。ActivityThread通過WindowManagerImpl與WindowManagerGlobal實現(xiàn)通訊啡浊,WindowManagerGlobal用于緩存所有頁面的PhoneWindow觅够、DecorView、ViewRootImpl等界面相關(guān)的數(shù)據(jù)虫啥。
??WindowManagerGlobal內(nèi)部有addView()蔚约、removeView()等增刪查的所有方法都是通過遍歷的形式進行邏輯處理,對外提供服務(wù)涂籽。
??主要給WMS提供管理所有View的便利。由于與WMS是SystemServer進程中砸抛,和App屬于不同進程评雌,所有使用的是Binder進程間通訊。


440a278717dd49bc93d23a5c3c939da1.png

4 WindowManagerService

WindowManagerService窗口管理服務(wù)簡稱WMS直焙,一臺設(shè)備只有一個WMS景东。WMS管理所有App的全部PhoneWindow。
??WindowManagerGlobal利用Session跨進程通過WMS與SurfaceFlinger通訊奔誓。根據(jù)每個不同的應(yīng)用一一對應(yīng)創(chuàng)建一個Surface斤吐,用于該應(yīng)用的渲染搔涝。


f9f469b8516b408d8a462f238a099ccf.png

5 建立Surface和SurfaceFlinger連接

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

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

Android接著提供了兩個類用于簡化App端的操作,主要包括:
1)ComposerService
??單列類腺劣,主要封裝跟SurfaceFlinger的連接绿贞,在構(gòu)造時調(diào)用connectlocaked成員函數(shù)連接
“SurfaceFlinger”然后將BpSurfaceCompose保存到成員變量mComposerService
2)SurfaceComposerClient
??封裝跟SurfaceFlinger建立會話連接的操作,在onFirstRef時調(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)造時,會調(diào)用incStrong第一次增加強引用計數(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;
        }
    }
}

這個函數(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 流程圖


54acc9f4c14c4741b4636ff59c42d5dd.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秸滴,一起剝皮案震驚了整個濱河市武契,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荡含,老刑警劉巖咒唆,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異释液,居然都是意外死亡全释,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門误债,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浸船,“玉大人妄迁,你說我怎么就攤上這事±蠲” “怎么了登淘?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長项戴。 經(jīng)常有香客問我形帮,道長,這世上最難降的妖魔是什么周叮? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任辩撑,我火速辦了婚禮,結(jié)果婚禮上仿耽,老公的妹妹穿的比我還像新娘合冀。我一直安慰自己,他們只是感情好项贺,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布君躺。 她就那樣靜靜地躺著,像睡著了一般开缎。 火紅的嫁衣襯著肌膚如雪棕叫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天奕删,我揣著相機與錄音俺泣,去河邊找鬼。 笑死完残,一個胖子當著我的面吹牛伏钠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谨设,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼熟掂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扎拣?” 一聲冷哼從身側(cè)響起赴肚,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎二蓝,沒想到半個月后尊蚁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡侣夷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仑乌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片百拓。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡琴锭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衙传,到底是詐尸還是另有隱情决帖,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布蓖捶,位于F島的核電站地回,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俊鱼。R本人自食惡果不足惜刻像,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望并闲。 院中可真熱鬧细睡,春花似錦、人聲如沸帝火。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽犀填。三九已至蠢壹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間九巡,已是汗流浹背图贸。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留比庄,地道東北人求妹。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像佳窑,于是被迫代替她去往敵國和親制恍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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