Surface系统-1-应用与SurfaceFlinger建立链接

895 阅读6分钟

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。

                        -- 服装学院的IT男

以前做应用开发的时候一直对 SurfaceFlinger 感觉到陌生,甚至有点“畏惧”,觉得这是自己“不配接触”和学不会的领域。

最近花了点时间开始接触这块,整理出几篇记录,个人对 SurfaceFlinger 分为3块:

    1. Surface 系统 这部分简单的梳理出 Surface 系统的成员类构建流程,和简单梳理工作模型
    1. VSysnc 相关 个人觉得这块也是 SurfaceFlinger 中很重要的概念
    1. SurfaceFlinger 合成 这部分就是最后的核心了,目前还没有能力写出来,后续补充

当前系列为第一部分 Surface 系统的学习记录,分为5篇,由于不是从事这块,所以是通过查阅资料,书籍,加日志,trace,debug 等方式学习,内容不是很深入,肯定会有很多细节没有提到,不过对于主流程和出现了的内容肯定能保证正确性。

也希望职业生涯中能整理出更加详细深入的 SurfaceFlinger 系列文章。

适合人群: SurfaceFlinger 小白,应用开发,想简单了解 SurfaceFlinger 的同学

Surface系统-1-应用与SurfaceFlinger建立链接

Surface系统-2-SurfaceControl的创建(java层)

Surface系统-3-SurfaceControl的创建(native层)

Surface系统-4-BLASTBufferQueue和Surface的创建

Surface系统-5-BLASTBufferQueue工作流程概览

本篇同时已收录于Activity短暂的一生系列

正文

本篇介绍应用端是如何 SurfaceFlinger 建立链接,进行通信。 它们直接使用 SurfaceSession 通信,SurfaceSession 的创建时机发生在应用第一个窗口显示(addWindow流程)流程。

1 java 层 SurfaceSession 的创建

APP 端触发 addWindow 流程是通过匿名 Binder -> Session 这个类与 WindowManagerService 通信的。 在 WindowManagerService::addWindow 方法会先创建 WindowState 对象,此时也会将 Session 作为参数传递。 然后又会执行 执行 WindowState::attach 方法,这里会触发 SurfaceSession 的创建逻辑。 代码如下:

# WindowState
    // 客户端的 Session
    final Session mSession;

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
            super(service);
            mTmpTransaction = service.mTransactionFactory.get();
            // session 赋值
            mSession = s;
            ......
    }
    // 在 WMS 的addWindow 方法中马上会调用 WindowState::attach
    void attach() {
        ......
        if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked();
    }

继续看 Session::windowAddedLocked

# Session
    // 应用端和 SurfaceFlinger 通信的 Session
    SurfaceSession mSurfaceSession;

    void windowAddedLocked() {
        ......
        if (mSurfaceSession == null) {
            if (DEBUG) {
                Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
            }
            // 应用第一次添加窗口,需要创建 SurfaceSession
            mSurfaceSession = new SurfaceSession();
        }
        mNumWindow++;
    }

应用端和 WMS 通信是通过 Session ,现在看到 Session 下持有着一个与 SurfaceFlinger 通信的 SurfaceSession 对象。

# SurfaceSession
    // native的指针
    private long mNativeClient; // SurfaceComposerClient*

    /** Create a new connection with the surface flinger. */
    public final class SurfaceSession {
        mNativeClient = nativeCreate();
    }

java 层的 SurfaceSession 非常简单,构造方法也是触发 native 的创建,上层只保存对应的指针即可。 这里发现 google 加了个注释,表示对应 native 层的是一个 SurfaceComposerClient

所以上层的 SurfaceSession 本质就是一个底层的 SurfaceComposerClient 。

对应的 JNI 为 android_view_SurfaceSession.cpp

