App调用hal层接口调用开发指南

776 阅读3分钟

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. 部署验证步骤

  1. 刷写系统镜像
  2. 安装测试APK
  3. 验证日志输出:
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接口,构建定制化硬件功能。