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之间的框架图:

android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论
从底层往上看:
1)linux内核提供统一的设备驱动,/dev/graphics/fb*
2) Android HAL 提供2个接口 Gralloc & fb
fb 负责打开framebuffer,提供接口操作。gralloc负责管理帧缓冲区的分配和释放。
composer是HAL中另一个重要的功能,它主要是给厂商定制UI合成。SurfaceFlinger中负责HWComposer会用到这个功能。
而且关键是HWComposer还负责产生VSync信号,这是本期SurfaceFlinger的重点。
3)由于OpenGL是一套通用的库(大部分就是接口),所以它需要一个本地的实现。andorid平台OpenGL有2个本地窗口,FrameBufferNativeWindow & Surface。
4)OpenGL可以有软件 或者依托于硬件实现,具体的运行状态,就是由EGL来配置。
5)SurfaceFlinger持有一个成员数组mDisplays来支持各种显示设备。DisplayDevices在初始化的时候调用EGL来搭建OpenGL的环境。
 

2.Android的硬件接口HAL

HAL需要满足android系统和厂商的要求

2.1硬件接口的抽象

从面向对象角度来讲,接口的概念就是由C++非常容易实现,但是HAL很多代码是C语言描述的。
这就需要一种技巧来实现面向对象。
定义一种结构,子类的成员变量第一个类型是父类的结构就可以了。抽象方法可以用函数指针来实现。
其实这个就是C++多态实现的基本原理,具体可参考《深入理解C++对象模型》

2.2接口的稳定性

Android已经把各个硬件都接口都统一定义在:

libhardware/include/hardware/ 具体代码可以参考:https://github.com/CyanogenMod/android_hardware_libhardware/tree/cm-12.0/include/hardware

 

3.Android显示设备:Gralloc &  FrameBuffer

FrameBuffer是linux环境下显示设备的统一接口。从而让用户设备不需要做太多的操作,就可以适配多种显示设备。
FramwBuffer本质上就是一套接口。android系统不会直接操作显示驱动,而通过HAL层来封装。而HAL中操作驱动的模块就是
gralloc。

3.1Gralloc模块的加载

gralloc通过FrameBufferNativeWindow 来加载的:
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;
}
FramebufferNativeWindow

我们继续深入看:

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设备名是否正确。

相关文章: