Android HAL层接口调用开发指南
一、整体架构概述
本指南完整实现从APP到HAL层的全链路调用,包含四个核心模块:
| 层级 | 功能描述 | 核心技术点 |
|---|---|---|
| HAL层 | 硬件抽象接口实现 | 自定义HAL模块开发 |
| JNI层 | 本地方法桥接 | JNI注册与HAL接口调用 |
| Framework | 系统服务封装与Binder通信 | AIDL接口定义与ServiceManager注册 |
| APP层 | 客户端调用 | Binder IPC通信 |
二、HAL层实现
1. 核心文件
bash
hardware/libhardware/
├── include/hardware/test.h
└── modules/test/
├── test.c
└── Android.bp
2. 接口定义(test.h)
c
#define TEST_HARDWARE_MODULE_ID "test"
#define TEST_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(0, 1)
typedef struct test_module {
struct hw_module_t common;
} test_module_t;
typedef struct test_device {
struct hw_device_t common;
int (*additionTest)(const struct test_device *dev, int a, int b);
} test_device_t;
3. 实现逻辑(test.c)
c
static int additionTest(const struct test_device *dev, int a, int b) {
return a + b;
}
static int test_open(...) {
dev->additionTest = additionTest;
*device = &(dev->common);
return 0;
}
test_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.id = TEST_HARDWARE_MODULE_ID,
.methods = &test_module_methods,
}
};
4. 编译配置(Android.bp)
javascript
cc_library_shared {
name: "test.default",
relative_install_path: "hw",
srcs: ["test.c"],
header_libs: ["libhardware_headers"],
shared_libs: ["liblog"],
}
三、JNI层桥接
1. JNI实现(com_android_server_TestService.cpp)
cpp
static jint nativeAdd(JNIEnv* env, jobject, jint a, jint b) {
return test_device->additionTest(test_device, a, b);
}
static void nativeInit(JNIEnv*) {
hw_get_module(TEST_HARDWARE_MODULE_ID, &hw_module);
test_device_open(hw_module, &test_device);
}
static const JNINativeMethod gMethods[] = {
{"nativeAdd", "(II)I", (void*)nativeAdd},
{"nativeInit", "()V", (void*)nativeInit}
};
2. 系统集成配置
diff
# frameworks/base/services/core/jni/Android.bp
srcs += ["com_android_server_TestService.cpp"]
# frameworks/base/services/core/jni/onload.cpp
register_android_server_TestService(env);
四、Framework服务层
1. AIDL接口定义(ITestService.aidl)
java
interface ITestService {
int add(int a, int b);
}
2. 服务实现(TestService.java)
java
public class TestService extends ITestService.Stub {
public int add(int a, int b) {
return nativeAdd(a, b);
}
private static native int nativeAdd(int a, int b);
private static native void nativeInit();
}
3. 服务注册(SystemServer.java)
java
ServiceManager.addService("test", new TestService());
五、APP层调用
1. 客户端实现
java
public class MainActivity extends Activity {
private ITestService mService;
protected void onCreate(Bundle savedInstanceState) {
IBinder binder = ServiceManager.getService("test");
mService = ITestService.Stub.asInterface(binder);
}
public void onAddClick(View v) {
int result = mService.add(5, 3);
Log.d("TestApp", "Result: " + result);
}
}
2. 权限配置(AndroidManifest.xml)
xml
<uses-permission android:name="android.permission.ACCESS_TEST_SERVICE" />
六、SELinux策略配置
1. 服务上下文
diff
# system/sepolicy/private/service_contexts
+test u:object_r:test_service:s0
2. 策略文件
diff
# system/sepolicy/public/service.te
+type test_service, system_api_service, system_server_service;
3. 设备权限
diff
# system/core/rootdir/ueventd.rc
+/dev/test 0666 root root
七、编译部署验证
1. 编译指令
bash
m test.default libandroid_servers TestServiceApp
2. 部署验证步骤
- 刷写系统镜像
- 安装测试APK
- 验证日志输出:
log
D/TestHal: additionTest called with 5+3
D/TestApp: Result: 8
八、常见问题排查
| 问题现象 | 排查要点 | 解决方案 |
|---|---|---|
| ServiceManager返回空指针 | SELinux策略未正确配置 | 检查service_contexts配置 |
| JNI方法无法找到 | JNI注册函数未正确调用 | 验证onload.cpp注册逻辑 |
| HAL库加载失败 | 设备节点权限问题 | 检查ueventd.rc权限设置 |
| 跨进程调用返回SecurityException | 缺少Binder权限 | 添加INTERACT_ACROSS_USERS权限 |
| 计算结果异常 | JNI类型转换错误 | 检查JNI方法签名与实际类型匹配 |
通过本指南可实现从应用层到硬件层的完整调用链路,开发者可根据实际硬件功能扩展HAL接口,构建定制化硬件功能。