前一篇文章介绍了android的显示系统,这篇文章中,我们把视角往上层移动一下,研究一下framework是如何与surfaceflinger进行业务交互的。如何创建surface,如何显示窗口等等,所有的这一切都是通过系统服务WindowManagerService与surfaceflinger来进行的。
android中的Surface机制这一块代码写的比较难理解,光叫Surface的类就有3个,因此本篇文章从两部分来分析,首先,想要理解Surface机制,还是需要首先理清各个类之间的关系。其次,在理解了整个Surface机制的类关系之后,到时我们再结合前一篇文章中对显示系统的介绍,研究一下一个Surface是如何和显示系统建立起联系来的,这个联系主要是指Surface的显示buffer的存储管理。在下篇文章中,再分析SurfaceFlinger是如何将已经存储了窗口图形数据的Surface Buffer显示到显示系统中。。
relayoutWindow()@ViewRoot.java
private final Surface mSurface = new Surface();
Surface()@Surface.java
public Surface() {
if (DEBUG_RELEASE) {
mCreationStack = new Exception();
}
mCanvas = new CompatibleCanvas();
}
由上面可以看出在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
int relayoutResult = sWindowSession.relayout(
mWindow, params,
(int) (mView.mMeasuredWidth * appScale + 0.5f),
(int) (mView.mMeasuredHeight * appScale + 0.5f),
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);
relayoutWindow()@WindowManagerService.java Surface surface = win.createSurfaceLocked();
if (surface != null) {
outSurface.copyFrom(surface);
win.mReportDestroySurface = false;
win.mSurfacePendingDestroy = false;
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
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
class Client : public BnSurfaceComposerClient
void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { mClient = conn; Composer::addClient(this); mPrebuiltLayerState = new layer_state_t; mStatus = NO_ERROR; } } }
下图描述了整个SurfaceSession的内部结构与工作流程。
其中蓝色箭头是SurfaceComposerClient通过ComposerService获得SurfaceFlinger的IBinder接口ISurfaceComposer过程;
红色箭头表示SurfaceComposerClient通过IPC请求SurfaceFlinger创建Client的过程,并获得Client的IBinder接口ISurfaceComposerClient;
绿色箭头表示SurfaceComposerClient通过IPC请求Client创建Surface。
上一节我们分析了SurfaceSession的静态结构,得知Surface的创建过程是通过SurfaceSession这个中间会话层去请求SurfaceFlinger去创建的,并且这篇文章中,我们说了半天Surface了,那么究竟我们要创建的Surface究竟是什么样的一个东西呢,它的具体形态是什么呢?这一小节我们就来分析以下Surface的形态。
首先,我们看一下Surface在WMS中定义的代码
createSurfaceLocked()@WindowManagerService.java
mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, mAttrs.format, flags);我们可以看到,它将SurfaceSession对象当作参数传递给了Surface的构造函数。往下看Surface的构造函数。
@Surface.java
public Surface(SurfaceSession s, int pid, int display, int w, int h, int format, int flags) throws OutOfResourcesException { if (DEBUG_RELEASE) { mCreationStack = new Exception(); } mCanvas = new CompatibleCanvas(); init(s,pid,null,display,w,h,format,flags); }这个构造函数,不同于我们在ViewRoot中看到的Surface的构造函数,这个构造函数并不是一个空壳,它做了本地实体的初始化工作,因此这个Surface才是一个真正的Suface。
Native 函数init回调到SurfaceComposerClient的createSurface()函数,往下的过程在上一节的图中描述的很清楚,流程就不介绍了,同时我们先不管SurfaceFlinger为SurfaceComposerClient创建的Surface到底是一个什么东西,我们先看看SurfaceComposerClient为WMS创建的是一个什么东西?
@SurfaceComposerClient.cpp
sp<SurfaceControl> SurfaceComposerClient::createSurface( int pid, const String8& name, DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp<SurfaceControl> result; if (mStatus == NO_ERROR) { ISurfaceComposerClient::surface_data_t data; sp<ISurface> surface = mClient->createSurface(&data, pid, name, display, w, h, format, flags); if (surface != 0) { result = new SurfaceControl(this, surface, data, w, h, format, flags); } } return result; }
从上面的代码我们可以看出,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
sp<Surface> SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); } return mSurfaceData; }
sp<Layer> normalLayer; switch (flags & eFXSurfaceMask) { case eFXSurfaceNormal: if (UNLIKELY(flags & ePushBuffers)) { layer = createPushBuffersSurface(client, d, w, h, flags); } else { normalLayer = createNormalSurface(client, d, w, h, flags, format); layer = normalLayer; } break; case eFXSurfaceBlur: layer = createBlurSurface(client, d, w, h, flags); break; case eFXSurfaceDim: layer = createDimSurface(client, d, w, h, flags); break; } if (layer != 0) { layer->initStates(w, h, flags); layer->setName(name); ssize_t token = addClientLayer(client, layer); surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) { params->token = token; params->identity = surfaceHandle->getIdentity(); params->width = w; params->height = h; params->format = format; if (normalLayer != 0) { Mutex::Autolock _l(mStateLock); mLayerMap.add(surfaceHandle->asBinder(), normalLayer); } }
当client请求SurfaceFlinger创建Surface时,SurfaceFlinger首先根据WMS提供的窗口的属性来一个命名为Layer概念的对象,然后再根据Layer创建它的子类对象LayerBaseClient::Surface。此时第三个名为Surface类出现了,下一节我们来介绍一下这个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的具体业务我们在下一篇文章中分析
上文我们在分析SurfaceSession的时候,也分析过,一个Client可能会创建多个Surface,也就是要创建多个Layer,那么SurfaceFlinger端如何管理这个写个Layer呢?SurfaceFlinger维护了2个Vector来管理Layer。
第一种方式,我们知道SurfaceFlinger会为每个SurfaceSession创建一个Client对象,这第一种方式就是将所有为某一个SurfacSession创建的Layer保存在它对应的Client对象中。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
ssize_t token = addClientLayer(client, layer);
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
在前文介绍Client端的Surface形态的内容时,我们提到SurfaceControl中还会维护一个名为Surface对象,它定义在 frameworks/base/libs/surfaceflinger/Surface.h中,它负责向LayerBaseClient::Surface请求显示Buffer,同时将显示Buffer交给JAVA Surface的Canvas去绘制窗口,我们称这个Surface为Client Surface。
draw()@ViewRoot.java
Canvas canvas; try { int left = dirty.left; int top = dirty.top; int right = dirty.right; int bottom = dirty.bottom; canvas = surface.lockCanvas(dirty); if (left != dirty.left || top != dirty.top || right != dirty.right || bottom != dirty.bottom) { mAttachInfo.mIgnoreDirtyState = true; } // TODO: Do this in native canvas.setDensity(mDensity);上面的代码显示,JAVA Surface 会lock canvas。而 Client Surface的创建就在这个过程中,即下面代码中的第一行getSurface().我们先不管Client Surface的创建,先看看Canvas是如何与Client Surface的显示Buffer关联的。
static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) { const sp<Surface>& surface(getSurface(env, clazz)); if (!Surface::isValid(surface)) return 0; SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); SkBitmap bitmap; ssize_t bpr = info.s * bytesPerPixel(info.format); bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); if (info.format == PIXEL_FORMAT_RGBX_8888) { bitmap.setIsOpaque(true); } if (info.w > 0 && info.h > 0) { bitmap.setPixels(info.bits); } else { // be safe with an empty bitmap. bitmap.setPixels(NULL); } nativeCanvas->setBitmapDevice(bitmap); SkRegion clipReg; if (dirtyRegion.isRect()) { // very common case const Rect b(dirtyRegion.getBounds()); clipReg.setRect(b.left, b.top, b.right, b.bottom); } else { size_t count; Rect const* r = dirtyRegion.getArray(&count); while (count) { clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op); r++, count--; } } nativeCanvas->clipRegion(clipReg); int saveCount = nativeCanvas->save(); env->SetIntField(clazz, so.saveCount, saveCount); if (dirtyRect) { const Rect& bounds(dirtyRegion.getBounds()); env->SetIntField(dirtyRect, ro.l, bounds.left); env->SetIntField(dirtyRect, ro.t, bounds.top); env->SetIntField(dirtyRect, ro.r, bounds.right); env->SetIntField(dirtyRect, ro.b, bounds.bottom); } return canvas; }
bitmap.setPixels(info.bits);
这样Canvas的绘制空间就有了。下一步就该绘制窗口了。
draw()@ViewRoot.java
try { canvas.translate(0, -yoff); if (mTranslator != null) { mTranslator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); mView.draw(canvas); }其中ViewRoot中的mView为整个窗口的DecorView。
Client Surface的创建是从ViewRoot首次Lock canvas时进行的,这么做的目的可能也是为了节约空间,减少不必要的开支。
Client Surface的初始化和显示Buffer的管理过程比较复杂,下图给出了这一部分的一个静态结构图,有些东西从图上表现不出来,下面我简单的介绍一下。
@SurfaceFlinger.cpp
UserClient::UserClient(const sp<SurfaceFlinger>& flinger) : ctrlblk(0), mBitmap(0), mFlinger(flinger) { const int pgsize = getpagesize(); const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1)); mCblkHeap = new MemoryHeapBase(cblksize, 0, "SurfaceFlinger Client control-block"); ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); if (ctrlblk) { // construct the shared structure in-place. new(ctrlblk) SharedClient; } }
为什么需要将SharedClient设计为共享内存呢?每个Client Surface需要的SharedBufferStack寄存在SharedClient中,而对于每个SharedBufferStack,一方面,Client Surface需要对它进行一些区域尺寸等的设置;另一方面,在render时,Layer需要获得当前Client Surfce对应的SharedBufferStack中获得区域尺寸等设置信息。
class [email protected]
SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
status_t setDirtyRegion(int buffer, const Region& reg); status_t setCrop(int buffer, const Rect& reg); status_t setTransform(int buffer, uint8_t transform);
volatile int32_t head; // server's current front buffer volatile int32_t available; // number of dequeue-able buffers这几个变量的值来确定 Client Surface中GraphicBuffer的索引,其中SharedBufferClient::tail记录的是BackBuffer的索引;SharedBufferStack::head记录的是FrontBuffer的索引。
这里将Client Surface的GraphicBuffer的创建过程以时序图的形式展现出来。
这里需要注意的是,Client Surface的2个GraphicBuffer只有在lock()时才会去创建,而不是在Client Surface被创建的时候创建的。