GUI 是任何系統都很重要的一塊。
android GUI大體分為4大塊。
1)SurfaceFlinger
2)WMS
3)View機制
4)InputMethod
這塊內容非常之多,但是理解后,可以觸類旁通,其實現在主流的系統,包括andorid,ios在構架上,都是有很多相識之處。
我們先來講SurfaceFlinger
1.OpenGL & OpenGL ES
OPenGL ES 是android系統繪畫的基礎。關於OpenGL部分,可以百度了解下。
先來看一個OpenGL & SurfaceFlinger之間的框架圖:

2.Android的硬件接口HAL
2.1硬件接口的抽象
2.2接口的穩定性
Android已經把各個硬件都接口都統一定義在:
libhardware/include/hardware/ 具體代碼可以參考:https://github.com/CyanogenMod/android_hardware_libhardware/tree/cm-12.0/include/hardware
3.Android顯示設備:Gralloc & FrameBuffer
3.1Gralloc模塊的加載

FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) { hw_module_t const* module; if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { int stride; int err; int i; err = framebuffer_open(module, &fbDev); ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); err = gralloc_open(module, &grDev); ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); // bail out if we can't initialize the modules if (!fbDev || !grDev) return; mUpdateOnDemand = (fbDev->setUpdateRect != 0); // initialize the buffer FIFO if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS && fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){ mNumBuffers = fbDev->numFramebuffers; } else { mNumBuffers = MIN_NUM_FRAME_BUFFERS; } mNumFreeBuffers = mNumBuffers; mBufferHead = mNumBuffers-1; /* * This does not actually change the framebuffer format. It merely * fakes this format to surfaceflinger so that when it creates * framebuffer surfaces it will use this format. It's really a giant * HACK to allow interworking with buggy gralloc+GPU driver * implementations. You should *NEVER* need to set this for shipping * devices. */ #ifdef FRAMEBUFFER_FORCE_FORMAT *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT; #endif for (i = 0; i < mNumBuffers; i++) { buffers[i] = new NativeBuffer( fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); } for (i = 0; i < mNumBuffers; i++) { err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", i, fbDev->width, fbDev->height, strerror(-err)); if (err) { mNumBuffers = i; mNumFreeBuffers = i; mBufferHead = mNumBuffers-1; break; } } const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; } else { ALOGE("Couldn't get gralloc module"); } ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; ANativeWindow::queueBuffer = queueBuffer; ANativeWindow::query = query; ANativeWindow::perform = perform; ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED; ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED; ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED; }
我們繼續深入看:
galloc的父類,最終是:
libhardware\include\hardware\hardware.h
typedef struct hw_module_methods_t { /** Open a specific device */ int (*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device); } hw_module_methods_t;
只有一個open方法,也就是所有的廠商都需要實現開啟設備的方法。
看下fb的打開的代碼:
libhardware\modules\gralloc\framebuffer.cpp
int fb_device_open(hw_module_t const* module, const char* name, hw_device_t** device) { int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { /* initialize our state here */ fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = fb_close; dev->device.setSwapInterval = fb_setSwapInterval; dev->device.post = fb_post; dev->device.setUpdateRect = 0; private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); if (status >= 0) { int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); int format = (m->info.bits_per_pixel == 32) ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888) : HAL_PIXEL_FORMAT_RGB_565; const_cast<uint32_t&>(dev->device.flags) = 0; const_cast<uint32_t&>(dev->device.width) = m->info.xres; const_cast<uint32_t&>(dev->device.height) = m->info.yres; const_cast<int&>(dev->device.stride) = stride; const_cast<int&>(dev->device.format) = format; const_cast<float&>(dev->device.xdpi) = m->xdpi; const_cast<float&>(dev->device.ydpi) = m->ydpi; const_cast<float&>(dev->device.fps) = m->fps; const_cast<int&>(dev->device.minSwapInterval) = 1; const_cast<int&>(dev->device.maxSwapInterval) = 1; *device = &dev->device.common; } } return status; }
首先check設備名是否正確。
status = mapFrameBuffer(m);
然后是建立殼 & 核心間的關系。
這樣就打開了fb設備。
在回到FrameBufferNativeWindow 可以看到:
err = framebuffer_open(module, &fbDev); ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); err = gralloc_open(module, &grDev); ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
fb打開的驅動信息在fbDev,gralloc打開的信息在grDev中。
fbDev負責的是主屏幕,grDev負責圖形緩沖去的分配和釋放。
所以FrameBufferNativeWindow控制這SurfaceFlinger的基礎。
4.FrameBufferNativeWindow
4.1FramebufferNativeWindow
在OpenGL中,我們不斷提及本地窗口的概念,在Android中,native window一共由2個。首先看下定義的地方:
class FramebufferNativeWindow : public ANativeObjectBase< ANativeWindow, FramebufferNativeWindow, LightRefBase<FramebufferNativeWindow> > {
ANativeWindow是什么東西?
ANativeWindow是OpenGL 在android平台的顯示類型。
所以FramebufferNativeWindow就是一種Open GL可以顯示的類型。
FramebufferNativeWindow的構造函數上面已經貼出來了,進一步分析如下:
1)加載module,上面已經分析過了。
2)打開fb & gralloc,也已經分析過了。
3)根據fb的設備屬性,獲得buffer數。這個buffer后面會解釋。
4)給每個buffer初始化,並分配空間。這里new NativeBuffer只是指定buffer的類型,或者分配了一個指針,但是沒有分配內存,所以還需要alloc操作。
5)為本地窗口屬性賦值。
目前buffer默認值是在2~3,后面會介紹3緩沖技術,就會用到3個buffer。
雙緩沖技術:
把一組圖畫,畫到屏幕上,畫圖是需要時間的,如果時間間隔比較長,圖片就是一個一個的畫在屏幕的,看上去就會卡。
如果先把圖片放在一個緩沖buffer中,待全部畫好后,把buffer直接顯示在屏幕上,這就是雙緩沖技術。
4.2dequeuebuffer
int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { FramebufferNativeWindow* self = getSelf(window); Mutex::Autolock _l(self->mutex); framebuffer_device_t* fb = self->fbDev; int index = self->mBufferHead++; if (self->mBufferHead >= self->mNumBuffers) self->mBufferHead = 0; // wait for a free non-front buffer while (self->mNumFreeBuffers < 2) { self->mCondition.wait(self->mutex); } ALOG_ASSERT(self->buffers[index] != self->front); // get this buffer self->mNumFreeBuffers--; self->mCurrentBufferIndex = index; *buffer = self->buffers[index].get(); *fenceFd = -1; return 0; }
代碼不多,但是卻是核心功能,通過它來獲取一塊可渲染的buffer。
1)獲取FramebufferNativeWindow對象。為什么沒有使用this 而是使用了傳入ANativeWindow的方式,此處我們並不關心。
2)獲得一個Autolock的鎖,函數結束,自動解鎖。
3)獲取mBufferHead變量,這里自增,也就是使用下一個buffer,一共只有3個,(原因上面已經解釋),所以循環取值。
4)如果沒有可用的緩沖區,等待bufferqueue釋放。一旦獲取后,可用buffer就自減
5.Surface
Surface是另一個本地窗口,主要和app這邊交互。注意:app層java代碼無法直接調用surface,只是概念上surface屬於app這一層的。
首先Surface是ANativeWindow的一個子類。
可以推測,surface需要解決如下幾個問題:
1)面向上層(java層)提供畫板。由誰來分配這塊內存
2)與SurfaceFlinger是什么關系
Surface::Surface( const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
sp<IGraphicBufferProducer>& bufferProducer 是分配surface內存的。它到底是什么呢?

SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
SurfaceFlinger是BnSurfaceComposer的一個子類。也就是ISurfaceComposer的一個實現。
surface雖然是為app層服務的,但是本質上還是由SurfaceFlinger來管理的。
SurfaceFlinger怎么創建和管理surface,需要通過BufferQueue,將在下一篇討論。
參考:
《深入理解android內核設計思想》 林學森