# android_view_SurfaceSession.cpp
    static jlong nativeCreate(JNIEnv* env, jclass clazz) {
        // 创建SurfaceComposerClient
        SurfaceComposerClient* client = new SurfaceComposerClient();
        // 增加对象的引用计数,防止在JNI方法执行结束后被释放
        client->incStrong((void*)nativeCreate);
        // 将SurfaceComposerClient对象的地址转换为jlong类型,并返回
        return reinterpret_cast<jlong>(client);
    }

2. native 层 SurfaceComposerClient 的创建

# SurfaceComposerClient.h
    class SurfaceComposerClient : public RefBase
    {
        friend class Composer;
    public:
        ......
        protected:
            int mStatus = NO_ERROR;
        ......
    private:
    ......
    virtual void onFirstRef();

        mutable     Mutex                       mLock;
                    // 状态
                    status_t                    mStatus; 
                    // 对应的 ISurfaceComposerClient 
                    sp<ISurfaceComposerClient>  mClient; 
    }
# SurfaceComposerClient.cpp

    SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT) {}
    1. SurfaceComposerClient 是 RefBase 子类
    1. 创建 SurfaceComposerClient 时设置了状态为:NO_INIT
    1. mClient 变量其实就是 SurfaceFlinger 的一个 BP 端

这里可以画出 SurfaceComposerClient 的类图:

类图-SurfaceComposerClient.png

因为 SurfaceComposerClient 是 RefBase 子类所以在对象构建的时候会触发 onFirstRef() 方法。

# SurfaceComposerClient.cpp

    void SurfaceComposerClient::onFirstRef() {
        // 1. 拿到 SurfaceComposerAIDL 服务
        sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
        if (sf != nullptr && mStatus == NO_INIT) {
            // 创建对象
            sp<ISurfaceComposerClient> conn;
            // 2. 创建对应 BP 代理
            binder::Status status = sf->createConnection(&conn);
            if (status.isOk() && conn != nullptr) {
                // 设置给当前变量
                mClient = conn;
                // 修改状态
                mStatus = NO_ERROR;
            }
        }
    }

这里分为2步:

    1. 拿到 SurfaceComposerAIDL 服务
    1. 创建 Clinet 赋值给 mClient

2.1 拿到 SurfaceComposerAIDL 服务

先看看 ComposerServiceAIDL 是什么

# ComposerServiceAIDL.h
    // 静态类
    class ComposerServiceAIDL : public Singleton<ComposerServiceAIDL> {
        // 保存SurfaceFlinger服务
        sp<gui::ISurfaceComposer> mComposerService;
        ......
        ComposerServiceAIDL();
        // 获取SurfaceFlinger服务
        bool connectLocked();
        ......
    public:
        // Get a connection to the Composer Service.  This will block until
        // a connection is established. Returns null if permission is denied.
        // 返回SurfaceFlinger服务
        static sp<gui::ISurfaceComposer> getComposerService();
    };
    1. ComposerServiceAIDL 是个单例类
    1. 定义了 mComposerService 保存 ISurfaceComposer
    1. 定义了 getComposerService 和 connectLocked 两个方法

ComposerServiceAIDL::getComposerService 方法定义如下

# SurfaceComposerClient.cpp

    /*static*/ sp<gui::ISurfaceComposer> ComposerServiceAIDL::getComposerService() {

        // 获取单例
        ComposerServiceAIDL& instance = ComposerServiceAIDL::getInstance();
        std::scoped_lock lock(instance.mMutex);
        // 如果对应的变量为空则执行 connectLocked 方法赋值
        if (instance.mComposerService == nullptr) {
            // 获取 binder 服务
            if (ComposerServiceAIDL::getInstance().connectLocked()) {
                ALOGD("ComposerServiceAIDL reconnected");
                WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);
            }
        }
        // 返回
        return instance.mComposerService;
    }

也就是说执行 ComposerServiceAIDL::getComposerService 目的就是返回其成员变量 mComposerService ,如果值为空就执行 ComposerServiceAIDL::connectLocked 进行赋值再返回。

