美文网首页
【Android车载体系】四、Activity启动到渲染到Sur

【Android车载体系】四、Activity启动到渲染到Sur

作者: Johnson_Coding | 来源:发表于2024-05-09 14:21 被阅读0次

    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的容器


    image.png

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


    image.png
    4 WindowManagerService
      WindowManagerService窗口管理服务简称WMS,一台设备只有一个WMS。WMS管理所有App的全部PhoneWindow。
      WindowManagerGlobal利用Session跨进程通过WMS与SurfaceFlinger通讯。根据每个不同的应用一一对应创建一个Surface,用于该应用的渲染。
    image.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 流程图


    image.png

    相关文章

      网友评论

          本文标题:【Android车载体系】四、Activity启动到渲染到Sur

          本文链接:https://www.haomeiwen.com/subject/faqsfjtx.html