1、SurfaceFlinger模块
Android中SurfaceFlinger与其它模块的关系图如下所示:
上图中,最底层的是Linux内核提供的framebuffer显示驱动,设备节点为/dev/graphics/fb*或/dev/fb*,其中fb0表示第一个monitor。HAL层提供了Gralloc和Composer,其中Gralloc包括fb和gralloc两个设备,fb负责打开内核中的framebuffer、初始化配置,gralloc管理帧缓冲区的分配和释放,而Composer为UI合成提供接口,直接使用者是SurfaceFlinger中的HWComposer,HWComposer管理HAL层的Composer并负责VSync信号的产生和控制。FramebufferNativeWindow是OpengGL ES在Android平台上本地化的中介之一,EGL为OpengGL ES配置本地窗口,OpengGL ES支持软件实现libagl和硬件实现libhgl,DisplayDevice用于构建OpenGL ES运行环境。
2、HAL与Gralloc
HAL是位于Linux Kernel之上的硬件抽象层,旨在降低Android系统与硬件的耦合性,提供了统一的硬件无关的抽象接口。Android的各子系统通常不会直接使用内核驱动,而是由HAL层来间接引用底层架构,显示系统也同样如此,它借助于HAL层来操作帧缓冲区,而完成这一中介任务的就是Gralloc,Android中源码位置在hardware/libhardware/modules/gralloc/,包括三个文件,framebuffer.cpp、gralloc.cpp和mapper.cpp。
为了做到与硬件无关的抽象配置,在hardware/libhardware/include/hardware.h中定义了三个重要的数据结构,如下所示:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
其中,hw_module_t有如下要求:
/**
* 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 hw_module_t {
uint32_t tag;
uint16_t module_api_version;
uint16_t hal_api_version;
const char *id;
const char *name;
const char *author;
struct hw_module_methods_t* methods;
void* dso;
#ifdef __LP64__
uint64_t reserved[32-7];
#else
uint32_t reserved[32-7];
#endif
} hw_module_t;
也就是说,每个硬件模块都要有一个名为HAL_MODULE_INFO_SYM的变量,这个变量的数据结构的第一个字段类型为hw_module_t,犹如面向对象编程语言如C++的继承机制一样,以实现接口抽象。下面看一下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,
};
struct private_module_t {
gralloc_module_t base;
private_handle_t* framebuffer;
uint32_t flags;
uint32_t numBuffers;
uint32_t bufferMask;
pthread_mutex_t lock;
buffer_handle_t currentBuffer;
int pmem_master;
void* pmem_master_base;
struct fb_var_screeninfo info;
struct fb_fix_screeninfo finfo;
float xdpi;
float ydpi;
float fps;
};
typedef struct gralloc_module_t {
struct hw_module_t common;
int (*registerBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
int (*unlock)(struct gralloc_module_t const* module,
buffer_handle_t handle);
/* reserved for future use */
int (*perform)(struct gralloc_module_t const* module,
int operation, ... );
int (*lock_ycbcr)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
struct android_ycbcr *ycbcr);
int (*lockAsync)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr, int fenceFd);
int (*unlockAsync)(struct gralloc_module_t const* module,
buffer_handle_t handle, int* fenceFd);
int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
struct android_ycbcr *ycbcr, int fenceFd);
void* reserved_proc[3];
} gralloc_module_t;
可以看出,HAL_MODULE_INFO_SYM通过private_module_t、gralloc_module_t最终包含了hw_module_t。
3、Gralloc模块加载过程
Gralloc模块加载通过hardware/libhardware/include/hardware.h声明的如下函数完成。
int hw_get_module(const char *id, const struct hw_module_t **module);
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"
通过hw_get_module加载Gralloc时,参数id为GRALLOC_HARDWARE_MODULE_ID,随后会走到如下hw_get_module_by_class函数,其中参数inst为NULL。
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
return load(class_id, path, module);
}
hw_get_module_by_class的实现逻辑是先获取ro.hardware.graphic属性,属性获取成功后就到指定的目录检查gralloc库是否存在,对于64位的机器来说在如下几个目录检查:
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#define HAL_LIBRARY_PATH3 "/odm/lib64/hw"
库的名字为gralloc..so。如果ro.hardware.graphic属性获取失败或者在指定的目录找不到gralloc库时就逐个获取如下几个属性:
"ro.hardware"
"ro.product.board"
"ro.board.platform"
"ro.arch"
属性获取成功后,再到上面提到的几个目录查找gralloc..so,如果还是找不到,最后则查找Android默认的库gralloc.default.so。上面几个步骤中一旦找到了gralloc库,就立即通过dlopen函数打开,否则gralloc模块加载失败。dlopen成功后,通过dlsym获取HAL_MODULE_INFO_SYM_AS_STR即名为HMI的函数地址,dlsym成功后再判断其模块id是否为gralloc,如果是的话,预示着gralloc模块加载成功,最后将dlopen结果保存到hw_module_t的dso成员,即一开始调用hw_get_module函数的参数module中,这是个二级指针,至此,Gralloc模块加载完成。总结一下,Gralloc模块的加载就是在指定的几个目录中逐个查找gralloc库,因为gralloc库有不同的表示形式,gralloc库存在的话进而使用dlopen、dlsym进行处理。
4、Gralloc接口
从上面的数据结构中可以看出,gralloc_module_t继承了hw_module_t,进而包含了如下hw_module_methods_t:
typedef struct hw_module_methods_t {
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
这是一个重要的接口,目前只是一个函数指针open,用来打开某个特定的设备文件。既然有open,那么必然有close,在如下的hw_device_t中。
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct hw_device_t {
uint32_t tag;
uint32_t version;
#ifdef __LP64__
uint64_t reserved[12];
#else
uint32_t reserved[12];
#endif
int (*close)(struct hw_device_t* device);
} hw_device_t;
上述open用来打开设备gpu0和fb0,两者用法类似,如下函数所示:
// gralloc.h
#define GRALLOC_HARDWARE_GPU0 "gpu0"
static inline int gralloc_open(const struct hw_module_t* module,
struct alloc_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_GPU0, TO_HW_DEVICE_T_OPEN(device));
}
static inline int gralloc_close(struct alloc_device_t* device) {
return device->common.close(&device->common);
}
// fb.h
#define GRALLOC_HARDWARE_FB0 "fb0"
static inline int framebuffer_open(const struct hw_module_t* module,
struct framebuffer_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_FB0, TO_HW_DEVICE_T_OPEN(device));
}
static inline int framebuffer_close(struct framebuffer_device_t* device) {
return device->common.close(&device->common);
}
上面提到了每一个HAL模块如这里的Gralloc都应该有一个HAL_MODULE_INFO_SYM,其中指定了open函数指针为gralloc_device_open函数,具体如下:
int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
gralloc_context_t *dev;
dev = (gralloc_context_t*)malloc(sizeof(*dev));
/* initialize our state here */
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 = gralloc_close;
dev->device.alloc = gralloc_alloc;
dev->device.free = gralloc_free;
*device = &dev->device.common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}
从上面的gralloc_device_open可以看出,会判断打开gpu还是fb,下面分开介绍。
5、device-gpu
gpu相关device的数据结构如下:
struct gralloc_context_t {
alloc_device_t device;
};
typedef struct alloc_device_t {
struct hw_device_t common;
int (*alloc)(struct alloc_device_t* dev,
int w, int h, int format, int usage,
buffer_handle_t* handle, int* stride);
int (*free)(struct alloc_device_t* dev,
buffer_handle_t handle);
void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);
void* reserved_proc[7];
} alloc_device_t;
在gralloc_device_open中,malloc一个gralloc_context_t,然后指定了对应的close、alloc和free接口,其中close用于free刚刚malloc的gralloc_context_t,alloc和free用于管理帧缓冲区,涉及字节对齐(包括页对齐)、共享内存、设备管理、内存映射等,以及一个新的数据结构private_handle_t(管理文件描述符),后面着重说明。
6、device-fb
framebuffer相关device的数据结构如下:
struct fb_context_t {
framebuffer_device_t device;
};
typedef struct framebuffer_device_t {
struct hw_device_t common;
const uint32_t flags;
const uint32_t width;
const uint32_t height;
const int stride;
const int format;
const float xdpi;
const float ydpi;
const float fps;
const int minSwapInterval;
const int maxSwapInterval;
const int numFramebuffers;
int reserved[7];
int (*setSwapInterval)(struct framebuffer_device_t* window,
int interval);
int (*setUpdateRect)(struct framebuffer_device_t* window,
int left, int top, int width, int height);
int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
int (*compositionComplete)(struct framebuffer_device_t* dev);
void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);
int (*enableScreen)(struct framebuffer_device_t* dev, int enable);
void* reserved_proc[6];
} framebuffer_device_t;
fb_device_open函数如下:
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)) {
fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
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;
}
可以看出,fb与gpu设备的处理类似,重要的一步在与mapFrameBuffer,此时有posix mutex作同步保护。这一步才是真正的open操作,首先尝试打开/dev/graphics/fb0、/dev/fb0,成功则继续,随后是一些ioctl操作,用于获取屏幕信息,并通过这些屏幕信息算出fb的长度,最后mmap映射到刚打开的fb0设备文件,长度为刚算出的fb长度。在打开gpu0时,可以像fb0一样分配framebuffer,也可以是普通的buffer,这个普通的buffer映射的为共享内存区,即文件描述符通过ashmem_create_region函数(属于Android的libcutils库)创建。