4 Activity启动到渲染到SurfaceFlinger流程

1 Activity的创建

ActivityThread对于App进程来说,它是App的入口。此外ActivityThread还实现了创建主线程Looper、dump应用内存使用情况、获取应用包名等接口。我们看看ActivityThread对于四大组件的作用,一句话概括,ActivityThread管理着四大组件的生命周期方法的调用。
  AMS服务进程发出信号触发App内的ActivityThread通过反射实例化Activity并启动Activity,然后调用activity的attach()方法。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //...
   ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // 通过反射创建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);
            }
        }


    //调用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的生命周期。执行onCreate()-onStart()-onResume(),onResume()执行时页面还不可见,onResume()完全执行完之后的第一个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()方法内会初始化一个PhoneWindow对象(一个Activity对应一个PhoneWindow对象)。
  Android系统AMS服务通过Binder与ActivityThread进行通讯,ActivityThread将App内所有Activity的页面进行管理。每个Activity中有一个对应的PhoneWindow,每个PhoneWindow有对应的DecorView,DecorView是布局内layout的容器


9eeff571555d46b6a88636546eec6058.png

3 WindowManagerGlobal

每个App都只有一个WindowManagerGlobal对象,App层的单例对象。ActivityThread通过WindowManagerImpl与WindowManagerGlobal实现通讯,WindowManagerGlobal用于缓存所有页面的PhoneWindow、DecorView、ViewRootImpl等界面相关的数据。
  WindowManagerGlobal内部有addView()、removeView()等增删查的所有方法都是通过遍历的形式进行逻辑处理,对外提供服务。
  主要给WMS提供管理所有View的便利。由于与WMS是SystemServer进程中,和App属于不同进程,所有使用的是Binder进程间通讯。


440a278717dd49bc93d23a5c3c939da1.png

4 WindowManagerService

WindowManagerService窗口管理服务简称WMS,一台设备只有一个WMS。WMS管理所有App的全部PhoneWindow。
  WindowManagerGlobal利用Session跨进程通过WMS与SurfaceFlinger通讯。根据每个不同的应用一一对应创建一个Surface,用于该应用的渲染。


f9f469b8516b408d8a462f238a099ccf.png

5 建立Surface和SurfaceFlinger连接

SurfaceFlinger服务主要实现了两个Binder service用于App连接:
1) SurfaceFlinger
  派生自BnSurfaceComposer,是SurfaceFlinger程序的主服务,在程序启动时就被构造并添加到servicemanager,相关代码在main_surfaceflinger.cpp,服务名为”SurfaceFlinger”
2) Client
  派生自BnSurfaceComposerClient,在SurfaceFlinger:: createConnection的时候被创建,对应一个App Client连接

然后App启动后,需要通过如下操作和SurfaceFlinger建立会话:
1)通过servicemanager获取服务SurfaceFlinger的BpBinder,然后转换成BpSurfaceComposer
2)调用BpsurfaceComposer.createConnection建立连接,然后将返回的BpBinder转换成BpSurfaceComposeClient

Android接着提供了两个类用于简化App端的操作,主要包括:
1)ComposerService
  单列类,主要封装跟SurfaceFlinger的连接,在构造时调用connectlocaked成员函数连接
“SurfaceFlinger”然后将BpSurfaceCompose保存到成员变量mComposerService
2)SurfaceComposerClient
  封装跟SurfaceFlinger建立会话连接的操作,在onFirstRef时调用createConnection建立
会话并将BpSurfaceComposerClient保存到成员变量mClient
3)Composer
  单列类,主要封装对Layer数据配置相关操作

接下去基于代码来分析,封装好后,App初始化连接很简单

sp<SurfaceComposerClient> session= new SurfaceComposerClient();

就一行代码,接着看构造函数

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

获取Composer单例对象并保存到mComposer,由于SurfaceComposerClient派生自RefBase

class SurfaceComposerClient : public RefBase

所以在其构造时,会调用incStrong第一次增加强引用计数,同时onFirstRef会被调用

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

这个函数完成了连接的最终操作,先是通过ComposerService::getComposerService()生成
ComposeService单列,并调用其connectLocked连接SurfaceFlinger返回BpSurfaceComposer,接着调用sm->createConnection()创建会话并保存到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;
}

很简单,就是创建Client本地对象并返回

到这里,App跟SurfaceFlinger的初始化连接已经结束,接下去就是基于会话对象,创建绘图表面了

6 流程图


54acc9f4c14c4741b4636ff59c42d5dd.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容