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


Android 12(S) 图形显示系统 - 应用建立和SurfaceFlinger的沟通桥梁(三)的更多相关文章

  1. Android 12(S) 图形显示系统 - 简单聊聊 SurfaceView 与 BufferQueue的关联(十三)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 前面的文章中,讲解的内容基本都是从我们提供的一个 native demo Android 12(S) 图形显示系统 - 示例应用( ...

  2. Android 12(S) 图形显示系统 - 示例应用(二)

    1 前言 为了更深刻的理解Android图形系统抽象的概念和BufferQueue的工作机制,这篇文章我们将从Native Level入手,基于Android图形系统API写作一个简单的图形处理小程序 ...

  3. Android 12(S) 图形显示系统 - createSurface的流程(五)

    题外话 刚刚开始着笔写作这篇文章时,正好看电视在采访一位92岁的考古学家,在他的日记中有这样一句话,写在这里与君共勉"不要等待幸运的降临,要去努力的掌握知识".如此朴实的一句话,此 ...

  4. Android 12(S) 图形显示系统 - BufferQueue/BLASTBufferQueue之初识(六)

    题外话 你有没有听见,心里有一声咆哮,那一声咆哮,它好像在说:我就是要从后面追上去! 写文章真的好痛苦,特别是自己对这方面的知识也一知半解就更加痛苦了.这已经是这个系列的第六篇了,很多次都想放弃了,但 ...

  5. Android 12(S) 图形显示系统 - 初识ANativeWindow/Surface/SurfaceControl(七)

    题外话 "行百里者半九十",是说步行一百里路,走过九十里,只能算是走了一半.因为步行越接近目的地,走起来越困难.借指凡事到了接近成功,往往是最吃力.最艰难的时段.劝人做事贵在坚持, ...

  6. Android 12(S) 图形显示系统 - BufferQueue的工作流程(九)

    题外话 Covid-19疫情的强烈反弹,小区里检测出了无症状感染者.小区封闭管理,我也不得不居家办公了.既然这么大把的时间可以光明正大的宅家里,自然要好好利用,八个字 == 努力工作,好好学习 一.前 ...

  7. Android 12(S) 图形显示系统 - 解读Gralloc架构及GraphicBuffer创建/传递/释放(十四)

    必读: Android 12(S) 图形显示系统 - 开篇 一.前言 在前面的文章中,已经出现过 GraphicBuffer 的身影,GraphicBuffer 是Android图形显示系统中的一个重 ...

  8. Android 12(S) 图形显示系统 - 基本概念(一)

    1 前言 Android图形系统是系统框架中一个非常重要的子系统,与其它子系统一样,Android 框架提供了各种用于 2D 和 3D 图形渲染的 API供开发者使用来创建绚丽多彩的应用APP.图形渲 ...

  9. Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)

    1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...

随机推荐

  1. Vue3 全家桶,从 0 到 1 实战项目,新手有福了

    前端发展百花放,一技未熟百技出.未知何处去下手,关注小编胜百书. 我是前端人,专注分享前端内容! 本篇文章主要是,使用 vite 创建一个vue3 项目,实践 vie-router4 vuex4 结合 ...

  2. Clusternet 成为首批通过工信部开源成熟度评估项目!!!

    Clusternet 作为首批项目参与了<信息技术 开源 开源项目评估模型参考架构>测评,并成为通过评估的四个项目之一.<信息技术 开源 开源项目评估模型参考架构>由国防科技大 ...

  3. JAVA生成文件的md5校验值

    这里使用了lombok打印日志,也可以不用 import java.io.File; import java.io.FileInputStream; import java.io.IOExceptio ...

  4. Elasticsearch删除所有数据

    使用post请求 POST http://localhost:9200/索引/标签/_delete_by_query?pretty { "query": { "match ...

  5. -fno-rtti -fno-exceptions

    -fno-rtti 禁用运行时类型信息-fno-exceptions 禁用异常机制一般只有对程序运行效率及资源占用比较看重的场合才会使用, 如果要做这两个的话最好连libstdc++和其他所有的的c+ ...

  6. 【LeetCode】1472. 设计浏览器历史记录 Design Browser History (Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 模拟法 日期 题目地址:https://leetcod ...

  7. 【LeetCode】1041. Robot Bounded In Circle 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 找规律 日期 题目地址:https://leetco ...

  8. 【LeetCode】257. Binary Tree Paths 解题报告(java & python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 题目地址:https://leet ...

  9. hdu 5592 ZYB's Premutation(线段树优化)

    设f_if​i​​是第ii个前缀的逆序对数,p_ip​i​​是第ii个位置上的数,则f_i-f_{i-1}f​i​​−f​i−1​​是ii前面比p_ip​i​​大的数的个数.我们考虑倒着做,当我们处理 ...

  10. 1137 - Expanding Rods

    1137 - Expanding Rods    PDF (English) Statistics Forum Time Limit: 0.5 second(s) Memory Limit: 32 M ...