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函数签名完全匹配
Java应用 MainActivity JNI Bridge hello_jni.cpp HIDL Interface IHello@1.0 HAL Service HelloImpl 返回字符串结果 JNI调用 HIDL IPC 调用链: Java → JNI → HIDL IPC → HAL Service 验证点: lshal 显示服务注册 + 应用获取到字符串