最近梳理中间件架构,写这篇文章做一下梳理总结,主要整理一下从上层APP调用到驱动层的整个流程。
中间件硬件接口层现在主要有HIDL 和AIDL两种两大架构,HIDL 相对于AIDL会比较复杂,先来梳理一下HIDL的主要流程。
HIDL
1.1 APP调用JAR包
顶层应用通常都是安卓APK,首先要在java层封装出一个jar包,在java层引用native层的so库,跳转到JNI层
1.2 JNI层
JNI层负责打通Java到HIDL客户端的通信,JNI层代码实现通过手动编写的方式而不是自动生成的方式,因为我们有大量的自定义结构和HIDL的变量需要使用,用自动生成JNI CPP的方式不利于维护。
cpp
// 手动注册,不需要遵循自动生成的命名规则
// 1. 定义普通的 C++ 函数(命名更自由)
jstring simple_hello(JNIEnv* env, jobject thiz) {
return env->NewStringUTF("Hello from manually registered native function!");
}
jint fast_add(JNIEnv* env, jobject thiz, jint a, jint b) {
return a + b;
}
// 2. 定义方法映射表
static JNINativeMethod method_table[] = {
{"hello", "()Ljava/lang/String;", (void*)simple_hello},
{"add", "(II)I", (void*)fast_add}
};
// 3. 在 JNI_OnLoad 中注册
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
jclass clazz = env->FindClass("com/example/MyManualClass");
if (clazz) {
env->RegisterNatives(clazz, method_table,
sizeof(method_table) / sizeof(method_table[0]));
env->DeleteLocalRef(clazz);
}
return JNI_VERSION_1_6;
}
1.3 HIDL客户端
JNI层完成以后,通过在JNI源文件里,进行HIDL Client对象的实例化,调用Client的方法,当然也可以直接把JNI层直接当作HIDL的Client也行,在客户端代码编译和运行的时候依赖 HIDL自动打包生成的so文件。
1.4 HIDL服务端
Server通过xxx@1.0-service.rc文件开机自动启动,在HIDL 客户端对HIDL Server的对象进行实例化,调用Server的方法跳转到Server端,Server和Client是通过Binder通信,同样Server编译和运行也依赖HIDL自动打包生成的so文件。
1.5 HAL层
.hal文件里面主要声明HAL层的接口,类型,和回调方法,最终会生成一个类似这样名字xxx@1.0-service的库文件,里面包含了Binder通信,Client在调用getService的时候实际得到的是BpXXX类型的对象,然后通过Binder通信调用到BnXXX,BnXXX再调用到最终的Server。ICallback.hal中定义的接口,会被声明称纯虚函数,需要在Client中继承ICallback类重写回调函数,重写了callback函数后,将回调函数注册到Server端,Server端各个子服务在需要返回数据的时候,主动调用callback函数将数据返回给Client端。

下面是一个HIDL的流程图

AIDL
AIDL比HIDL要方便很多,AIDL更成熟,使用更广泛,对HAL层使用AIDL的方式,就可以直接从应用进程调用到HAL进程。
2.1 AIDL客户端
不同于HIDL,客户端直接在java端实现,AIDL的生成产物主要有三个:
- vendor.XXX-V1-java.jar
- vendor.XXX-V1-service
- vendor.XXX-V1-ndk.so
在java层引入jar包,实现Client端,然后将java层整体打包成aar文件,提供给上层app使用。
2.2 AIDL服务端
vendor.XXX-V1-service 会在开机自动运行,调用ndk库文件,将各个子服务模块整体打包成一个so库,供Server端使用,Server端的代码是通过ndk实现的。
