android surfaceflinger研究----Surface机制

前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。如何创建surface,如何显示窗口等等,所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。

android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析,首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface Buffer显示到显示系统中。。

1. Surface机制的静态关系

将这一部分叫做Surface机制,是有别于SurfaceFlinger而言的,android的图形系统中,作为C/S模型两端的WMS和SurfaceFlinger是图形系统业务的核心,但是不把WMS和SurfaceFlinger中间的这层联系搞清楚的话,是很难理解整个图形系统的,在本文中我将两者之间的这个联系关系称之为Surface机制,它的主要任务就是创建一个Surface,ViewRoot在这个Surface上描绘当前的窗口,SurfaceFlinger将这个Surface flinger(扔)给显示系统将其呈现在硬件设备上。其实这里这个Surface在不同的模块中是以不同的形态存在的,唯一不变的就是其对应的显示Buffer。



1.1 ViewRoot和WMS共享Surface

我们知道每个Activity都会有一个ViewRoot作为Activity Window与WMS交互的接口,ViewRoot会绘制整个Activity的窗口View到Surface上,因此我们在ViewRoot中就有了创建Surface的需求。看一下代码中的Surface的定义:

relayoutWindow()@ViewRoot.java

  1. <spanstyle="font-size:13px;">privatefinalSurfacemSurface=newSurface();</span>
Surface()@Surface.java

  1. <spanstyle="font-size:13px;">publicSurface(){
  2. if(DEBUG_RELEASE){
  3. mCreationStack=newException();
  4. }
  5. mCanvas=newCompatibleCanvas();
  6. }</span>
由上面可以看出在ViewRoot中定义的Surface只是一个空壳,那么真正的Surface是在哪里被初始化的呢?大管家WMS中!当ViewRoot请求WMS relayout时,会将ViewSurface中的Surface交给WMS初始化。在WMS中,对应每个WindowState对象,在relayout窗口时,同样会创建一个Surface,wms中的这个Surface会真正的初始化,然后再将这个WMS Surface复制给ViewRoot中的Surface。这么实现的目的就是保证ViewRoot和WMS共享同一个Surface。ViewRoot对Surface进行绘制,WMS对这个Surface进行初始化及管理。很和谐!

relayoutWindow()@ViewRoot.java

  1. <spanstyle="font-size:13px;">intrelayoutResult=sWindowSession.relayout(
  2. mWindow,params,
  3. (int)(mView.mMeasuredWidth*appScale+0.5f),
  4. (int)(mView.mMeasuredHeight*appScale+0.5f),
  5. viewVisibility,insetsPending,mWinFrame,
  6. mPendingContentInsets,mPendingVisibleInsets,
  7. mPendingConfiguration,mSurface);</span>
