8.4.3 SurfaceControl分析

最后更新于:2022-04-02 05:52:31

1. SurfaceControl的来历 根据精简的流程可知,这一节要分析的是SurfaceControl对象。先回顾一下这个对象的创建过程,代码如下所示: **android_view_Surface.cpp** ~~~ static void Surface_init(JNIEnv* env, jobjectclazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) { SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client); //注意这个变量,类型是SurfaceControl,名字却叫surface,稍不留神就出错了。 spsurface; if (jname == NULL) { //调用Client的createSurface函数,得到一个SurfaceControl对象。 surface= client->createSurface(pid, dpy, w, h, format, flags); } ...... //将这个SurfaceControl对象设置到Java层的对象中保存。 setSurfaceControl(env, clazz, surface); } ~~~ 通过上面的代码可知,SurfaceControl对象由createSurface得来,下面看看这个函数。 此时,读者或许会被代码中随意起的变量名搞糊涂,因为我的处理方法碰到了容易混淆的地方,尽量以对象类型来表示这个对象。 (1)分析createSurface的请求端 在createSurface内部会使用Binder通信将请求发给SF,所以它分为请求和响应两端,先看请求端,代码如下所示: **SurfaceComposerClient.cpp** ~~~ spSurfaceComposerClient::createSurface( int pid, DisplayID display,//DisplayID是什么意思? uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { String8 name; constsize_t SIZE = 128; charbuffer[SIZE]; snprintf(buffer, SIZE, "", getpid()); name.append(buffer); //调用另外一个createSurface,多一个name参数 returnSurfaceComposerClient::createSurface(pid, name, display, w, h, format, flags); } ~~~ 在分析另外一个createSurface之前,应先介绍一下DisplayID的含义: ~~~ typedef int32_t DisplayID; ~~~ DisplayID是一个int整型,它的意义是屏幕编号,例如双屏手机就有内屏和外屏两块屏幕。由于目前Android的Surface系统只支持一块屏幕,所以这个变量的取值都是0。 再分析另外一个createSurface函数,它的代码如下所示: **SurfaceComposerClient.cpp** ~~~ spSurfaceComposerClient::createSurface( int pid,const String8& name,DisplayID display,uint32_t w, uint32_t h,PixelFormat format,uint32_t flags) { sp result; if(mStatus == NO_ERROR) { ISurfaceFlingerClient::surface_data_t data; //调用BpSurfaceFlingerClient的createSurface函数 sp surface = mClient->createSurface(&data, pid,name, display, w, h,format, flags); if(surface != 0) { if (uint32_t(data.token) < NUM_LAYERS_MAX) { //以返回的ISurface对象创建一个SurfaceControl对象 result = new SurfaceControl(this, surface, data, w, h, format, flags); } } } returnresult;//返回的是SurfaceControl对象 } ~~~ 请求端的处理比较简单: - 调用跨进程的createSurface函数,得到一个ISurface对象,根据Binder一章的知识可知,这个对象的真实类型是BpSurface。不过以后统称之为ISurface。 - 以这个ISurface对象为参数,构造一个SurfaceControl对象。 createSurface函数的响应端在SurfaceFlinger进程中,下面去看这个函数。 在Surface系统定义了很多类型,咱们也中途休息一下,不妨来看看和字符串“Surface”有关的有多少个类,权当其为小小的 娱乐: Native层有Surface、ISurface、SurfaceControl、SurfaceComposerClient。 Java层有Surface、SurfaceSession。 上面列出的还只是一部分,后面还有呢!*&@&*%¥* (2)分析createSurface的响应端 前面讲过,可把BClient看作是SF的Proxy,它会把来自客户端的请求派发给SF处理,通过代码来看看,是不是这样的?如下所示: **SurfaceFlinger.cpp** ~~~ sp BClient::createSurface( ISurfaceFlingerClient::surface_data_t* params, int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { //果然是交给SF处理,以后我们将跳过BClient这个代理。 return mFlinger->createSurface(mId, pid,name, params, display, w, h, format, flags); } ~~~ 来看createSurface函数,它的目的就是创建一个ISurface对象,不过这中间的玄机还挺多,代码如下所示: **SurfaceFlinger.cpp** ~~~ spSurfaceFlinger::createSurface(ClientID clientId, int pid, const String8& name, ISurfaceFlingerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp layer;//LayerBaseClient是Layer家族的基类 //这里又冒出一个LayerBaseClient的内部类,它也叫Surface,是不是有点头晕了? sp surfaceHandle; Mutex::Autolock _l(mStateLock); //根据clientId找到createConnection时加入的那个Client对象 sp client = mClientsMap.valueFor(clientId); ...... //注意这个id,它的值表示Client创建的是第几个显示层,根据图8-14可以看出,这个id //同时也表示将使用SharedBufferStatck数组的第id个元素。 int32_t id = client->generateId(pid); //一个Client不能创建多于NUM_LAYERS_MAX个的Layer。 if(uint32_t(id) >= NUM_LAYERS_MAX) { return surfaceHandle; } //根据flags参数来创建不同类型的显示层,我们在8.4.1节介绍过相关知识 switch(flags & eFXSurfaceMask) { case eFXSurfaceNormal: if (UNLIKELY(flags & ePushBuffers)) { //创建PushBuffer类型的显示层,我们将在拓展思考部分分析它 layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags); } else { //①创建Normal类型的显示层,我们分析待会这个 layer = createNormalSurfaceLocked(client, d, id, w, h, flags, format); } break; case eFXSurfaceBlur: //创建Blur类型的显示层 layer = createBlurSurfaceLocked(client, d, id, w, h, flags); break; case eFXSurfaceDim: //创建Dim类型的显示层 layer = createDimSurfaceLocked(client, d, id, w, h, flags); break; } if(layer != 0) { layer->setName(name); setTransactionFlags(eTransactionNeeded); //从显示层对象中取出一个ISurface对象赋值给SurfaceHandle surfaceHandle = layer->getSurface(); if(surfaceHandle != 0) { params->token = surfaceHandle->getToken(); params->identity = surfaceHandle->getIdentity(); params->width = w; params->height = h; params->format = format; } } returnsurfaceHandle;//ISurface的Bn端就是这个对象。 } ~~~ 上面代码中的函数倒是很简单,知识代码里面冒出来的几个新类型和它们的名字却让人有点头晕。先用文字总结一下: - LayerBaseClient:前面提到的显示层在代码中的对应物,就是这个LayerBaseClient,不过这是一个大家族,不同类型的显示层将创建不同类型的LayerBaseClient。 - LayerBaseClient中有一个内部类,名字叫Surface,这是一个支持Binder通信的类,它派生于ISurface。 关于Layer的故事,后面会有单独的章节来介绍。这里先继续分析createNormalSurfaceLocked函数。它的代码如下所示: **SurfaceFlinger.cpp** ~~~ spSurfaceFlinger::createNormalSurfaceLocked( const sp& client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) { switch(format) { //一些图像方面的参数设置,可以不去管它。 casePIXEL_FORMAT_TRANSPARENT: casePIXEL_FORMAT_TRANSLUCENT: format = PIXEL_FORMAT_RGBA_8888; break; casePIXEL_FORMAT_OPAQUE: format = PIXEL_FORMAT_RGB_565; break; } //①创建一个Layer类型的对象 sp layer = new Layer(this, display,client, id); //②设置Buffer status_t err = layer->setBuffers(w, h, format, flags); if (LIKELY(err == NO_ERROR)) { //初始化这个新layer的一些状态 layer->initStates(w, h, flags); //③ 还记得在图8-10中提到的Z轴吗?下面这个函数把这个layer加入到Z轴大军中。 addLayer_l(layer); } ...... returnlayer; } ~~~ createNormalSurfaceLocked函数有三个关键点,它们是: - 构造一个Layer对象。 - 调用Layer对象的setBuffers函数。 - 调用SF的addLayer_l函数。 暂且记住这三个关键点,后文有单独章节分析它们。先继续分析SurfaceControl的流程。 (3)创建SurfaceControl对象 当跨进程的createSurface调用返回一个ISurface对象时,将通过下面的代码创建一个SurfaceControl对象: ~~~ result = new SurfaceControl(this, surface, data,w, h,format, flags); ~~~ 下面来看这个SurfaceControl对象为何物。它的代码如下所示: **SurfaceControl.cpp** ~~~ SurfaceControl::SurfaceControl( const sp& client, const sp& surface, const ISurfaceFlingerClient::surface_data_t& data, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) //mClient为SurfaceComposerClient,而mSurface指向跨进程createSurface调用 //返回的ISurface对象。 :mClient(client), mSurface(surface), mToken(data.token), mIdentity(data.identity), mWidth(data.width), mHeight(data.height), mFormat(data.format), mFlags(flags) { } ~~~ SurfaceControl类可以看作是一个wrapper类: 它封装了一些函数,通过这些函数可以方便地调用mClient或ISurface提供的函数。 在SurfaceControl的分析过程中,还遗留了和Layer相关的部分,下面就来解决它们。 2. Layer和它的家族 我们在createSurface中创建的是Normal的Layer,下面先看这个Layer的构造函数。 (1)Layer的构造 Layer是从LayerBaseClient派生的,其代码如下所示: **Layer.cpp** ~~~ Layer::Layer(SurfaceFlinger* flinger, DisplayIDdisplay, const sp& c, int32_t i)//这个i表示SharedBufferStack数组的索引 : LayerBaseClient(flinger, display, c, i),//先调用基类构造函数 mSecure(false), mNoEGLImageForSwBuffers(false), mNeedsBlending(true), mNeedsDithering(false) { //getFrontBuffer实际取出的是FrontBuffer的位置 mFrontBufferIndex = lcblk->getFrontBuffer(); } ~~~ 再来看基类LayerBaseClient的构造函数,代码如下所示: **LayerBaseClient.cpp** ~~~ LayerBaseClient::LayerBaseClient(SurfaceFlinger*flinger, DisplayID display, const sp& client, int32_t i) :LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity))) { /* 创建一个SharedBufferServer对象,注意它使用了SharedClient对象, 并且传入了表示SharedBufferStack数组索引的i和一个常量NUM_BUFFERS */ lcblk = new SharedBufferServer( client->ctrlblk, i, NUM_BUFFERS,//该值为常量2,在Layer.h中定义 mIdentity); } ~~~ SharedBufferServer是什么?它和SharedClient有什么关系? 其实,之前在介绍SharedClient时曾提过与此相关的内容,这里再来认识一下,先看图8-15: :-: ![](http://img.blog.csdn.net/20150802162659551?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图8-15 ShardBufferServer的示意图 根据上图并结合前面的介绍,可以得出以下结论: - 在SF进程中,Client的一个Layer将使用SharedBufferStack数组中的一个成员,并通过SharedBufferServer结构来控制这个成员,我们知道SF是消费者,所以可由SharedBufferServer来控制数据的读取。 - 与之相对应,客户端的进程也会有一个对象来使用这个SharedBufferStatck,可它是通过另外一个叫SharedBufferClient的结构来控制的。客户端为SF提供数据,所以可由SharedBufferClient控制数据的写入。在后文的分析中还会碰到SharedBufferClient。 注意,在拓展思考部分,会有单独章节来分析生产/消费过程中的读写控制。 通过前面的代码可知,Layer对象被new出来后,传给了一个sp对象,读者还记得sp中的onFirstRef函数吗?Layer家族在这个函数中还有一些处理。一起去看看,但这个函数由基类LayerBaseClient实现。 **LayerBase.cpp** ~~~ void LayerBaseClient::onFirstRef() { sp client(this->client.promote()); if (client != 0) { //把自己加入client对象的mLayers数组中,这部分内容比较简单,读者可以自行研究 client->bindLayer(this, mIndex); } } ~~~ 好,Layer创建完毕,下面来看第二个重要的函数setBuffers。 (2)setBuffers的分析 setBuffers,Layer类以及Layer的基类都有实现。由于创建的是Layer类型的对象,所以请读者直接到Layer.cpp中寻找setBuffers函数。这个函数的目的就是创建用于PageFlipping的FrontBuffer和BackBuffer。一起来看,代码如下所示: **Layer.cpp** ~~~ status_t Layer::setBuffers( uint32_t w, uint32_th, PixelFormat format,uint32_t flags) { PixelFormatInfo info; status_t err = getPixelFormatInfo(format, &info); if(err) return err; //DisplayHardware是代表显示设备的HAL对象,0代表第一块屏幕的显示设备。 //这里将从HAL中取出一些和显示相关的信息。 constDisplayHardware& hw(graphicPlane(0).displayHardware()); uint32_t const maxSurfaceDims = min( hw.getMaxTextureSize(), hw.getMaxViewportDims()); PixelFormatInfo displayInfo; getPixelFormatInfo(hw.getFormat(),&displayInfo); constuint32_t hwFlags = hw.getFlags(); ...... /* 创建Buffer,这里将创建两个GraphicBuffer。这两个GraphicBuffer就是我们前面 所说的FrontBuffer和BackBuffer。 */ for (size_t i=0 ; i& layer) { /* mCurrentState是SurfaceFlinger定义的一个结构,它有一个成员变量叫 layersSortedByZ,其实就是一个排序数组。下面这个add函数将把这个新的layer按照 它在Z轴的位置加入到排序数组中。mCurrentState保存了所有的显示层。 */ ssize_t i = mCurrentState.layersSortedByZ.add( layer,&LayerBase::compareCurrentStateZ); sp lbc = LayerBase::dynamicCast< LayerBaseClient*>(layer.get()); if(lbc != 0) { mLayerMap.add(lbc->serverIndex(), lbc); } returnNO_ERROR; } ~~~ 对Layer的三个关键函数都已分析过了,下面正式介绍Layer家族。 (4)Layer家族的介绍 前面的内容确让人头晕眼花,现在应该帮大家恢复清晰的头脑。先来“一剂猛药”,见图8-16: :-: ![](http://img.blog.csdn.net/20150802162717491?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图8-16 Layer家族 通过上图可知: - LayerBaseClient从LayerBase类派生。 - LayerBaseClient还有四个派生类,分别是Layer、LayerBuffer、LayerDim和LayerBlur。 - LayerBaseClient定义了一个内部类Surface,这个Surface从ISurface类派生,它支持Binder通信。 - 针对不同的类型,Layer和LayerBuffer分别有一个内部类SurfaceLayer和SurfaceLayerBuffer,它们继承了LayerBaseClient的Surface类。所以对于Normal类型的显示层来说,getSurface返回的ISurface对象的真正类型是SurfaceLayer。 - LayerDim和LayerBlur类没有定义自己的内部类,所以对于这两种类型的显示层来说,它们直接使用了LayerBaseClient的Surface。 - ISurface接口提供了非常简单的函数,如requestBuffer、postBuffer等。 这里大量使用了内部类。我们知道,内部类最终都会把请求派发给外部类对象来处理,既然如此,在以后分析中,如果没有特殊情况,就会直接跳到外部类的处理函数中。 强烈建议Google把Surface相关代码好好整理一下,至少让类型名取得更直观些,现在这样确实有点让人头晕。好,来小小娱乐一下。看之前介绍的和“Surface”有关的名字: Native层有Surface、ISurface、SurfaceControl、SurfaceComposerClient。 Java层有Surface、SurfaceSession。 在介绍完Layer家族后,与它相关的名字又多了几个,它们是 LayerBaseClient::Surface、Layer::SurfaceLayer、LayerBuffer::SurfaceLayerBuffer。 3. SurfaceControl总结 SurfaceControl创建后得到了什么呢?可用图8-17来表示: :-: ![](http://img.blog.csdn.net/20150802162734012?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图8-17 SurfaceControl创建后的结果图 通过上图可以知道: - mClient成员变量指向SurfaceComposerClient。 - mSurface的Binder通信响应端为SurfaceLayer。 - SurfaceLayer有一个变量mOwner指向它的外部类Layer,而Layer有一个成员变量mSurface指向SurfaceLayer。这个SurfaceLayer对象由getSurface函数返回。 >[info] **注意**,mOwner变量由SurfaceLayer的基类Surface(LayBaseClient的内部类)定义。 接下来就是writeToParcel分析和Native Surface对象的创建了。注意,这个Native的Surface可不是LayBaseClient的内部类Surface。
';