1. Display HAL 接口概览与最小实现
任务说明
本案例以 Android 8.0 及以上版本的 Display HAL 为对象,分析其从动态库加载到设备句柄创建完成的完整初始化链路。目标是通过阅读 AOSP 源码路径(hardware/libhardware 与 hardware/rockchip/display 等厂商实现),梳理 HAL 模块的加载机制、open 调用约定以及 hw_device_t 的创建过程,并最终通过一个最小可复现的 C 程序验证该初始化流程的核心环节。
初始化流程总览
Android Display HAL 的初始化遵循 hw_get_module → module->methods->open → device_create 的三段式结构。上层 SurfaceFlinger 通过 hw_get_module 按模块 ID 查找并加载 HAL 动态库,随后调用模块的 open 方法创建具体的设备实例。设备实例以 hw_device_t 为基类,厂商实现通过结构体嵌套方式扩展出 hwc_device_t(HWC 1.x)或 hwc2_device_t(HWC 2.x)。
核心代码路径分析
以下代码展示 HAL 模块加载与设备创建的最小可复现实现。该程序模拟了 hw_get_module 的查找逻辑,并演示厂商如何通过 open 回调创建 hw_device_t 实例。为保持案例独立可运行,此处使用本地结构体定义替代 AOSP 头文件依赖。
// display_hal_init_demo.c
// 编译: gcc -o display_hal_init_demo display_hal_init_demo.c
// 运行: ./display_hal_init_demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- 模拟 AOSP hardware.h 核心定义 ---- */
#define HARDWARE_MODULE_TAG 0x484D4F44 // 'HMOD'
#define HARDWARE_DEVICE_TAG 0x48444556 // 'HDEV'
struct hw_module_t;
struct hw_device_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;
typedef struct hw_module_t {
uint32_t tag;
const char* id;
const char* name;
const hw_module_methods_t* methods;
} hw_module_t;
typedef struct hw_device_t {
uint32_t tag;
struct hw_module_t* module;
void (*close)(struct hw_device_t* device);
} hw_device_t;
/* ---- 厂商 Display HAL 实现 ---- */
typedef struct display_device_t {
struct hw_device_t common;
int display_count;
char* vendor_data;
} display_device_t;
static int display_device_close(struct hw_device_t* dev) {
if (dev) {
display_device_t* d = (display_device_t*)dev;
free(d->vendor_data);
free(d);
printf("[display HAL] device closed and freed\n");
}
return 0;
}
static int display_device_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device) {
if (strcmp(id, "display") != 0) {
fprintf(stderr, "unknown device id: %s\n", id);
return -1;
}
display_device_t* dev = calloc(1, sizeof(display_device_t));
if (!dev) return -1;
// 初始化基类 hw_device_t
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = display_device_close;
// 初始化厂商扩展字段
dev->display_count = 2; // 假设双屏
dev->vendor_data = strdup("rockchip_display_ctx");
*device = &dev->common;
printf("[display HAL] open() called, id=%s, display_count=%d\n",
id, dev->display_count);
return 0;
}
/* ---- 模块定义,对应 AOSP 中的 HAL_MODULE_INFO_SYM ---- */
static struct hw_module_t display_module = {
.tag = HARDWARE_MODULE_TAG,
.id = "display",
.name = "Rockchip Display HAL",
.methods = &(hw_module_methods_t){ .open = display_device_open },
};
/* ---- 模拟 hw_get_module 的查找与加载 ---- */
// 真实系统中此函数通过 dlopen 加载 /vendor/lib64/hw/display.*.so
// 并查找名为 HAL_MODULE_INFO_SYM 的符号
static int hw_get_module_sim(const char* id, hw_module_t** module) {
if (strcmp(id, "display") == 0) {
*module = &display_module;
printf("[loader] module '%s' found (simulated dlopen)\n", id);
return 0;
}
return -1;
}
int main(void) {
hw_module_t* mod = NULL;
hw_device_t* dev = NULL;
// 第一步: 加载模块
if (hw_get_module_sim("display", &mod) != 0) {
fprintf(stderr, "failed to load display module\n");
return 1;
}
printf("[main] module loaded: %s (tag=0x%x)\n", mod->name, mod->tag);
// 第二步: 调用 open 创建设备
if (mod->methods->open(mod, "display", &dev) != 0) {
fprintf(stderr, "failed to open display device\n");
return 1;
}
// 第三步: 验证设备句柄
if (dev->tag != HARDWARE_DEVICE_TAG) {
fprintf(stderr, "invalid device tag\n");
return 1;
}
display_device_t* d = (display_device_t*)dev;
printf("[main] device created: displays=%d, vendor=%s\n",
d->display_count, d->vendor_data);
// 清理
dev->close(dev);
return 0;
}
验证方法与判定标准
执行以下步骤验证初始化流程的正确性:
- 将上述代码保存为
display_hal_init_demo.c,运行gcc -o display_hal_init_demo display_hal_init_demo.c编译,确认无错误无警告; - 运行
./display_hal_init_demo,观察输出顺序:应先打印模块加载信息,再打印open() called,最后打印设备创建信息与关闭信息; - 判定通过标准:程序退出码为 0,且输出中依次出现
module loaded、open() called、device created、device closed四类关键日志,表明模块加载、open 回调、设备实例化与资源释放的完整闭环已打通。
预期输出(与代码逻辑严格对应):
[loader] module 'display' found (simulated dlopen)
[main] module loaded: Rockchip Display HAL (tag=0x484d4f44)
[display HAL] open() called, id=display, display_count=2
[main] device created: displays=2, vendor=rockchip_display_ctx
[display HAL] device closed and freed
本案例通过模拟 AOSP 的 HAL 加载与 open 机制,完整呈现了 Display HAL 初始化中 hw_module_t 查找、hw_device_t 创建及厂商扩展结构体初始化的核心路径。真实系统中 hw_get_module 的 dlopen 细节与厂商 open 内部的硬件资源申请逻辑,可在本框架基础上按需扩展。