【Android GUI】从总体上了解Android的GUI体系

文章目录

概览

  • Linux内核提供了统一的framebuffer显示驱动。设备节点/dev/graphics/fb*或者/dev/fb*,其中fb0表示第一个Monitor。

  • Android的HAL层提供了Gralloc,包括fb和gralloc两个设备。fb负责打开内核的framebuffer、初始化配置。gralloc管理帧缓冲区的分配和释放。所以上层只需要通过Gralloc来间接访问帧缓冲区,来保证对framebuffer的统一管理。

  • HAL层的composer为UI合成提供接口,被surface flinger调用。

  • VSync是"Project Butter"加入的同步机制,可以通过硬件产生,也可以通过软件,即VSyncThread模拟。

  • OpenGL ES 是一个通用函数库,需要和具体平台建立关联才可以工作。

  • FramebufferNativeWindow负责OpenGL ES在Android平台本地化的中介之一

  • EGL为OpenGL ES配置本地窗口。

Android硬件接口HAL

HAL是Android很多子系统,例如显示系统、音频系统等和Linux kernel驱动之间通信的统一接口。

Gralloc与Framebuffer

Framebuffer是内核系统提供的图形硬件的抽象描述,它占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。

Android中,Framebuffer提供的设备文件节点是/dev/graphics/fb*

Android的显示系统借助于HAL层的Gralloc操作帧缓冲区。

Gralloc模块的加载

Gralloc对应的模块是由FramebufferNativeWindow在构造函数中加载的。

cpp 复制代码
hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
cpp 复制代码
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"

hw_get_module查找和ID值匹配的库:

cpp 复制代码
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

lib库的命名形式:

cpp 复制代码
gralloc.[ro.hardware].so
gralloc.[ro.product.board].so
gralloc.[ro.board.platform].so
gralloc.[ro.arch].so

默认的:

cpp 复制代码
    gralloc.default.so

Gralloc提供的接口

cpp 复制代码
/*hardware/libhardware/include/hardware/Hardware.h*/
typedef struct hw_module_t {...
    struct hw_module_methods_t* methods;//一个HAL库必须提供的方法
    ...
} hw_module_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接口可以帮助上层打开"fb0"和"gpu0"。fb0就是主屏幕,gpu0负责图形缓冲区的分配和释放。

cpp 复制代码
/*frameworks/native/libs/ui/FramebufferNativeWindow.cpp*/
FramebufferNativeWindow::FramebufferNativeWindow()
: BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{...
    err = framebuffer_open(module, &fbDev); //打开fb设备
    err = gralloc_open(module, &grDev);//打开gralloc设备

Android原生的Gralloc实现

Android原生态的Gralloc实现在hardware/libhardware/modules/gralloc中,它open接口对应的是:

cpp 复制代码
/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/
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设备
        ...
    } else {
        status = fb_device_open(module, name, device);//否则就是fb设备
    }
    return status;
}

打开framebuffer设备

cpp 复制代码
/*hardware/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)) {//设备名是否正确
       fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));/分配hw_device_t空间,   
       这是一个"壳"*/
       memset(dev, 0, sizeof(*dev));//初始化,良好的编程习惯
       ...
       dev->device.common.close = fb_close;//这几个接口是fb设备的核心
       dev->device.setSwapInterval = fb_setSwapInterval;
       dev->device.post = fb_post;
       ...
       private_module_t* m = (private_module_t*)module;
       status = mapFrameBuffer(m);//内存映射,以及参数配置
       if (status >= 0) {
           ...
           *device = &dev->device.common;//"壳"和"核心"的关系
       }
    }
    return status;
}

标准的fb设备需要实现:int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);,将buffer数据post到屏幕上 ,这样buffer内容在下一次VSYNC中被显示出来。

设置缓冲区swap的时间间隔:int (*setSwapInterval)(struct framebuffer_device_t* window, int interval);

设置刷新区域:int (*setUpdateRect)(struct framebuffer_device_t* window, int left, int top, int width, int height);

接着是打开kernel层的fb设备和对fb进行配置,在mapFrameBuffer()中完成,它会尝试打开:

cpp 复制代码
"/dev/graphics/fb%u"或者 "/dev/fb%u"

打开后,通过

cpp 复制代码
ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
ioctl(fd, FBIOGET_VSCREENINFO, &info)

得到屏幕参数,接着通过ioctl(fd, FBIOPUT_VSCREENINFO, &info)对fb进行配置。

mapFrameBuffer()的另外一个任务是做为fb设备做内存映射:

cpp 复制代码
    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);    
    module->framebuffer->base = intptr_t(vaddr);
    memset(vaddr, 0, fbSize);

打开gralloc设备

cpp 复制代码
/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/
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;//做法和fb类似
        dev = (gralloc_context_t*)malloc(sizeof(*dev));//分配空间
        /* initialize our state here */
        memset(dev, 0, sizeof(*dev));
        ...
        dev->device.alloc = gralloc_alloc; //从提供的接口来看,gralloc主要负责"分配和释放"操作
        dev->device.free = gralloc_free;
        ...
}

总结下Android原生的Gralloc:

参考

《深入理解Android内核设计思想》

相关推荐
CYRUS STUDIO26 分钟前
ARM64汇编寻址、汇编指令、指令编码方式
android·汇编·arm开发·arm·arm64
weixin_449310841 小时前
高效集成:聚水潭采购数据同步到MySQL
android·数据库·mysql
Zender Han1 小时前
Flutter自定义矩形进度条实现详解
android·flutter·ios
白乐天_n3 小时前
adb:Android调试桥
android·adb
姑苏风7 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k11 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小1011 小时前
JavaWeb项目-----博客系统
android
风和先行12 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.12 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰13 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder