AOSP实战:5分钟搞定Native Service的AIDL接口定义与实现(附完整代码)
如果你正在AOSP的底层世界里探索,想给系统添加一个自己的服务,却发现Java层的Binder服务例子铺天盖地,而Native Service的教程却总是语焉不详,那么你来对地方了。很多开发者第一次接触AOSP的Native服务开发时,都会被AIDL文件生成、Bn/Bp类实现、服务注册这一连串的步骤搞得晕头转向,更别提那些隐藏在编译脚本和头文件包含路径里的坑了。这篇文章就是为你准备的——我们将抛开那些冗长的理论,直接切入实战,用最清晰的步骤和完整的代码,带你快速搭建一个可运行的Native Service。无论你是想为硬件抽象层(HAL)添加一个C++接口,还是需要在系统底层实现一个高性能的IPC服务,这个流程都能让你在五分钟内看到成果。
1. 项目结构与AIDL定义:一切从接口开始
在AOSP中添加一个Native Service,第一步不是写C++代码,而是定义通信的“契约”——AIDL接口。这和我们熟知的Java层AIDL思想一致,但具体到Native层,目录结构和编译方式有它自己的规矩。
我习惯在frameworks/native/services目录下创建自己的服务模块,但为了模块化和避免污染原生代码树,在frameworks/vendor/下新建目录是更稳妥的做法。这清晰地划分了平台通用服务和厂商定制服务的界限。假设我们的服务模块叫myservice,完整的目录树规划如下:
frameworks/vendor/myservice/
├── aidl/
│ └── android/
│ └── myservice/
│ └── IMyService.aidl
├── include/
│ ├── aidl/
│ │ ├── BnMyService.h
│ │ ├── BpMyService.h
│ │ └── IMyService.h
│ └── MyService.h
├── MyService.cpp
└── test/
├── MyServiceClient.cpp
└── MyServiceServer.cpp
接下来是IMyService.aidl文件的内容。我们定义一个简单的接口,它包含一个方法,接收一个整数参数n,并返回一个字符串列表。注意out关键字,它表示这个参数由服务端填充后返回给客户端。
// frameworks/vendor/myservice/aidl/android/myservice/IMyService.aidl
package android.myservice;
interface IMyService {
void generateMessages(int n, out List<String> messages);
}
这个接口描述了一个功能:客户端告诉服务端需要生成几条消息,服务端则填充一个消息列表并返回。AIDL语法相对直观,但有几个关键点需要注意:
package必须与目录路径匹配。- 支持的数据类型包括基本类型(int, long, boolean等)、String、List、Map以及自定义的Parcelable。
in、out、inout参数方向标识符对于非基本类型至关重要,它决定了数据拷贝的方向和开销。
提示:在定义AIDL接口时,尽量保持接口的原子性和正交性。避免设计一个庞大的、包含无数方法的“上帝接口”,这不利于维护和版本迭代。将功能相近的方法归类到不同的接口中,是更优雅的做法。
2. 构建脚本与AIDL代码生成:让Soong系统为你工作
有了AIDL文件,下一步是让AOSP的构建系统(Soong)为我们生成对应的C++桩代码(Stub)和代理(Proxy)代码。这通过编写Android.bp文件来实现。这个文件是Soong构建系统的蓝图(Blueprint),它描述了模块的源代码、依赖和构建规则。
在frameworks/vendor/myservice/目录下创建Android.bp:
// frameworks/vendor/myservice/Android.bp
// 1. 定义一个文件组,将我们的AIDL文件声明为源
filegroup {
name: "myservice_aidl_srcs",
srcs: ["aidl/android/myservice/IMyService.aidl"],
}
// 2. 定义共享库模块,它将包含AIDL生成的代码和我们实现的服务代码
cc_library_shared {
name: "libmyservice",
// AIDL配置块,告诉构建系统如何处理我们的AIDL文件
aidl: {
export_aidl_headers: true, // 导出生成的头文件,供其他模块包含
local_include_dirs: ["aidl"], // AIDL文件的本地搜索路径
include_dirs: ["frameworks/vendor/myservice/aidl"], // 头文件包含路径
},
// 源文件:包括AIDL文件组和我们自己实现的C++文件
srcs: [
":myservice_aidl_srcs",
"MyService.cpp",
],
// 依赖的系统共享库
shared_libs: [
"libbinder", // Binder IPC核心库
"libutils", // Android工具类库
"liblog", // 日志库 (ALOGD, ALOGI等)
],
// 导出libbinder的头文件,确保编译时能找到必要的Bind

&spm=1001.2101.3001.5002&articleId=148658847&d=1&t=3&u=6bf4942d92cc4b209194eb8f8628473e)
33

被折叠的 条评论
为什么被折叠?