那么需要看看 ComposerServiceAIDL::connectLocked 做了什么。

# SurfaceComposerClient.cpp

    bool ComposerServiceAIDL::connectLocked() {
        
        const String16 name("SurfaceFlingerAIDL");
        // 拿到 SurfaceFlingerAIDL 
        mComposerService = waitForService<gui::ISurfaceComposer>(name);
        if (mComposerService == nullptr) {
            return false; // fatal error or permission problem
        }
        ......
        return true;
    }

之前的获取的是服务是 "SurfaceFlinger" 新版本现在是 "SurfaceFlingerAIDL" 。 在 SurfaceFlinger 初始化的时候,这2个服务现在都是注册了的,注册的代码在 main_surfaceflinger.cpp 的 main 方法中执行。

现在单例类 ComposerServiceAIDL 下的 mComposerService 的值就是 SurfaceFlingerAIDL 服务了。

2.2 创建 Clinet

# SurfaceFlinger.cpp

    binder::Status SurfaceComposerAIDL::createConnection(sp<gui::ISurfaceComposerClient>* outClient) {

        // * 创建 Client
        const sp<Client> client = sp<Client>::make(mFlinger);
        if (client->initCheck() == NO_ERROR) {
            // 出参赋值
            *outClient = client; 
            return binder::Status::ok();
        } else {
            *outClient = nullptr;
            return binderStatusFromStatusT(BAD_VALUE);
        }
    }

做了一件事:创建匿名 Binder (Client) 返回给出参。 而且可以看到创建 Client 传递了 SurfaceFlinger 本身,那也就是说这个 Client 会持有真正是 SurfaceFlinger

这个 Client 是 ISurfaceComposerClient 的子类,具体代码如下:

# Client.h

class Client : public gui::BnSurfaceComposerClient {

    public:
        explicit Client(const sp<SurfaceFlinger>& flinger);
    ......
    private:
        ......
    // constant
    sp<SurfaceFlinger> mFlinger;
}

// 对应实现
# Client.cpp
    Client::Client(const sp<SurfaceFlinger>& flinger)
        : mFlinger(flinger)
    {......}

可知Client 是个 BN 服务,通过变量 mFlinger 持有 SurfaceFlinger

-Client 继承于 BnSurfaceComposerClient ,这种 Bn 开头的肯定是 Binder 本地端了,其父类是 ISurfaceComposerClient 如下:

# ISurfaceComposerClient.h

    class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {
    ......
    };

这里可以画出Client的类图:

类图-Client.png

所以可以确定这里创建的 Client 就是 SurfaceFlinger 的本地代理,也就是执行 SurfaceComposerAIDL::createConnection 方法是为了创建获取一个 SurfaceFlinger 的本地代理,用于后续应用端与 SurfaceFlinger 进行通信。而这个 Client 最终被赋值给 SurfaceComposerClient 的成员变量 mClient 。

3 小结

完整的调用链如下:

WindowManagerService::addWindow
    WindowState::init
    WindowState::attach
        Session::windowAddedLocked
            SurfaceSession::init 
                SurfaceSession::nativeCreate  -- 进入native层
                    SurfaceComposerClient::init -- android_view_SurfaceSession.cpp
                        SurfaceComposerClient::onFirstRef
                           ComposerServiceAIDL::getComposerService  -- 拿到 SurfaceComposerAIDL 服务
                              ComposerServiceAIDL::connectLocked 
                           SurfaceComposerAIDL::createConnection -- 创建 Client
                              Client::init  -- 传递 SF

客户端通过 SurfaceSession 来与 SurfaceFlinger 通信,只保留 SurfaceFlinger 的类图关系如下:

类图-SF关系.png

上层的 SurfaceSession 通过指针对应 native 层的 SurfaceComposerClient 间接持有 SurfaceFlinger 。

看到一篇博客绘制的完整类图如下:

类图-参考博客完整类图.png

出自于:blog.csdn.net/ukynho/arti…