首页 技术 正文
技术 2022年11月15日
0 收藏 537 点赞 4,603 浏览 6919 个字

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.cppsp<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) 图形显示系统 – 开篇


相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,088
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,564
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,412
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,185
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,822
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905