relayoutWindow()@WindowManagerService.java
  1. <spanstyle="font-size:13px;">Surfacesurface=win.createSurfaceLocked();
  2. if(surface!=null){
  3. outSurface.copyFrom(surface);
  4. win.mReportDestroySurface=false;
  5. win.mSurfacePendingDestroy=false;
  6. if(SHOW_TRANSACTIONS)Slog.i(TAG,
  7. "OUTSURFACE"+outSurface+":copied");
  8. }else{</span>

1.2SurfaceSession

SurfaceSession可以认为是创建Surface过程中,WMS和SurfaceFlinger之间的会话层,通过这个SurfaceSession实现了Surface的创建。


SurfaceSession是JAVA层的概念,@SurfaceSession.java。它对应的native实体是一个SurfaceComposerClient对象。

SurfaceComposerClient通过ComposerService类来获得SurfaceFlinger的IBinder接口,但是光获得SurfaceFlinger的IBinder接口是不够的,要想请求SurfaceFlinger创建一个Surface,还需要向SurfaceFlinger获得一个IBinder接口ISurfaceComposerClient,通过这个ISurfaceComposerClient来请求SurfaceFlinger创建一个Surface,为什么这么绕呢,为什么不直接让SurfaceFlinger创建Surface呢?

站在SurfaceFlinger的角度来考虑,对于SurfaceFlinger来说,可能有多个Client来请求SurfaceFlinger的业务,每个Client可能会请求SurfaceFlinger创建多个Surface,那么SurfaceFlinger本地需要提供一套机制来保存每个client请求创建的Surface,SurfaceFlinger通过为每个client创建一个Client对象实现这个机制,并将这个Client的IBinder接口ISurfaceComposerClient返给SurfaceComposerClient对象。SurfaceComposerClient对象在通过ISurfaceComposerClient去请求创建Surface。

@SurfaceFlinger.h

  1. classClient:publicBnSurfaceComposerClient

@SurfaceComposerClient.cpp
  1. voidSurfaceComposerClient::onFirstRef()
  2. {
  3. sp<ISurfaceComposer>sm(getComposerService());
  4. if(sm!=0){
  5. sp<ISurfaceComposerClient>conn=sm->createConnection();
  6. if(conn!=0){
  7. mClient=conn;
  8. Composer::addClient(this);
  9. mPrebuiltLayerState=newlayer_state_t;
  10. mStatus=NO_ERROR;
  11. }
  12. }
  13. }

下图描述了整个SurfaceSession的内部结构与工作流程。

其中蓝色箭头是SurfaceComposerClient通过ComposerService获得SurfaceFlinger的IBinder接口ISurfaceComposer过程;

红色箭头表示SurfaceComposerClient通过IPC请求SurfaceFlinger创建Client的过程,并获得Client的IBinder接口ISurfaceComposerClient;

绿色箭头表示SurfaceComposerClient通过IPC请求Client创建Surface。



1.3 Surface的形态

上一节我们分析了SurfaceSession的静态结构,得知Surface的创建过程是通过SurfaceSession这个中间会话层去请求SurfaceFlinger去创建的,并且这篇文章中,我们说了半天Surface了,那么究竟我们要创建的Surface究竟是什么样的一个东西呢,它的具体形态是什么呢?这一小节我们就来分析以下Surface的形态。

1.3.1 client端Surface的形态

首先,我们看一下Surface在WMS中定义的代码

createSurfaceLocked()@WindowManagerService.java

  1. mSurface=newSurface(
  2. mSession.mSurfaceSession,mSession.mPid,
  3. mAttrs.getTitle().toString(),
  4. 0,w,h,mAttrs.format,flags);
我们可以看到,它将SurfaceSession对象当作参数传递给了Surface的构造函数。往下看Surface的构造函数。

@Surface.java

  1. publicSurface(SurfaceSessions,
  2. intpid,intdisplay,intw,inth,intformat,intflags)
  3. throwsOutOfResourcesException{
  4. if(DEBUG_RELEASE){
  5. mCreationStack=newException();
  6. }
  7. mCanvas=newCompatibleCanvas();
  8. init(s,pid,null,display,w,h,format,flags);
  9. }
这个构造函数,不同于我们在ViewRoot中看到的Surface的构造函数,这个构造函数并不是一个空壳,它做了本地实体的初始化工作,因此这个Surface才是一个真正的Suface。

Native 函数init回调到SurfaceComposerClient的createSurface()函数,往下的过程在上一节的图中描述的很清楚,流程就不介绍了,同时我们先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?


@SurfaceComposerClient.cpp

  1. sp<SurfaceControl>SurfaceComposerClient::createSurface(
  2. intpid,
  3. constString8&name,
  4. DisplayIDdisplay,
  5. uint32_tw,
  6. uint32_th,
  7. PixelFormatformat,
  8. uint32_tflags)
  9. {
  10. sp<SurfaceControl>result;
  11. if(mStatus==NO_ERROR){
  12. ISurfaceComposerClient::surface_data_tdata;
  13. sp<ISurface>surface=mClient->createSurface(&data,pid,name,
  14. display,w,h,format,flags);
  15. if(surface!=0){
  16. result=newSurfaceControl(this,surface,data,w,h,format,flags);
  17. }
  18. }
  19. returnresult;
  20. }

从上面的代码我们可以看出,SurfaceComposerClient为WMS返回的是一个SurfaceControl对象,这个SurfaceControl对象包含了surfaceFlinger为SurfaceComposerClient创建的surface,这个surfaceFlinge创建的Surface在Client端的形态为ISurface。这个过程下面分析SurfaceFlinger端的Surface形态时会看到。

SurfaceControl类中还有一个非常重要的成员,它的类型也叫做Surface,定义在frameworks/base/libs/surfaceflinger/Surface.h。这个Surface提供了显示Buffer的管理。在文章的后面再介绍。

@frameworks/base/libs/surfaceflinger_client/Surface.cpp

  1. sp<Surface>SurfaceControl::getSurface()const
  2. {
  3. Mutex::Autolock_l(mLock);
  4. if(mSurfaceData==0){
  5. mSurfaceData=newSurface(const_cast<SurfaceControl*>(this));
  6. }
  7. returnmSurfaceData;
  8. }

1.3.2 SurfaceFlinger端Surface形态

SurfaceFlinger::createSurface@SurfaceFlinger.cpp

  1. sp<Layer>normalLayer;
  2. switch(flags&eFXSurfaceMask){
  3. caseeFXSurfaceNormal:
  4. if(UNLIKELY(flags&ePushBuffers)){
  5. layer=createPushBuffersSurface(client,d,w,h,flags);
  6. }else{
  7. normalLayer=createNormalSurface(client,d,w,h,flags,format);
  8. layer=normalLayer;
  9. }
  10. break;
  11. caseeFXSurfaceBlur:
  12. layer=createBlurSurface(client,d,w,h,flags);
  13. break;
  14. caseeFXSurfaceDim:
  15. layer=createDimSurface(client,d,w,h,flags);
  16. break;
  17. }
  18. if(layer!=0){
  19. layer->initStates(w,h,flags);
  20. layer->setName(name);
  21. ssize_ttoken=addClientLayer(client,layer);
  22. surfaceHandle=layer->getSurface();
  23. if(surfaceHandle!=0){
  24. params->token=token;
  25. params->identity=surfaceHandle->getIdentity();
  26. params->width=w;
  27. params->height=h;
  28. params->format=format;
  29. if(normalLayer!=0){
  30. Mutex::Autolock_l(mStateLock);
  31. mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
  32. }
  33. }

当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::Surface。此时第三个名为Surface类出现了,下一节我们来介绍一下这个Layer的概念。


1.4 Layer

1.4.1 Layer的分类

目前,android中有4中Layer类型,如上图所示。

1.Layer, 普通的Layer,它为每个Client端请求的Surface创建显示Buffer。

2.LayerBuffer,这种Layer它并不会创建显示Buffer,它只是使用已有的Buffer作为显示Buffer,如Camera的preview;

3.LayerBlur,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行模糊处理;

4.LayerDim,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行暗淡处理;


从这中Layer看出,我们分析的重点就是第一种Layer,下面我们着重分析一下普通的Layer。Layer的具体业务我们在下一篇文章中分析

1.4.2 Layer的管理

上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理这个写个Layer呢?SurfaceFlinger维护了2个Vector来管理Layer。

第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。

SurfaceFlinger::createSurface()@SurfaceFlinger.cpp

  1. ssize_ttoken=addClientLayer(client,layer);

第二种方式,将所有的创建的普通的Layer保存起来,以便Client Surface在请求实现Buffer时能够辨识Client Surface对应的Layer。

SurfaceFlinger::createSurface()@SurfaceFlinger.cpp

  1. mLayerMap.add(surfaceHandle->asBinder(),normalLayer);

2. Surface 显示Buffer的存储管理

在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::Surface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface

2.1 窗口绘制

我们先从ViewRoot中分析一下,它是如何显示窗口View的,如何用到Client Surface请求的显示Buffer的。

draw()@ViewRoot.java

  1. Canvascanvas;
  2. try{
  3. intleft=dirty.left;
  4. inttop=dirty.top;
  5. intright=dirty.right;
  6. intbottom=dirty.bottom;
  7. canvas=surface.lockCanvas(dirty);
  8. if(left!=dirty.left||top!=dirty.top||right!=dirty.right||
  9. bottom!=dirty.bottom){
  10. mAttachInfo.mIgnoreDirtyState=true;
  11. }
  12. //TODO:Dothisinnative
  13. canvas.setDensity(mDensity);
上面的代码显示,JAVA Surface 会lock canvas。而 Client Surface的创建就在这个过程中,即下面代码中的第一行getSurface().我们先不管Client Surface的创建,先看看Canvas是如何与Client Surface的显示Buffer关联的。

  1. staticjobjectSurface_lockCanvas(JNIEnv*env,jobjectclazz,jobjectdirtyRect)
  2. {
  3. constsp<Surface>&surface(getSurface(env,clazz));
  4. if(!Surface::isValid(surface))
  5. return0;
  6. SkCanvas*nativeCanvas=(SkCanvas*)env->GetIntField(canvas,no.native_canvas);
  7. SkBitmapbitmap;
  8. ssize_tbpr=info.s*bytesPerPixel(info.format);
  9. bitmap.setConfig(convertPixelFormat(info.format),info.w,info.h,bpr);
  10. if(info.format==PIXEL_FORMAT_RGBX_8888){
  11. bitmap.setIsOpaque(true);
  12. }
  13. if(info.w>0&&info.h>0){
  14. bitmap.setPixels(info.bits);
  15. }else{
  16. //besafewithanemptybitmap.
  17. bitmap.setPixels(NULL);
  18. }
  19. nativeCanvas->setBitmapDevice(bitmap);
  20. SkRegionclipReg;
  21. if(dirtyRegion.isRect()){//verycommoncase
  22. constRectb(dirtyRegion.getBounds());
  23. clipReg.setRect(b.left,b.top,b.right,b.bottom);
  24. }else{
  25. size_tcount;
  26. Rectconst*r=dirtyRegion.getArray(&count);
  27. while(count){
  28. clipReg.op(r->left,r->top,r->right,r->bottom,SkRegion::kUnion_Op);
  29. r++,count--;
  30. }
  31. }
  32. nativeCanvas->clipRegion(clipReg);
  33. intsaveCount=nativeCanvas->save();
  34. env->SetIntField(clazz,so.saveCount,saveCount);
  35. if(dirtyRect){
  36. constRect&bounds(dirtyRegion.getBounds());
  37. env->SetIntField(dirtyRect,ro.l,bounds.left);
  38. env->SetIntField(dirtyRect,ro.t,bounds.top);
  39. env->SetIntField(dirtyRect,ro.r,bounds.right);
  40. env->SetIntField(dirtyRect,ro.b,bounds.bottom);
  41. }
  42. returncanvas;
  43. }

上面的代码,我们可以看出,Canvas的Bitmap设备的设置了Client Surface的显示Buffer为其Bitmap pixel存储空间。

  1. bitmap.setPixels(info.bits);

这样Canvas的绘制空间就有了。下一步就该绘制窗口了。

draw()@ViewRoot.java

  1. try{
  2. canvas.translate(0,-yoff);
  3. if(mTranslator!=null){
  4. mTranslator.translateCanvas(canvas);
  5. }
  6. canvas.setScreenDensity(scalingRequired
  7. ?DisplayMetrics.DENSITY_DEVICE:0);
  8. mView.draw(canvas);
  9. }
其中ViewRoot中的mView为整个窗口的DecorView。


2.2Client Surface的初始化

Client Surface的创建是从ViewRoot首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。

Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。



2.2.1SharedClient

SharedClient是这一部分实现的关键所在,它并不是一个每个Client Surface创建时都会被创建的,整个系统中只有一个SharedClient对象,并且它是在共享内存上创建的,下面代码中可以看出,UserClient在初始化时,提供了一个MemoryHeapBase来供SharedClient创建,MemoryHeapBase是创建的共享内存。

@SurfaceFlinger.cpp

  1. UserClient::UserClient(constsp<SurfaceFlinger>&flinger)
  2. :ctrlblk(0),mBitmap(0),mFlinger(flinger)
  3. {
  4. constintpgsize=getpagesize();
  5. constintcblksize=((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
  6. mCblkHeap=newMemoryHeapBase(cblksize,0,
  7. "SurfaceFlingerClientcontrol-block");
  8. ctrlblk=static_cast<SharedClient*>(mCblkHeap->getBase());
  9. if(ctrlblk){//constructthesharedstructurein-place.
  10. new(ctrlblk)SharedClient;
  11. }
  12. }

SharedClient对象的主要目的其实很简单,就是为系统提供了SharedBufferStack::NUM_LAYERS_MAX(GB上为31)个SharedBufferStack。也就是目前系统同时支持31个Client Surface的创建。关于SharedBufferStack下面再做介绍。

为什么需要将SharedClient设计为共享内存呢?每个Client Surface需要的SharedBufferStack寄存在SharedClient中,而对于每个SharedBufferStack,一方面,Client Surface需要对它进行一些区域尺寸等的设置;另一方面,在render时,Layer需要获得当前Client Surfce对应的SharedBufferStack中获得区域尺寸等设置信息。

class SharedClient@SharedBufferStack.h

  1. SharedBufferStacksurfaces[SharedBufferStack::NUM_LAYERS_MAX];

2.2.2SharedBufferStack

SharedBufferStack在这个模块中所处的地位在上一小节中介绍了,下面主要介绍一下它的作用。
1. 设置当前窗口要显示的区域等信息;
class SharedBufferStack@SharedBufferStack.h
  1. status_tsetDirtyRegion(intbuffer,constRegion&reg);
  2. status_tsetCrop(intbuffer,constRect&reg);
  3. status_tsetTransform(intbuffer,uint8_ttransform);
2. android的图形系统中提供了两个显示Buffer,从上图中我们可以看出Client Surface有2个GraphicBuffer,2个Buffer其中一个显示,称之为Front Buffer,另外一个交给ViewRoot去绘制窗口,称之为Back Buffer。等BackBuffer绘制完成,SurfaceFlinger在将两者调换,这样就大大提高了显示的效率,具体过程下篇文章介绍。
而SharedBufferStack第二个很重要的作用就是提供了一套机制来实现这个调换的过程,以保证提供给ViewRoot的Buffer符合当前Buffer轮转的要求。通过SharedBufferClient::tail和
class SharedBufferStack@SharedBufferStack.h
  1. volatileint32_thead;//server'scurrentfrontbuffer
  2. volatileint32_tavailable;//numberofdequeue-ablebuffers
这几个变量的值来确定 Client Surface中GraphicBuffer的索引,其中SharedBufferClient::tail记录的是BackBuffer的索引;SharedBufferStack::head记录的是FrontBuffer的索引。


2.2.3 Client Surace GraphicBuffer的请求

这里将Client Surface的GraphicBuffer的创建过程以时序图的形式展现出来。


这里需要注意的是,Client Surface的2个GraphicBuffer只有在lock()时才会去创建,而不是在Client Surface被创建的时候创建的。


上一篇: android surfaceflinger研究----显示系统 下一篇: android surfaceflinger研究----SurfaceFlinger loop

前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。如何创建surface,如何显示窗口等等,所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。

android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析,首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface Buffer显示到显示系统中。。

1. Surface机制的静态关系

将这一部分叫做Surface机制,是有别于SurfaceFlinger而言的,android的图形系统中,作为C/S模型两端的WMS和SurfaceFlinger是图形系统业务的核心,但是不把WMS和SurfaceFlinger中间的这层联系搞清楚的话,是很难理解整个图形系统的,在本文中我将两者之间的这个联系关系称之为Surface机制,它的主要任务就是创建一个Surface,ViewRoot在这个Surface上描绘当前的窗口,SurfaceFlinger将这个Surface flinger(扔)给显示系统将其呈现在硬件设备上。其实这里这个Surface在不同的模块中是以不同的形态存在的,唯一不变的就是其对应的显示Buffer。



1.1 ViewRoot和WMS共享Surface

我们知道每个Activity都会有一个ViewRoot作为Activity Window与WMS交互的接口,ViewRoot会绘制整个Activity的窗口View到Surface上,因此我们在ViewRoot中就有了创建Surface的需求。看一下代码中的Surface的定义:

relayoutWindow()@ViewRoot.java

  1. <spanstyle="font-size:13px;">privatefinalSurfacemSurface=newSurface();</span>
Surface()@Surface.java

  1. <spanstyle="font-size:13px;">publicSurface(){
  2. if(DEBUG_RELEASE){
  3. mCreationStack=newException();
  4. }
  5. mCanvas=newCompatibleCanvas();
  6. }</span>
由上面可以看出在ViewRoot中定义的Surface只是一个空壳,那么真正的Surface是在哪里被初始化的呢?大管家WMS中!当ViewRoot请求WMS relayout时,会将ViewSurface中的Surface交给WMS初始化。在WMS中,对应每个WindowState对象,在relayout窗口时,同样会创建一个Surface,wms中的这个Surface会真正的初始化,然后再将这个WMS Surface复制给ViewRoot中的Surface。这么实现的目的就是保证ViewRoot和WMS共享同一个Surface。ViewRoot对Surface进行绘制,WMS对这个Surface进行初始化及管理。很和谐!

relayoutWindow()@ViewRoot.java

  1. <spanstyle="font-size:13px;">intrelayoutResult=sWindowSession.relayout(
  2. mWindow,params,
  3. (int)(mView.mMeasuredWidth*appScale+0.5f),
  4. (int)(mView.mMeasuredHeight*appScale+0.5f),
  5. viewVisibility,insetsPending,mWinFrame,
  6. mPendingContentInsets,mPendingVisibleInsets,
  7. mPendingConfiguration,mSurface);</span>
relayoutWindow()@WindowManagerService.java
  1. <spanstyle="font-size:13px;">Surfacesurface=win.createSurfaceLocked();
  2. if(surface!=null){
  3. outSurface.copyFrom(surface);
  4. win.mReportDestroySurface=false;
  5. win.mSurfacePendingDestroy=false;
  6. if(SHOW_TRANSACTIONS)Slog.i(TAG,
  7. "OUTSURFACE"+outSurface+":copied");
  8. }else{</span>

1.2SurfaceSession

SurfaceSession可以认为是创建Surface过程中,WMS和SurfaceFlinger之间的会话层,通过这个SurfaceSession实现了Surface的创建。


SurfaceSession是JAVA层的概念,@SurfaceSession.java。它对应的native实体是一个SurfaceComposerClient对象。

SurfaceComposerClient通过ComposerService类来获得SurfaceFlinger的IBinder接口,但是光获得SurfaceFlinger的IBinder接口是不够的,要想请求SurfaceFlinger创建一个Surface,还需要向SurfaceFlinger获得一个IBinder接口ISurfaceComposerClient,通过这个ISurfaceComposerClient来请求SurfaceFlinger创建一个Surface,为什么这么绕呢,为什么不直接让SurfaceFlinger创建Surface呢?

站在SurfaceFlinger的角度来考虑,对于SurfaceFlinger来说,可能有多个Client来请求SurfaceFlinger的业务,每个Client可能会请求SurfaceFlinger创建多个Surface,那么SurfaceFlinger本地需要提供一套机制来保存每个client请求创建的Surface,SurfaceFlinger通过为每个client创建一个Client对象实现这个机制,并将这个Client的IBinder接口ISurfaceComposerClient返给SurfaceComposerClient对象。SurfaceComposerClient对象在通过ISurfaceComposerClient去请求创建Surface。

@SurfaceFlinger.h

  1. classClient:publicBnSurfaceComposerClient

@SurfaceComposerClient.cpp
  1. voidSurfaceComposerClient::onFirstRef()
  2. {
  3. sp<ISurfaceComposer>sm(getComposerService());
  4. if(sm!=0){
  5. sp<ISurfaceComposerClient>conn=sm->createConnection();
  6. if(conn!=0){
  7. mClient=conn;
  8. Composer::addClient(this);
  9. mPrebuiltLayerState=newlayer_state_t;
  10. mStatus=NO_ERROR;
  11. }
  12. }
  13. }

下图描述了整个SurfaceSession的内部结构与工作流程。

其中蓝色箭头是SurfaceComposerClient通过ComposerService获得SurfaceFlinger的IBinder接口ISurfaceComposer过程;

红色箭头表示SurfaceComposerClient通过IPC请求SurfaceFlinger创建Client的过程,并获得Client的IBinder接口ISurfaceComposerClient;

绿色箭头表示SurfaceComposerClient通过IPC请求Client创建Surface。



1.3 Surface的形态

上一节我们分析了SurfaceSession的静态结构,得知Surface的创建过程是通过SurfaceSession这个中间会话层去请求SurfaceFlinger去创建的,并且这篇文章中,我们说了半天Surface了,那么究竟我们要创建的Surface究竟是什么样的一个东西呢,它的具体形态是什么呢?这一小节我们就来分析以下Surface的形态。

1.3.1 client端Surface的形态

首先,我们看一下Surface在WMS中定义的代码

createSurfaceLocked()@WindowManagerService.java

  1. mSurface=newSurface(
  2. mSession.mSurfaceSession,mSession.mPid,
  3. mAttrs.getTitle().toString(),
  4. 0,w,h,mAttrs.format,flags);
我们可以看到,它将SurfaceSession对象当作参数传递给了Surface的构造函数。往下看Surface的构造函数。

@Surface.java

  1. publicSurface(SurfaceSessions,
  2. intpid,intdisplay,intw,inth,intformat,intflags)
  3. throwsOutOfResourcesException{
  4. if(DEBUG_RELEASE){
  5. mCreationStack=newException();
  6. }
  7. mCanvas=newCompatibleCanvas();
  8. init(s,pid,null,display,w,h,format,flags);
  9. }
这个构造函数,不同于我们在ViewRoot中看到的Surface的构造函数,这个构造函数并不是一个空壳,它做了本地实体的初始化工作,因此这个Surface才是一个真正的Suface。

Native 函数init回调到SurfaceComposerClient的createSurface()函数,往下的过程在上一节的图中描述的很清楚,流程就不介绍了,同时我们先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?


@SurfaceComposerClient.cpp

  1. sp<SurfaceControl>SurfaceComposerClient::createSurface(
  2. intpid,
  3. constString8&name,
  4. DisplayIDdisplay,
  5. uint32_tw,
  6. uint32_th,
  7. PixelFormatformat,
  8. uint32_tflags)
  9. {
  10. sp<SurfaceControl>result;
  11. if(mStatus==NO_ERROR){
  12. ISurfaceComposerClient::surface_data_tdata;
  13. sp<ISurface>surface=mClient->createSurface(&data,pid,name,
  14. display,w,h,format,flags);
  15. if(surface!=0){
  16. result=newSurfaceControl(this,surface,data,w,h,format,flags);
  17. }
  18. }
  19. returnresult;
  20. }

从上面的代码我们可以看出,SurfaceComposerClient为WMS返回的是一个SurfaceControl对象,这个SurfaceControl对象包含了surfaceFlinger为SurfaceComposerClient创建的surface,这个surfaceFlinge创建的Surface在Client端的形态为ISurface。这个过程下面分析SurfaceFlinger端的Surface形态时会看到。

SurfaceControl类中还有一个非常重要的成员,它的类型也叫做Surface,定义在frameworks/base/libs/surfaceflinger/Surface.h。这个Surface提供了显示Buffer的管理。在文章的后面再介绍。

@frameworks/base/libs/surfaceflinger_client/Surface.cpp

  1. sp<Surface>SurfaceControl::getSurface()const
  2. {
  3. Mutex::Autolock_l(mLock);
  4. if(mSurfaceData==0){
  5. mSurfaceData=newSurface(const_cast<SurfaceControl*>(this));
  6. }
  7. returnmSurfaceData;
  8. }

1.3.2 SurfaceFlinger端Surface形态

SurfaceFlinger::createSurface@SurfaceFlinger.cpp

  1. sp<Layer>normalLayer;
  2. switch(flags&eFXSurfaceMask){
  3. caseeFXSurfaceNormal:
  4. if(UNLIKELY(flags&ePushBuffers)){
  5. layer=createPushBuffersSurface(client,d,w,h,flags);
  6. }else{
  7. normalLayer=createNormalSurface(client,d,w,h,flags,format);
  8. layer=normalLayer;
  9. }
  10. break;
  11. caseeFXSurfaceBlur:
  12. layer=createBlurSurface(client,d,w,h,flags);
  13. break;
  14. caseeFXSurfaceDim:
  15. layer=createDimSurface(client,d,w,h,flags);
  16. break;
  17. }
  18. if(layer!=0){
  19. layer->initStates(w,h,flags);
  20. layer->setName(name);
  21. ssize_ttoken=addClientLayer(client,layer);
  22. surfaceHandle=layer->getSurface();
  23. if(surfaceHandle!=0){
  24. params->token=token;
  25. params->identity=surfaceHandle->getIdentity();
  26. params->width=w;
  27. params->height=h;
  28. params->format=format;
  29. if(normalLayer!=0){
  30. Mutex::Autolock_l(mStateLock);
  31. mLayerMap.add(surfaceHandle->asBinder(),normalLayer);
  32. }
  33. }

当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::Surface。此时第三个名为Surface类出现了,下一节我们来介绍一下这个Layer的概念。


1.4 Layer

1.4.1 Layer的分类

目前,android中有4中Layer类型,如上图所示。

1.Layer, 普通的Layer,它为每个Client端请求的Surface创建显示Buffer。

2.LayerBuffer,这种Layer它并不会创建显示Buffer,它只是使用已有的Buffer作为显示Buffer,如Camera的preview;

3.LayerBlur,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行模糊处理;

4.LayerDim,这种Layer也不会创建显示Buffer,它只是将通过这个Layer将原来FrameBuffer上的数据进行暗淡处理;


从这中Layer看出,我们分析的重点就是第一种Layer,下面我们着重分析一下普通的Layer。Layer的具体业务我们在下一篇文章中分析

1.4.2 Layer的管理

上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理这个写个Layer呢?SurfaceFlinger维护了2个Vector来管理Layer。

第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。

SurfaceFlinger::createSurface()@SurfaceFlinger.cpp

  1. ssize_ttoken=addClientLayer(client,layer);

第二种方式,将所有的创建的普通的Layer保存起来,以便Client Surface在请求实现Buffer时能够辨识Client Surface对应的Layer。

SurfaceFlinger::createSurface()@SurfaceFlinger.cpp

  1. mLayerMap.add(surfaceHandle->asBinder(),normalLayer);

2. Surface 显示Buffer的存储管理

在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::Surface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface

2.1 窗口绘制

我们先从ViewRoot中分析一下,它是如何显示窗口View的,如何用到Client Surface请求的显示Buffer的。

draw()@ViewRoot.java

  1. Canvascanvas;
  2. try{
  3. intleft=dirty.left;
  4. inttop=dirty.top;
  5. intright=dirty.right;
  6. intbottom=dirty.bottom;
  7. canvas=surface.lockCanvas(dirty);
  8. if(left!=dirty.left||top!=dirty.top||right!=dirty.right||
  9. bottom!=dirty.bottom){
  10. mAttachInfo.mIgnoreDirtyState=true;
  11. }
  12. //TODO:Dothisinnative
  13. canvas.setDensity(mDensity);
上面的代码显示,JAVA Surface 会lock canvas。而 Client Surface的创建就在这个过程中,即下面代码中的第一行getSurface().我们先不管Client Surface的创建,先看看Canvas是如何与Client Surface的显示Buffer关联的。

  1. staticjobjectSurface_lockCanvas(JNIEnv*env,jobjectclazz,jobjectdirtyRect)
  2. {
  3. constsp<Surface>&surface(getSurface(env,clazz));
  4. if(!Surface::isValid(surface))
  5. return0;
  6. SkCanvas*nativeCanvas=(SkCanvas*)env->GetIntField(canvas,no.native_canvas);
  7. SkBitmapbitmap;
  8. ssize_tbpr=info.s*bytesPerPixel(info.format);
  9. bitmap.setConfig(convertPixelFormat(info.format),info.w,info.h,bpr);
  10. if(info.format==PIXEL_FORMAT_RGBX_8888){
  11. bitmap.setIsOpaque(true);
  12. }
  13. if(info.w>0&&info.h>0){
  14. bitmap.setPixels(info.bits);
  15. }else{
  16. //besafewithanemptybitmap.
  17. bitmap.setPixels(NULL);
  18. }
  19. nativeCanvas->setBitmapDevice(bitmap);
  20. SkRegionclipReg;
  21. if(dirtyRegion.isRect()){//verycommoncase
  22. constRectb(dirtyRegion.getBounds());
  23. clipReg.setRect(b.left,b.top,b.right,b.bottom);
  24. }else{
  25. size_tcount;
  26. Rectconst*r=dirtyRegion.getArray(&count);
  27. while(count){
  28. clipReg.op(r->left,r->top,r->right,r->bottom,SkRegion::kUnion_Op);
  29. r++,count--;
  30. }
  31. }
  32. nativeCanvas->clipRegion(clipReg);
  33. intsaveCount=nativeCanvas->save();
  34. env->SetIntField(clazz,so.saveCount,saveCount);
  35. if(dirtyRect){
  36. constRect&bounds(dirtyRegion.getBounds());
  37. env->SetIntField(dirtyRect,ro.l,bounds.left);
  38. env->SetIntField(dirtyRect,ro.t,bounds.top);
  39. env->SetIntField(dirtyRect,ro.r,bounds.right);
  40. env->SetIntField(dirtyRect,ro.b,bounds.bottom);
  41. }
  42. returncanvas;
  43. }

上面的代码,我们可以看出,Canvas的Bitmap设备的设置了Client Surface的显示Buffer为其Bitmap pixel存储空间。

  1. bitmap.setPixels(info.bits);

这样Canvas的绘制空间就有了。下一步就该绘制窗口了。

draw()@ViewRoot.java

  1. try{
  2. canvas.translate(0,-yoff);
  3. if(mTranslator!=null){
  4. mTranslator.translateCanvas(canvas);
  5. }
  6. canvas.setScreenDensity(scalingRequired
  7. ?DisplayMetrics.DENSITY_DEVICE:0);
  8. mView.draw(canvas);
  9. }
其中ViewRoot中的mView为整个窗口的DecorView。


2.2Client Surface的初始化

Client Surface的创建是从ViewRoot首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。

Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。



2.2.1SharedClient

SharedClient是这一部分实现的关键所在,它并不是一个每个Client Surface创建时都会被创建的,整个系统中只有一个SharedClient对象,并且它是在共享内存上创建的,下面代码中可以看出,UserClient在初始化时,提供了一个MemoryHeapBase来供SharedClient创建,MemoryHeapBase是创建的共享内存。

@SurfaceFlinger.cpp

  1. UserClient::UserClient(constsp<SurfaceFlinger>&flinger)
  2. :ctrlblk(0),mBitmap(0),mFlinger(flinger)
  3. {
  4. constintpgsize=getpagesize();
  5. constintcblksize=((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
  6. mCblkHeap=newMemoryHeapBase(cblksize,0,
  7. "SurfaceFlingerClientcontrol-block");
  8. ctrlblk=static_cast<SharedClient*>(mCblkHeap->getBase());
  9. if(ctrlblk){//constructthesharedstructurein-place.
  10. new(ctrlblk)SharedClient;
  11. }
  12. }

SharedClient对象的主要目的其实很简单,就是为系统提供了SharedBufferStack::NUM_LAYERS_MAX(GB上为31)个SharedBufferStack。也就是目前系统同时支持31个Client Surface的创建。关于SharedBufferStack下面再做介绍。

为什么需要将SharedClient设计为共享内存呢?每个Client Surface需要的SharedBufferStack寄存在SharedClient中,而对于每个SharedBufferStack,一方面,Client Surface需要对它进行一些区域尺寸等的设置;另一方面,在render时,Layer需要获得当前Client Surfce对应的SharedBufferStack中获得区域尺寸等设置信息。

class SharedClient@SharedBufferStack.h

  1. SharedBufferStacksurfaces[SharedBufferStack::NUM_LAYERS_MAX];

2.2.2SharedBufferStack

SharedBufferStack在这个模块中所处的地位在上一小节中介绍了,下面主要介绍一下它的作用。
1. 设置当前窗口要显示的区域等信息;
class SharedBufferStack@SharedBufferStack.h
  1. status_tsetDirtyRegion(intbuffer,constRegion&reg);
  2. status_tsetCrop(intbuffer,constRect&reg);
  3. status_tsetTransform(intbuffer,uint8_ttransform);
2. android的图形系统中提供了两个显示Buffer,从上图中我们可以看出Client Surface有2个GraphicBuffer,2个Buffer其中一个显示,称之为Front Buffer,另外一个交给ViewRoot去绘制窗口,称之为Back Buffer。等BackBuffer绘制完成,SurfaceFlinger在将两者调换,这样就大大提高了显示的效率,具体过程下篇文章介绍。
而SharedBufferStack第二个很重要的作用就是提供了一套机制来实现这个调换的过程,以保证提供给ViewRoot的Buffer符合当前Buffer轮转的要求。通过SharedBufferClient::tail和
class SharedBufferStack@SharedBufferStack.h
  1. volatileint32_thead;//server'scurrentfrontbuffer
  2. volatileint32_tavailable;//numberofdequeue-ablebuffers
这几个变量的值来确定 Client Surface中GraphicBuffer的索引,其中SharedBufferClient::tail记录的是BackBuffer的索引;SharedBufferStack::head记录的是FrontBuffer的索引。


2.2.3 Client Surace GraphicBuffer的请求

这里将Client Surface的GraphicBuffer的创建过程以时序图的形式展现出来。


这里需要注意的是,Client Surface的2个GraphicBuffer只有在lock()时才会去创建,而不是在Client Surface被创建的时候创建的。


SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务是在 服务是在 服务是在 SystemSystemSystemSystemSystem 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 UI 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值