Android 12(S) 图像显示系统 - 应用建立和SurfaceFlinger的沟通桥梁(三) - 二的次方 - 博客园

Android 12(S) 图像显示系统 - 应用建立和SurfaceFlinger的沟通桥梁(三)

1 前言

上一篇文章中我们已经创建了一个Native示例应用,从使用者的角度了解了图形显示系统API的基本使用,从这篇文章开始我们将基于这个示例应用深入图形显示系统API的内部实现逻辑,分析运作流程。

本篇将聚焦应用和SurfaceFlinger的活动,即应用是如何与SurfaceFlinger这个服务建立连接并进行通信的。让我们开始吧!

注:本篇涉及的代码位置:

/frameworks/native/libs/gui/

/frameworks/native/libs/gui/include/gui/

/frameworks/native/libs/gui/include/private/gui/

/frameworks/native/services/surfaceflinger/

 


2 应用和SurfaceFlinger的通信

应用运行一开始便首先要去创建一个Native Surface,此时即开始了与SurfaceFlinger的互动,分步来看创建Surface的过程:

  • SurfaceFlinger系统服务的Binder RPC架构

在分析详细的代码前,我想先展示一下 SurfaceFlinger系统服务的Binder RPC架构,其中涉及哪些类?哪些接口?它们之间的关系如何?在宏观上去对这些对象的关系做了解,有助于我们理解具体的代码分析。

先看一张基本的类图:

SurfaceFlinger作为典型的Binder系统服务,遵循Binder服务设计的一般原则:

Interface接口:ISurfaceComposer 、ISurfaceComposerClient

Bp客户端:BpSurfaceComposer、BpSurfaceComposerClient

Bn服务端:BnSurfaceComposer、BnSurfaceComposerClient

服务实现:SurfaceFlinger、Client

具体Binder的原理在此就不展开讲了,相信你在网络上可以搜索到很多优秀的讲解文章。


这里请先留意两点:

  1. ComposerService中有成员mComposerService,它代表了SurfaceFlinger服务的代理客户端;
  2. SurfaceComposerClient中有成员mClient,它代表了SurfaceFlinger服务进程中的Client的代理客户端(这里应该是涉及所谓的匿名Binder的概念)

推荐两篇博文:https://blog.csdn.net/lewif/article/details/50696510

                        https://my.oschina.net/u/3897543/blog/4750360


 

  • 创建SurfaceComposerClient并建立与SurfaceFlinger的连接

应用首先去创建SurfaceComposerClient对象,透过这个对象建立和SurfaceFlinger的连接并进行后续的互动:


sp<SurfaceComposerClient> surfaceComposerClient = new SurfaceComposerClient;
status_t err = surfaceComposerClient->initCheck();
if (err != NO_ERROR) {
    ALOGD("SurfaceComposerClient::initCheck error: %#x\n", err);
    return;
}

SurfaceComposerClient 的定义非常简单,继承RefBase,其中成员mClient持有远程服务的代理客户端,基本操作都是以它作为桥梁传递到SurfaceFlinger的,如下:


// /frameworks/native/libs/gui/include/gui/SurfaceComposerClient.h
class SurfaceComposerClient : public RefBase
{
public:
                SurfaceComposerClient();
                SurfaceComposerClient(const sp<ISurfaceComposerClient>& client);
    virtual     ~SurfaceComposerClient();
    ......
private:
                sp<ISurfaceComposerClient>  mClient;
}

SurfaceComposerClient 的构造函数也十分简单,进行mStatus的初始化,其中mClient也可以外部传递进来初始值,或在onFirstRef的时候进行设置:


// /frameworks/native/libs/gui/SurfaceComposerClient.cpp
SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
    : mStatus(NO_ERROR), mClient(client)
{
}

对象第一次引用onFirstRef的时候,才真正的去建立和SurfaceFlinger的连接:


// /frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

先看一下ComposerService的定义,这是一个Singleton,它持有SurfaceFlinger服务的代理客户端:sp<ISurfaceComposer> mComposerService


// /frameworks/native/libs/gui/include/private/gui/ComposerService.h
// This holds our connection to the composer service (i.e. SurfaceFlinger).

class ComposerService : public Singleton<ComposerService>
{
    sp<ISurfaceComposer> mComposerService;  // composer service的代理端
    sp<IBinder::DeathRecipient> mDeathObserver;
    Mutex mLock;

    ComposerService();
    bool connectLocked();
    void composerServiceDied();
    friend class Singleton<ComposerService>;
public:
    // Get a connection to the Composer Service.  This will block until
    // a connection is established. Returns null if permission is denied.
    static sp<ISurfaceComposer> getComposerService();
};

