GUI即是图形用户界面,可以说任何操作系统中都占据非常重要的位置,因为它是用户对操作系统最直接的感官体验。一款优秀的图形界面系统至少满足以下几个条件。
流畅性 :评判GUI系统重要准则之一。
友好性:GUI直接面向用户,操作友好直接影响用户体验。
可拓展性 :意味着用户或者开发者可以在原来基础上延伸,添加新的界面和交互方式。
因为Android的GUI系统是基于OpenGL/EGL来实现的,所以掌握一定OpenGL基础只是对于分析Android系统源码会有帮助。
一、OpenGL ES 与EGL
SurfaceFlinger是GUI的核心,从OpenGL角度来讲算是一个应用程序。
按照上图分析
1. Linux内核提供了统一的framebuffer显示驱动。设备节点在/dev/graphics/fb* 或者/dev/fb* ,其中fb0表示一个Monitor。
2. Android的HAL提供了Gralloc,包括fb和gralloc两个设备 。gralloc负责打开内核中的framebuffer、初始化配置、提供post、setSwapInterval等操作接口 。 说明上层元素只能通过Gralloc来间接访问帧缓冲区,从而保证系统对framebuffer有序使用和统一管理。
3. OpenGL是一个通用的函数库。 不同平台需要与具体平台窗口系统建立关联,保证正常工作,从图中FrameBufferNativeWindow可以看出,它是扶着OpenGL ES与Android系统中介 。
4. OpenGL只是一个协议,具体实现采用软件,也可以依托硬件。 通过读取efl.cfg这个配置文件,然后用户设定动态加载libagl 或者libhgl 。
5. SurfaceFlinger中有一个显示设备
6.很多模块可以调用OpenGL ES提供的API。包括SurfaceFlinger,DisplayDevice等。
7.与OpenGL ES相关的模块分以下几类: 配置类、依赖类、使用类
二、Android的硬件接口---HAL
2.1硬件接口抽象
这里抽象涉及了继承关系,让子结构地一个成员变量是父类结构即可。 觉里Grolloc
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct gralloc_module_t {
struct hw_module_t common;
/*
* (*registerBuffer)() must be called before a buffer_handle_t that has not
* been created with (*alloc_device_t::alloc)() can be used.
*
* This is intended to be used with buffer_handle_t's that have been
* received in this process through IPC.
*
* This function checks that the handle is indeed a valid one and prepares
* it for use with (*lock)() and (*unlock)().
*
* It is not necessary to call (*registerBuffer)() on a handle created
* with (*alloc_device_t::alloc)().
*
* returns an error if this buffer_handle_t is not valid.
*/
int (*registerBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
从函数的注释可以看出,每一个硬件必须有一个名称为HAL_MODULE_INFO_SYM的变量。 其次变量的数据结构要以hw_module_t开头,后面才是硬件模块持有的部分,这就体现了继承关系。
2.2 接口稳定性
对于硬件设备商来说,它所提供的HAL接口必须是稳定不变的----android系统已经预先定义好了这些接口,硬件设备商只需要按照要求来实现即可。 HAL各硬件接口的定义统一放置在工程源码中:
2.3 灵活使用方法
比如说Androis手机设备A和B,分别采用了GPS1和GPS2两个厂家GPS。那么需要考虑那些问题呢?
对于GPS硬件厂家来说 ,只需要按照Android的要求来实现HAL接口。
对于Android手机开发商来说,只需要移植硬件厂家提供的HAL库即可。
对于Android团队来说,Android系统必须提供完整、可靠并且稳定的HAL机制。
三、Android终端显示设备的化身
3.1Gralloc与Framebuffer
Gralloc读应模块是有FramebuffNativeWindow的构造函数中加载的。
举例Gralloc
struct private_module_t HAL_MODULE_INFO_SYM = {
.base = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = GRALLOC_HARDWARE_MODULE_ID,
.name = "Graphics Memory Allocator Module",
.author = "The Android Open Source Project",
.methods = &gralloc_module_methods
},
.registerBuffer = gralloc_register_buffer,
.unregisterBuffer = gralloc_unregister_buffer,
.lock = gralloc_lock,
.unlock = gralloc_unlock,
},
.framebuffer = 0,
.flags = 0,
.numBuffers = 0,
.bufferMask = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
.currentBuffer = 0,
};
可以看到针对Gralloc的硬件模块ID为 GRALLOC_HARDWARE_MODULE_ID ,按照hw_get_module的做法,它会在如下路径查找与ID值匹配的库。
#define HAL_LIBRARY PATH1 "/system/lib/hw"
#define HAL_LIBRARY PATH2 "/vendor/lib/hw"
lib库有以下几种形式 gralloc.[ro.hardware].so 、gralloc.[ro.product.board].so 、
gralloc.[ro.board.platform].so 、 gralloc.[ro.arch].so 或者上诉系统属性组成的文件名都不存在时,使用默认的 gralloc.default.so
这个gralloc库是Android原生态实现的,
源位置在 /hardware/libhardware/modules/gralloc/
2. Gralloc提供接口
Gralloc对应的HAL库被成功加载后,看下有哪些提供的重要接口。
源码位置: /hardware/libhardware/include/hardware/hardware.h
typedef struct hw_module_t {
...
/** Modules methods */
struct hw_module_methods_t* methods;
...
} hw_module_t;
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;
也就说任何硬件设备HAL 库都必须实现hw_module_methods_t。Andriod原生态实现的gralloc会发现除了hw_module_t和gralloc_module_t外,各硬件厂商还定义了一个private_moudle_t ,可以看出整个继承关系如下:
继承关系: private_module_t --> gralloc_module_t ---> hw_module_t
open方法对应实现:
/hardware/libhardware/modules/gralloc/gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name,
292 hw_device_t** device)
293 {
294 int status = -EINVAL;
295 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
296 gralloc_context_t *dev;
297 dev = (gralloc_context_t*)malloc(sizeof(*dev));
298
299 /* initialize our state here */
300 memset(dev, 0, sizeof(*dev));
301
302 /* initialize the procs */
303 dev->device.common.tag = HARDWARE_DEVICE_TAG;
304 dev->device.common.version = 0;
305 dev->device.common.module = const_cast<hw_module_t*>(module);
306 dev->device.common.close = gralloc_close;
307
308 dev->device.alloc = gralloc_alloc;
309 dev->device.free = gralloc_free;
310
311 *device = &dev->device.common;
312 status = 0;
313 } else {
314 status = fb_device_open(module, name, device);
315 }
316 return status;
317 }
这个函数根据设备名打开fb设备还是gralloc设备。
可以看到frameBuffer设备打开过程 :
/hardware/libhardware/modules/gralloc/framebuffer.cpp
int fb_device_open(hw_module_t const* module, const char* name,
300 hw_device_t** device)
301 {
302 int status = -EINVAL;
303 if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
304 /* initialize our state here */
305 fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
306 memset(dev, 0, sizeof(*dev));
307
308 /* initialize the procs */
309 dev->device.common.tag = HARDWARE_DEVICE_TAG;
310 dev->device.common.version = 0;
311 dev->device.common.module = const_cast<hw_module_t*>(module);
312 dev->device.common.close = fb_close;
313 dev->device.setSwapInterval = fb_setSwapInterval;
314 dev->device.post = fb_post;
315 dev->device.setUpdateRect = 0;
316
317 private_module_t* m = (private_module_t*)module;
318 status = mapFrameBuffer(m); // 内存映射
319 if (status >= 0) {
320 ....
334 *device = &dev->device.common;
335 } else {
336 free(dev);
337 }
338 }
339 return status;
其中fb_context_t是framebuffer内部使用的一个类,它包含了众多信息,而参数函数device 的内容只是其内部的device.common。
struct fb_context_t {
framebuffer_device_t device;
};
类型fb_context_t里的唯一成员就是framebuffer_device_t,这是对framebuffer设备统一描述。一个标准的fb设备通常提供如下接口实现:
1. int(*post)(struct framebuffer_device_t * dev,buffer_handlet buffer)
将buffer数据post到显示屏上。要求buffer必须与屏幕尺寸一致,并且没有被locked,这样buffer内容将在下一次VSYNC中被显示出来。
2. int(*setSwapInterval)(struct framebuffer_device_t* window, int interval)
设置两个缓冲区交换的时间间隔
3. int(*setUpdateRect)(struct framebuffer_device_t* window , int left, int top ,int width, int height )
设置刷新区域,需要framebuffer驱动支持 update-on-demand 。也就是会所在这个区域外数据是可能被认为是无效的。
framebuffer_device_t重要的成员变量
变量 | 描述 |
uint32_t flags | 标记位,指示framebuffer的属性配置 |
uint32_t width uint32_t height | framebuffer的宽和高,象素单位 |
int format | framebuffer像素格式 |
float xdip float ydpi | x和y轴密度 |
float fps | 屏幕的每秒刷新频率,假如无法从设备获取这个值,Android系统会默认设置为60Hz |
int minSwapInterval int maxSwapInterval | 该framebuffer支持的最小和最大的u缓冲交换时间 |
fb设备和配置都是在mapFrameBuffer()中完成的,内部调用了方法mapFrameBufferLocked 。
这个函数首先要尝试打开(调用open接口,权限为O_RDWR)如下路径的fb设备。
char const * const device_template[] = {
"/dev/graphics/fb%u",
"/dev/fb%u",
0 };
成功打开fb后,通过方法:
ioctl(fd, FBIOGET_FSCREENINFO, &finfo)
ioctl(fd, FBIOGET_VSCREENINFO, &info)
来的到显示屏的一系列参数,同时通过:ioctl(fd, FBIOPUT_VSCREENINFO, &info)来对底层fb进行配置 。
接下里在看下系统打开gralloc设备过程:
/hardware/libhardware/modules/gralloc/gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name,
292 hw_device_t** device)
293 {
294 int status = -EINVAL;
295 if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
296 gralloc_context_t *dev;
297 dev = (gralloc_context_t*)malloc(sizeof(*dev));
298
299 /* initialize our state here */
300 memset(dev, 0, sizeof(*dev));
301
302 /* initialize the procs */
303 dev->device.common.tag = HARDWARE_DEVICE_TAG;
304 dev->device.common.version = 0;
305 dev->device.common.module = const_cast<hw_module_t*>(module);
306 dev->device.common.close = gralloc_close;
307
308 dev->device.alloc = gralloc_alloc;
309 dev->device.free = gralloc_free;
310
311 *device = &dev->device.common;
312 status = 0;
313 } else {
314 status = fb_device_open(module, name, device);
315 }
316 return status;
317 }
318
因为gralloc担负这图形缓冲区的分配与释放,所以它提供了两个最终要接口是alloc和free。
Gralloc模块简图:
四、Andorid中的本地窗口
对于Android系统来说,如何将OpenGL ES本地化呢?
4.1FramebufferNativeWindow
EGL需要通过本地窗口来为OpenGL/OpenGL ES创建环境。 函数原型如下:
GELSurface eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config,
NativeWindowTypeWindow , const EGLint *attrib_list)
#elif defined(__ANDROID__) || defined(ANDROID)
99
100 struct ANativeWindow;
101 struct egl_native_pixmap_t;
102
103 typedef struct ANativeWindow* EGLNativeWindowType;
104 typedef struct egl_native_pixmap_t* EGLNativePixmapType;
105 typedef void* EGLNativeDisplayType;
由于OpenGL ES并不是针对某一个特定操作平台,这个EGLNativeWindowType在同系统对应不同数据类型,如上代码所示,Android中的就是ANativeWindow ,它就像是一份协议,规定了本地窗口的形态和功能。
4.2应用程序端本地窗口---Surface
正对应用程序端本地窗口是Surface和FramebufferNativeWindow一样必须集成AnativeWindow
Surface是面向Android系统的所有UI应用程序,可以推测内部实现至少以下几点:
1. 面向上层实现提供绘制图像的画板
2. 与SurfaceFlinger间如何分工。
Surface由SurfaceControl管理,而后又有SurfaceComposerClient创建。 代码如下:
47 status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
1348 PixelFormat format,
1349 sp<SurfaceControl>* outSurface, uint32_t flags,
1350 SurfaceControl* parent,
1351 LayerMetadata metadata) {
1352 sp<SurfaceControl> sur;
1353 status_t err = mStatus;
1354
1355 if (mStatus == NO_ERROR) {
1356 sp<IBinder> handle;
1357 sp<IBinder> parentHandle;
1358 sp<IGraphicBufferProducer> gbp;
1359
1360 if (parent != nullptr) {
1361 parentHandle = parent->getHandle();
1362 }
1363
1364 err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
1365 &handle, &gbp);
1366 ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
1367 if (err == NO_ERROR) {
1368 *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
1369 }
1370 }
1371 return err;
1372 }
1373
上述代码中,mClient就是ISurfaceCompserClient的sp指针,程序通过它来生产一个Surface。
4.3 SurfaceFlingger
在createSurface的执行过程中,Client线程所在(即Binder线程)将进入wait状态,知道SurfaceFlinger成功完成业务后,它才被唤醒,然后发回最终结果给客户端,这一工作方式和postMessageSync所需要实现的同步他是一致的。
4.4、VSync的产生和处理
1. 硬件源
2.软件源