SurfaceFlinger框架是基于Binder进程间通信机制搭建的,SF作为一个服务进程,用户程序想要跟它通信必然要经过Binder机制。首先说一下,用户要跟SF通信,那么SF必须出现在ServiceManager中,因为SF也是一个服务,所有的服务都由ServiceManager来进行统一管理。在系统启动的过程中,SF就在ServiceManager中注册好了,注册好之后,SF在后台中监视一些surface的变化从而做出处理。

而启动之后,用户程序想操作一些跟surface有关的动作,就必须和SF进行交互。而这种交互是基于Binder进程间通信机制的。下面是一张图简单说明了SF的基本框架:

大体结构是这样,有些地方有些小错误用图形不能很好的表达。用文字来说明一下:
当应用程序需要请求SurfaceFlinger服务时,首先需要构造SurfaceComposerClient对象,通过SurfaceComposerClient对象就可以访问SurfaceFlinger服务了。基本的服务流程都是这么走的,我们看一下SurfaceComposerClient的构造函数:
SurfaceComposerClient::SurfaceComposerClient(): mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
可想而知没做啥事啊,SurfaceComposerClient 继承于RefBase类,在创建SurfaceComposerClient对象,系统第一次引用SurfaceComposerClient对象时,onFirstRef函数自动调用,我们看一下它的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;}}
}

上面代码,第二行的作用是获得SurfaceFlinger这个服务,我们跟踪一下:
sp<ISurfaceComposer> ComposerService::getComposerService() {ComposerService& instance = ComposerService::getInstance();Mutex::Autolock _l(instance.mLock);if (instance.mComposerService == NULL) {ComposerService::getInstance().connectLocked();assert(instance.mComposerService != NULL);ALOGD("ComposerService reconnected");}return instance.mComposerService;
}
第二行得到了ComposerService的对象,是为了下一步访问它的成员变量mComposerService(ISurfaceComposer类的),跟踪到第五行的函数 connectLocked():
void ComposerService::connectLocked() {const String16 name("SurfaceFlinger");while (getService(name, &mComposerService) != NO_ERROR) {usleep(250000);}assert(mComposerService != NULL);                                                                                                         //省略了一些东西。。。}

这里看到第三行getService(),第一个参数是“SurfaceFlinger”,第二个参数是mComposerService,记住它的类型的强引用的ISurfaceComposer,对就是这句得到了一个SurfaceFlinger服务的代理对象,看一下这个的函数的实体:
template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{const sp<IServiceManager> sm = defaultServiceManager();if (sm != NULL) {*outService = interface_cast<INTERFACE>(sm->getService(name));if ((*outService) != NULL) return NO_ERROR;}return NAME_NOT_FOUND;
}
到第四行这里跟之前启动过程中SurfaceFlinger的创建一模一样了,最后outService会被强转化成BpSurfaceComposer类,BpSurfaceComposer就是SurfaceFlinger在客户端这边的Binder代理,与之对应的是BnSurfaceComposer相当于SurfaceFlinger这边与BpSurfaceComposer进行交互的一方。获得了代理之后,我们再回到之前的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;}}
}

这时候走到if,sm有值了,所以往下走,看名字可以得出这是客户端在请求连接到SurfaceFlinger服务。我们跟踪一下createConnection:

virtual sp<ISurfaceComposerClient> createConnection(){uint32_t n;Parcel data, reply;data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());}

函数的大概意思是把一些连接信息写到数据包data里,然后通过transact这个函数传出去,remote()之前有研究过他是IBinder类的,这里重点看transact这个函数,他是IBinder类的成员函数故它的实现必定在BpBinder类里,我们跳到这个函数的实体:

status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{// Once a binder has died, it will never come back to life.if (mAlive) {status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);if (status == DEAD_OBJECT) mAlive = 0;return status;}return DEAD_OBJECT;
}

发现他又调用了transact这个函数,不同的是 是在IPCThreadState类中的 我们继续跟踪:

status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{status_t err = data.errorCheck();flags |= TF_ACCEPT_FDS;IF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "<< handle << " / code " << TypeCode(code) << ": "<< indent << data << dedent << endl;}if (err == NO_ERROR) {LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);}if (err != NO_ERROR) {if (reply) reply->setError(err);return (mLastError = err);}if ((flags & TF_ONE_WAY) == 0) {#if 0if (code == 4) { // relayoutALOGI(">>>>>> CALLING transaction 4");} else {ALOGI(">>>>>> CALLING transaction %d", code);}#endifif (reply) {err = waitForResponse(reply);} else {Parcel fakeReply;err = waitForResponse(&fakeReply);}#if 0if (code == 4) { // relayoutALOGI("<<<<<< RETURNING transaction 4");} else {ALOGI("<<<<<< RETURNING transaction %d", code);}#endifIF_LOG_TRANSACTIONS() {TextOutput::Bundle _b(alog);alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "<< handle << ": ";if (reply) alog << indent << *reply << dedent << endl;else alog << "(none requested)" << endl;}} else {err = waitForResponse(NULL, NULL);}return err;
}

这里已经扯到Binder机制的基本原理了,简单说就是客户端的SF代理通过BpBinder跟/dev/binder设备进行交互,向binder里写东西,函数err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);就是实现了这个功能,写完后他又等待服务端(SurfaceFlinger)那端的回应,err = waitForResponse(reply);当然服务端那边同样有人跟他进行交互。到这里,如果服务端收到消息并且返回了一个消息给客户端,这说明客户端请求连接成功。

请求成功后conn就不为0了,回到onFirstRef,成功后把coon赋给mClient。

既然客户端有请求了,那么服务端肯定有东西会去留意这个消息,回到更以前,做出向服务端请求连接这件事其实是SurfaceFlinger在客户端这边的代理BpSurfaceComposer完成的,那么之前说过,与之对应的就是BnSurfaceComposer。我们看一下他类的定义:

class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:enum {// Note: BOOT_FINISHED must remain this value, it is called from// Java by ActivityManagerService.BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,CREATE_CONNECTION,CREATE_GRAPHIC_BUFFER_ALLOC,CREATE_DISPLAY_EVENT_CONNECTION,CREATE_DISPLAY,DESTROY_DISPLAY,GET_BUILT_IN_DISPLAY,SET_TRANSACTION_STATE,AUTHENTICATE_SURFACE,BLANK,UNBLANK,GET_DISPLAY_INFO,CONNECT_DISPLAY,CAPTURE_SCREEN,};virtual status_t onTransact(uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags = 0);}

发现他没有构造函数只有一个成员函数 onTransact。跟踪一下:

status_t BnSurfaceComposer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{switch(code) {case CREATE_CONNECTION: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> b = createConnection()->asBinder();reply->writeStrongBinder(b);return NO_ERROR;}case CREATE_GRAPHIC_BUFFER_ALLOC: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> b = createGraphicBufferAlloc()->asBinder();reply->writeStrongBinder(b);return NO_ERROR;}case SET_TRANSACTION_STATE: {CHECK_INTERFACE(ISurfaceComposer, data, reply);size_t count = data.readInt32();ComposerState s;Vector<ComposerState> state;state.setCapacity(count);for (size_t i=0 ; i<count ; i++) {s.read(data);state.add(s);}count = data.readInt32();DisplayState d;Vector<DisplayState> displays;displays.setCapacity(count);for (size_t i=0 ; i<count ; i++) {d.read(data);displays.add(d);}uint32_t flags = data.readInt32();setTransactionState(state, displays, flags);return NO_ERROR;}case BOOT_FINISHED: {CHECK_INTERFACE(ISurfaceComposer, data, reply);bootFinished();return NO_ERROR;}case CAPTURE_SCREEN: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> display = data.readStrongBinder();sp<IGraphicBufferProducer> producer =interface_cast<IGraphicBufferProducer>(data.readStrongBinder());uint32_t reqWidth = data.readInt32();uint32_t reqHeight = data.readInt32();uint32_t minLayerZ = data.readInt32();uint32_t maxLayerZ = data.readInt32();status_t res = captureScreen(display, producer,reqWidth, reqHeight, minLayerZ, maxLayerZ);reply->writeInt32(res);return NO_ERROR;}case AUTHENTICATE_SURFACE: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IGraphicBufferProducer> bufferProducer =interface_cast<IGraphicBufferProducer>(data.readStrongBinder());int32_t result = authenticateSurfaceTexture(bufferProducer) ? 1 : 0;reply->writeInt32(result);return NO_ERROR;}case CREATE_DISPLAY_EVENT_CONNECTION: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IDisplayEventConnection> connection(createDisplayEventConnection());reply->writeStrongBinder(connection->asBinder());return NO_ERROR;}case CREATE_DISPLAY: {CHECK_INTERFACE(ISurfaceComposer, data, reply);String8 displayName = data.readString8();bool secure = bool(data.readInt32());sp<IBinder> display(createDisplay(displayName, secure));reply->writeStrongBinder(display);return NO_ERROR;}case DESTROY_DISPLAY: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> display = data.readStrongBinder();destroyDisplay(display);return NO_ERROR;}case GET_BUILT_IN_DISPLAY: {CHECK_INTERFACE(ISurfaceComposer, data, reply);int32_t id = data.readInt32();sp<IBinder> display(getBuiltInDisplay(id));reply->writeStrongBinder(display);return NO_ERROR;}case BLANK: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> display = data.readStrongBinder();blank(display);return NO_ERROR;}case UNBLANK: {CHECK_INTERFACE(ISurfaceComposer, data, reply);sp<IBinder> display = data.readStrongBinder();unblank(display);return NO_ERROR;}case GET_DISPLAY_INFO: {CHECK_INTERFACE(ISurfaceComposer, data, reply);DisplayInfo info;sp<IBinder> display = data.readStrongBinder();status_t result = getDisplayInfo(display, &info);memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo));reply->writeInt32(result);return NO_ERROR;}default: {return BBinder::onTransact(code, data, reply, flags);}}// should be unreachablereturn NO_ERROR;
}

