轉自:http://blog.csdn.net/windskier/article/details/7041610
前一篇文章介紹了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
- <span style="font-size:13px;"> private final Surface mSurface = new Surface();</span>
- <span style="font-size:13px;"> public Surface() {
- if (DEBUG_RELEASE) {
- mCreationStack = new Exception();
- }
- mCanvas = new CompatibleCanvas();
- }</span>
relayoutWindow()@ViewRoot.java
- <span style="font-size:13px;"> 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);</span>
- <span style="font-size:13px;"> 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 {</span>
1.2 SurfaceSession
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
@SurfaceComposerClient.cpp
- 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。
1.3 Surface的形態
上一節我們分析了SurfaceSession的靜態結構,得知Surface的創建過程是通過SurfaceSession這個中間會話層去請求SurfaceFlinger去創建的,並且這篇文章中,我們說了半天Surface了,那麼究竟我們要創建的Surface究竟是什麼樣的一個東西呢,它的具體形態是什麼呢?這一小節我們就來分析以下Surface的形態。
1.3.1 client端Surface的形態
首先,我們看一下Surface在WMS中定義的代碼
createSurfaceLocked()@WindowManagerService.java
- mSurface = new Surface(
- mSession.mSurfaceSession, mSession.mPid,
- mAttrs.getTitle().toString(),
- 0, w, h, mAttrs.format, flags);
@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);
- }
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;
- }
1.3.2 SurfaceFlinger端Surface形態
- 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的概念。
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
- ssize_t token = addClientLayer(client, layer);
第二種方式,將所有的創建的普通的Layer保存起來,以便Client Surface在請求實現Buffer時能夠辨識Client Surface對應的Layer。
SurfaceFlinger::createSurface()@SurfaceFlinger.cpp
- 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 窗口繪製
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);
- 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;
- }
上面的代碼,我們可以看出,Canvas的Bitmap設備的設置了Client Surface的顯示Buffer爲其Bitmap pixel存儲空間。
- 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);
- }
2.2 Client Surface的初始化
Client Surface的創建是從ViewRoot首次Lock canvas時進行的,這麼做的目的可能也是爲了節約空間,減少不必要的開支。
Client Surface的初始化和顯示Buffer的管理過程比較複雜,下圖給出了這一部分的一個靜態結構圖,有些東西從圖上表現不出來,下面我簡單的介紹一下。
2.2.1 SharedClient
SharedClient是這一部分實現的關鍵所在,它並不是一個每個Client Surface創建時都會被創建的,整個系統中只有一個SharedClient對象,並且它是在共享內存上創建的,下面代碼中可以看出,UserClient在初始化時,提供了一個MemoryHeapBase來供SharedClient創建,MemoryHeapBase是創建的共享內存。
@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對象的主要目的其實很簡單,就是爲系統提供了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 [email protected]
- SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
2.2.2 SharedBufferStack
- 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的創建過程以時序圖的形式展現出來。
這裏需要注意的是,Client Surface的2個GraphicBuffer只有在lock()時纔會去創建,而不是在Client Surface被創建的時候創建的。