ComposerService在构建时,调用connectLocked获取SurfaceFlinger(composer service)服务的代理客户端:


//  /frameworks/native/libs/gui/SurfaceComposerClient.cpp

// ComposerService的构造函数,调用到connectLocked去创建和SurfaceFlinger的连接
ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked();
}

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name); // 通过ServiceManager去获取SurfaceFlinger这个系统服务
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
    return true;
}

上面connectLocked方法可以看到调用waitForService去向ServiceManager请求名称为SurfaceFlinger的系统服务,成功后就取得了SurfaceFlinger这个系统服务的远程代理客户端,之后就可以透过这个代理跨进程与SurfaceFlinger进行互动了。

DeathObserver是一个监听器,用于监听远程服务的状态,当远程服务异常退出Died,触发该监听器,进而呼叫到mComposerService.composerServiceDied()做一些清理保护


void ComposerService::composerServiceDied()
{
    Mutex::Autolock _l(mLock);
    mComposerService = nullptr;
    mDeathObserver = nullptr;
}

再回到SurfaceComposerClient::onFirstRef方法中,透过ComposerService::getComposerService()获取到SurfaceFlinger服务的代理客户端后,接下来就是去初始化mClient了


// /frameworks/native/libs/gui/SurfaceComposerClient.cpp

sp<ISurfaceComposerClient> conn;
conn = sf->createConnection();
if (conn != nullptr) {
	mClient = conn;
	mStatus = NO_ERROR;
}

进而调用到了


// /frameworks/native/libs/gui/include/gui/ISurfaceComposer.h

/*
 * Create a connection with SurfaceFlinger.
 */
virtual sp<ISurfaceComposerClient> createConnection() = 0;

createConnection是一个典型的Binder C/S架构下的跨进程调用,傻瓜式的理解调用流程:


// 客户端端发送信息
BpSurfaceComposer::createConnection() {
	remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
    return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}

==>

// 服务端接收到信息
status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                    uint32_t flags) {
    status_t credentialCheck = CheckTransactCodeCredentials(code);
    if (credentialCheck != OK) {
        return credentialCheck;
    }

    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
  
  	....

}

BnSurfaceComposer::onTransact() {
        case CREATE_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> b = IInterface::asBinder(createConnection());
            reply->writeStrongBinder(b);
            return NO_ERROR;
        }
}

==>

// 服务具体实现
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    const sp<Client> client = new Client(this);
    return client->initCheck() == NO_ERROR ? client : nullptr;
}

SurfaceFlinger::createConnection方法中创建一个Client对象,Client继承自BnSurfaceComposerClient实现ISurfaceComposerClient接口,可以利用Binder机制传递回客户端。而且Client对象中含有SurfaceFlinger成员,这样SurfaceComposerClient::mClient就和SurfaceFlinger建立了连接。


Tips:

SurfaceFlinger进程中创建的Client对象,透过Binder IPC机制返回到了应用进程中,这里的具体原理感兴趣的可以研究下IInterface::asBinder /  writeStrongBinder / readStrongBinder / interface_cast 这些方法。这里我们就傻瓜式的理解为SurfaceComposerClient::mClient是SurfaceFlinger进程中Client对象的代理客户端,使用SurfaceComposerClient::mClient就可以呼叫到SurfaceFlinger进程中Client对象的方法。

 


前面的讲解看起来纷纷扰扰,简单的、抽象的概括就是如下图所示:

  1. 创建SurfaceComposerClient对象;
  2. SurfaceComposerClient::onFirstRef方法中透过ComposerService::getComposerService()获取到SurfaceFlinger服务的代理客户端;
  3. 调用SurfaceFlinger服务的代理客户端的createConnection方法,进而跨进程调用到SurfaceFlinger::createConnection方法;
  4. SurfaceFlinger::createConnection方法中创建一个Client对象,并透过Binder返回给SurfaceComposerClient::mClient;

之后再调用SurfaceComposerClient中的方法时就可以通过mClient这个客户端去呼叫到SurfaceFlinger服务的功能了

结合上面的类图和下面的时序图,大概总结如下


 

3 小结

这一篇文章中讲解了应用进程中如何建立和SurfaceFlinger沟通的桥梁,即得到SurfaceFlinger的远程代理客户端,之后就通过这个代理客户端向SurfaceFlinger发送请求或获取信息。

 


必读:
Android 12(S) 图像显示系统 - 开篇

 


 

 

心有猛虎,细嗅蔷薇,生活就该无惧无悔

 

作者: 二的次方
本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利
posted on 2022-01-21 09:30  二的次方  阅读( 1153)  评论( 1编辑  收藏  举报
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值