1. 编写第一个HAL模块
任务目标
在Android系统源码树中实现一个最小HAL模块hello.default,提供hello()函数返回字符串,并通过JNI接口供上层Java应用调用,验证HAL模块从底层到应用层的完整调用链。
环境与前置条件
- 已下载AOSP源码(本案例基于Android 9.0+,HIDL接口使用
android.hardware.hello@1.0) - 已配置源码编译环境(
source build/envsetup.sh) - 目标设备已解锁并支持
adb root
实现步骤
1. 定义HIDL接口
创建目录hardware/interfaces/hello/1.0/default,在hardware/interfaces/hello/1.0/下定义接口文件:
// IHello.hal
package android.hardware.hello@1.0;
interface IHello {
hello() generates (string result);
};
2. 实现HAL服务端
在default/目录下创建以下文件:
// Hello.cpp
#include <android/hardware/hello/1.0/IHello.h>
#include <hidl/LegacySupport.h>
#include <string>
using android::hardware::hello::V1_0::IHello;
using android::hardware::Return;
using android::hardware::Void;
using android::sp;
struct HelloImpl : public IHello {
Return<void> hello(std::function<void(const hidl_string&)> _hidl_cb) override {
std::string msg = "Hello from HAL!";
_hidl_cb(msg);
return Void();
}
};
int main() {
return android::hardware::defaultPassthroughServiceImplementation<IHello>("default");
}
// Android.bp
cc_binary {
name: "android.hardware.hello@1.0-service",
relative_install_path: "hw",
vendor: true,
srcs: ["Hello.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
"android.hardware.hello@1.0",
],
init_rc: ["android.hardware.hello@1.0-service.rc"],
}
// android.hardware.hello@1.0-service.rc
service vendor.hello-hal /vendor/bin/hw/android.hardware.hello@1.0-service
class hal
user root
group system
3. 实现JNI层
创建JNI桥接代码,供上层Java调用:
// hello_jni.cpp
#include <jni.h>
#include <android/hardware/hello/1.0/IHello.h>
#include <string>
using android::hardware::hello::V1_0::IHello;
using android::hardware::hidl_string;
using android::sp;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellohal_MainActivity_getHello(JNIEnv *env, jobject /* this */) {
sp<IHello> service = IHello::getService();
if (service == nullptr) {
return env->NewStringUTF("HAL service not available");
}
std::string result;
service->hello([&](hidl_string msg) {
result = msg.c_str();
});
return env->NewStringUTF(result.c_str());
}
4. 编译与部署
# 编译HAL服务
mmm hardware/interfaces/hello/1.0/default/
# 编译JNI库
mmm frameworks/base/core/jni/ # 假设JNI代码放在此处
# 推送并启动服务
adb root
adb remount
adb push $OUT/vendor/bin/hw/android.hardware.hello@1.0-service /vendor/bin/hw/
adb shell chmod 755 /vendor/bin/hw/android.hardware.hello@1.0-service
adb shell /vendor/bin/hw/android.hardware.hello@1.0-service &
验证方法
在Java应用中调用getHello(),观察返回字符串。通过以下命令确认HAL服务注册成功:
adb shell lshal | grep hello
# 预期输出: android.hardware.hello@1.0::IHello default
应用界面显示Hello from HAL!即表示HAL模块工作正常。若显示HAL service not available,检查服务是否启动及SELinux权限。
常见问题
- SELinux拒绝:添加
vendor_hal_file_contexts和hal_hello_default.te策略文件 - 服务未注册:确认
init.rc中service名称与getService("default")参数一致 - JNI找不到符号:确认Java包名与JNI函数签名完全匹配