代码虽然有点长,但是整体框架就是一个swith语句,看到第一个分支,马上就能看出来这是一个对请求连接信号的处理,这里大概能知道这个onTransact的功能就是判断收到的消息即参数code是哪种类型从而做出相应的处理。在server测,一开始创建SF服务的时候,在线城池创建的时候就已经开启线程去监听binder设备了我们来跟踪下:

从最开始SF服务启动的源文件开始:

int main(int argc, char** argv) {// When SF is launched in its own process, limit the number of// binder threads to 4.ProcessState::self()->setThreadPoolMaxThreadCount(4);// start the thread poolsp<ProcessState> ps(ProcessState::self());ps->startThreadPool();

是一个片段,最后一句就是开始线程池。跟踪其代码:

void ProcessState::startThreadPool()
{AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}
}

核心也在最后一句,

void ProcessState::spawnPooledThread(bool isMain)
{if (mThreadPoolStarted) {String8 name = makeBinderThreadName();ALOGV("Spawning new pooled thread, name=%s\n", name.string());sp<Thread> t = new PoolThread(isMain);t->run(name.string());}
}

到这里,可以看到实质的线程创建和开始运行。接下来我用一张图来表示他的函数调用的走向:

这里一旦检测到有连接请求消息就会跳到executeCommand的switch分支BR_TRANSACTION,去执行BBinder的transact,transact函数会调用onTransact函数,这个onTransact由其子类实现,在这里由BnSurfaceComposer完成,即调用的是BnSurfaceComposer::onTransact(),函数的具体内容在上面已贴出,就是处理不同的请求。

到此为止,客户端已经与SF进行连接,也就是交手过了,那么自然连接了,一定要做些事情比如客户端请求渲染一个surface,或者等等其他的。接下去的工作就是SurfaceFlinger的事,对客户端不同的请求而进行不同的处理,这才是SF核心工作所在。当然所有的通信机制都是基于binder机制,而求也有负责这个方面的客户端这边的binder代理BpSurfaceComposerClient和服务端这边的本地对象 BnSurfaceComposerClient,而这里有点不一样的是BnSurfaceComposerClient派生出Client所以事情都交与Client做了。

