1. 创建第一个HAL模块
任务目标
在AOSP源码树中创建一个最小HAL模块hello,包含公共头文件、模块源文件和Android.bp构建脚本,编译生成共享库libhello,并通过临时测试程序验证模块接口可被正确调用。
环境与前置条件
- AOSP源码树已初始化,环境已加载(
source build/envsetup.sh,lunch已选择目标)。 - 以下路径为示例,实际操作时替换为你的源码根目录。
目录结构与文件
在AOSP源码树中创建以下文件:
hardware/sample/hello/
├── include/hello.h
├── hello.c
└── Android.bp
include/hello.h
#ifndef HELLO_HAL_H
#define HELLO_HAL_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HELLO_MODULE_ID "hello"
typedef struct hello_device {
int (*get_version)(struct hello_device* dev, uint32_t* version);
} hello_device_t;
int hello_open(const char* id, hello_device_t** device);
void hello_close(hello_device_t* device);
#ifdef __cplusplus
}
#endif
#endif
hello.c
#include <string.h>
#include <stdlib.h>
#include <log/log.h>
#include "hello.h"
#define HELLO_VERSION 0x0100
static int hello_get_version(struct hello_device* dev, uint32_t* version) {
if (!version) return -EINVAL;
*version = HELLO_VERSION;
return 0;
}
int hello_open(const char* id, hello_device_t** device) {
if (!id || !device || strcmp(id, HELLO_MODULE_ID) != 0)
return -EINVAL;
hello_device_t* dev = calloc(1, sizeof(hello_device_t));
if (!dev) return -ENOMEM;
dev->get_version = hello_get_version;
*device = dev;
return 0;
}
void hello_close(hello_device_t* device) {
free(device);
}
Android.bp
cc_library_shared {
name: "libhello",
vendor_available: true,
srcs: ["hello.c"],
export_include_dirs: ["include"],
shared_libs: ["liblog"],
}
编译
cd <AOSP根目录>
mmm hardware/sample/hello
编译产物:out/target/product/<target>/system/lib64/libhello.so(64位)或.../system/lib/libhello.so(32位)。
验证方法
在hardware/sample/hello/下创建临时测试文件test_hello.c:
#include <stdio.h>
#include "hello.h"
int main() {
hello_device_t* dev = NULL;
uint32_t ver = 0;
if (hello_open(HELLO_MODULE_ID, &dev) != 0) return 1;
if (dev->get_version(dev, &ver) != 0) return 2;
printf("version=0x%04x\n", ver);
hello_close(dev);
return 0;
}
编译并运行:
# 在AOSP环境内
clang test_hello.c -I include -L $OUT/system/lib64 -lhello -o test_hello
# 将 libhello.so 与 test_hello 推送到设备或模拟器同一目录
adb push $OUT/system/lib64/libhello.so /data/local/tmp/
adb push test_hello /data/local/tmp/
adb shell "cd /data/local/tmp && LD_LIBRARY_PATH=. ./test_hello"
通过条件:程序输出version=0x0100且退出码为0。该输出由hello_get_version中HELLO_VERSION宏直接决定,与代码逻辑严格一致。
常见问题
- 头文件找不到:确认
export_include_dirs路径正确,且编译时-I指向include目录。 - 链接错误:检查
shared_libs是否包含liblog;测试程序链接时需用-L指定库路径。 - 设备端无法加载:确认
libhello.so已推送到设备且权限为可读(chmod 644),使用LD_LIBRARY_PATH指向库所在目录。