Android4.4深入浅出之SurfaceFlinger与Client通信框架(一)相关推荐

  1. Android4.4深入浅出之SurfaceFlinger总体结构

     转自:http://blog.csdn.net/w401229755/article/details/38420191 一.             Android GUI框架: SurfaceFl ...

  2. 网络通信之TCP Client通信(基于Arduino)

    网络通信之TCP Client通信(基于Arduino) 前期准备 实验要求 具体方法 程序流程 程序 实验现象 后续 前期准备 Arduino IDE ESPDuino Arduino ESP826 ...

  3. 【es】client通信流程与负载均衡

    1.概述 转载:[7]elasticsearch源码深入分析--client通信流程与负载均衡 2.如何与集群(Cluster)通信 2.1 使用Node与cluster通信 Node node = ...

  4. Netty的使用:Server和Client通信

    来自:Netty的使用:Server和Client通信_宿久-CSDN博客_netty server Netty 是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,提供 ...

  5. 有人串口转wifi模块 httpd client通信示例-用户使用网页通过服务器收发串口数据源码 小黄人软件

    有人串口转wifi模块 httpd client通信示例-用户使用网页通过服务器收发串口数据 功能:用户使用网页通过服务器收发串口数据,转发信息通过文件转存.网页自动更新串口发来的数据,网页发送数据到 ...

  6. Apollo 笔记(03)— Cyber RT Python 接口(channel 读和写、server/client 通信、record 文件读写信息查询、timer 时间定时器操作)

    https://cyber-rt.readthedocs.io/en/latest/CyberRT_Python_API.html https://cyber-rt.readthedocs.io/en ...

  7. Netty通信框架Java实现小记

    1.Netty介绍    Netty通俗地说就是一套Socket通信框架,提供异步的.事件驱动的网络应用程序框架和工具,可快速开发高性能.高可靠性的网络服务器和客户端程序 2.Netty的特性     ...

  8. 高性能 TCP UDP 通信框架 HP-Socket v3.2.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  9. .net3.5下的Socket通信框架

    .net3.5下的Socket通信框架 1:前言 写博客时间不短了但是一直不知道怎么开头.索性就开门见山吧. 这篇文章主要给大家介绍.net3.5下的Socket通信,主要从事件池,缓冲区以及协议三个 ...

最新文章

  1. C语言配置文件解析库——iniparser
  2. C语言中fgets()函数
  3. python list合并_python基础===两个list合并成一个dict的方法
  4. 自定义Gradle Plugin
  5. 再学 GDI+[86]: TGPImage(6) - 拖动图像
  6. 【C/C++】字符串类型
  7. debugging tools for windows 10下载安装问题
  8. python 局部变量和全局变量 global
  9. ant 发布web应用脚本
  10. ns-3 教程 —— 入门
  11. 【Python机器学习】决策树ID3算法结果可视化附源代码 对UCI数据集Caesarian Section进行分类
  12. 首次 golang爬虫插件gocolly/colly 使用经历
  13. iOS开发学习之大牛们的博客
  14. 拼多多优惠券赔付规则 拼多多发货超时具体怎么赔 拼多多超时发货之后没有优惠券怎么办
  15. 对话腾讯天琴赵伟峰:当音乐与科技结合,会碰撞出怎样的火花?
  16. 微信小程序反编译 PC端
  17. java 二进制 表示负数_java中的负数表示
  18. 12.11 蜜蜂路线
  19. CF1375E Inversion SwapSort
  20. Vue 之 移动端 better-scroll 下 click 事件失效问题(PC端却正常click点击)

热门文章

  1. 大数据处理问题及解决方法
  2. AddHeader使用方法
  3. 易语言可以编译c语言,刷屏软件?其实易语言也可以做这种软件
  4. 设置图片跟随鼠标移动
  5. hadoop之MapReduce学习教程
  6. Google BERT 中文应用之《红楼梦》中对话人物提取
  7. SEO每天都是动态变化的,你要关注什么?
  8. 港珠澳大桥介绍网站设计【期末大作业】源码
  9. 自动下载必应主页图片做壁纸
  10. java 打印出如下图案(菱形)