3. AIDL基础回顾:AIDL接口定义语言语法、服务注册与发现机制(Android 11+)
在深入AIDL化Camera HAL架构之前,必须牢固掌握AIDL(Android Interface Definition Language)的核心基础。本章聚焦于AIDL的接口定义语法、数据类型映射以及Android 11+引入的服务注册与发现机制,为后续理解Camera HAL从HIDL到AIDL的迁移奠定语法与架构基础。
3.1 AIDL接口定义语言语法
AIDL是一种轻量级的接口定义语言,用于定义客户端与服务端之间的进程间通信(IPC)契约。其语法与Java接口高度相似,但仅支持方法声明、参数和返回值类型,不支持访问修饰符、静态成员或内部类。
3.1.1 基本语法结构
一个标准的AIDL文件以包声明开头,随后导入依赖类型,最后定义接口。接口中的方法支持in、out、inout方向标记,用于指示参数的数据流向。
// ICameraDevice.aidl
package android.hardware.camera;
import android.hardware.camera.CameraMetadata;
interface ICameraDevice {
int open(String cameraId);
void close();
CameraMetadata getCharacteristics(in String cameraId);
int setCallback(in ICameraDeviceCallback callback);
CaptureResult capture(in CaptureRequest request, out ParcelFileDescriptor fd);
}
3.1.2 数据类型映射规则
AIDL支持的数据类型分为三类:基本类型、Parcelable类型和AIDL接口类型。下表列出了常用类型及其映射关系:
| AIDL类型 | Java类型 | C++类型 | 方向支持 |
|---|---|---|---|
boolean |
boolean |
bool |
in |
int |
int |
int32_t |
in |
long |
long |
int64_t |
in |
float |
float |
float |
in |
double |
double |
double |
in |
String |
String |
std::string |
in |
List<T> |
List<T> |
std::vector<T> |
in/out |
Map<K,V> |
Map<K,V> |
std::map<K,V> |
in/out |
IBinder |
IBinder |
android::IBinder |
in |
ParcelFileDescriptor |
ParcelFileDescriptor |
android::os::ParcelFileDescriptor |
in/out |
ParcelFileDescriptor用于传递Camera buffer的共享内存fd,IBinder用于传递回调接口。方向标记in表示数据从客户端流向服务端,out表示从服务端流向客户端,inout表示双向流动。错误使用方向标记会导致序列化异常。
3.1.3 自定义Parcelable类型
对于复杂数据结构,需要定义Parcelable类型。在AIDL中,Parcelable类型必须显式声明,并实现Parcelable接口。
// CameraMetadata.aidl
package android.hardware.camera;
parcelable CameraMetadata {
String cameraId;
int sensorOrientation;
long exposureTime;
float aperture;
List<int> availableFpsRanges;
}
对应的Java实现类必须包含writeToParcel()和CREATOR字段:
public class CameraMetadata implements Parcelable {
public String cameraId;
public int sensorOrientation;
public long exposureTime;
public float aperture;
public List<Integer> availableFpsRanges;
protected CameraMetadata(Parcel in) {
cameraId = in.readString();
sensorOrientation = in.readInt();
exposureTime = in.readLong();
aperture = in.readFloat();
availableFpsRanges = in.createIntArrayList();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(cameraId);
dest.writeInt(sensorOrientation);
dest.writeLong(exposureTime);
dest.writeFloat(aperture);
dest.writeIntList(availableFpsRanges);
}
public static final Creator<CameraMetadata> CREATOR =
new Creator<CameraMetadata>() {
@Override
public CameraMetadata createFromParcel(Parcel in) {
return new CameraMetadata(in);
}
@Override
public CameraMetadata[] newArray(int size) {
return new CameraMetadata[size];
}
};
}
3.2 AIDL服务注册与发现机制(Android 11+)
Android 11(API 30)对AIDL服务注册与发现机制进行了重大重构,引入了稳定的AIDL(Stable AIDL)概念,使得AIDL接口可以像HIDL一样作为系统API稳定发布。这一变化是Camera HAL从HIDL迁移到AIDL的核心驱动力。
3.2.1 服务注册流程
在Android 11+中,AIDL服务通过ServiceManager进行注册,但注册方式与早期版本有显著区别:
- 定义稳定AIDL接口:接口文件必须位于
hardware/interfaces/或frameworks/hardware/interfaces/目录下,并遵循版本化命名规范。 - 实现服务端:继承生成的Stub类,实现接口方法。
- 注册服务:使用
ServiceManager.addService()将Binder对象注册到全局服务管理器。 - 声明服务:在
manifest.xml中声明服务进程和接口版本。
// 服务端注册示例(C++)
#include <android/binder_manager.h>
#include <android/binder_service.h>
class CameraDeviceService : public ICameraDevice {
ndk::ScopedAStatus open(const std::string& cameraId, int32_t* _aidl_return) override {
// 实现逻辑
*_aidl_return = 0;
return ndk::ScopedAStatus::ok();
}
// 其他方法实现...
};
int main() {
auto service = ndk::SharedRefBase::make<CameraDeviceService>();
const std::string instance = std::string() + ICameraDevice::descriptor + "/default";
binder_status_t status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
if (status != STATUS_OK) {
// 错误处理
}
// 进入消息循环
ABinderProcess_joinThreadPool();
return 0;
}
3.2.2 服务发现机制
客户端通过ServiceManager查询服务实例,获取Binder代理对象。Android 11+推荐使用AServiceManager_getService()或getService()模板函数:
// 客户端发现服务示例(C++)
#include <android/binder_manager.h>
void connectToCameraService() {
const std::string instance = std::string() + ICameraDevice::descriptor + "/default";
ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str()));
if (!binder) {
// 服务未就绪,重试或报错
return;
}
auto service = ICameraDevice::fromBinder(binder);
if (!service) {
// 接口不匹配
return;
}
int32_t result;
ndk::ScopedAStatus status = service->open("0", &result);
if (status.isOk()) {
// 成功调用
}
}
hwservicemanager不同,AIDL服务统一使用servicemanager(即ServiceManager)。这意味着Camera HAL的AIDL服务与Android系统其他AIDL服务共享同一个命名空间,实例名称必须全局唯一,通常采用接口描述符/实例名的格式。
3.2.3 服务注册与发现架构图
下图展示了Android 11+中AIDL服务的完整注册与发现流程,以及客户端与服务端之间的IPC通信路径:
3.3 AIDL与HIDL服务注册对比
理解AIDL与HIDL在服务注册与发现机制上的差异,是掌握Camera HAL迁移的关键。下表从多个维度进行对比:
| 对比维度 | AIDL(Android 11+) | HIDL |
|---|---|---|
| 服务管理器 | ServiceManager(servicemanager进程) |
hwservicemanager(独立进程) |
| 接口描述符 | android.hardware.camera.ICameraDevice |
android.hardware.camera@3.4::ICameraDevice |
| 实例名称格式 | 接口描述符/实例名(如 .../default) |
接口描述符/实例名(如 .../default) |
| 注册API | AServiceManager_addService() |
registerAsService() |
| 发现API | AServiceManager_getService() |
getService() |
| 接口稳定性 | 稳定AIDL(版本化,冻结后不可修改) | HIDL(版本化,冻结后不可修改) |
| 传输层 | Binder(内核驱动) | Binderized HIDL(Binder驱动)或Passthrough(直通模式) |
| 客户端语言 | Java / C++ / Rust / NDK | Java / C++(主要) |
| 服务端语言 | Java / C++ / Rust / NDK | Java / C++ |
hwservicemanager和servicemanager两套服务注册表,增加了系统复杂性和调试难度。迁移到AIDL后,所有系统服务(包括Camera HAL)共享同一个ServiceManager,简化了服务发现流程,降低了跨进程通信的维护成本。
3.4 稳定AIDL接口版本化规则
Android 11+引入的稳定AIDL要求接口必须版本化,且一旦发布冻结,不允许修改已有方法。版本化规则如下:
- 接口文件命名:
ICameraDevice.aidl(无版本号),版本信息通过目录结构体现。 - 目录结构:
hardware/interfaces/camera/aidl/android.hardware.camera/,版本号在current.txt中定义。 - 版本冻结:每个版本发布后,接口文件被复制到对应版本目录(如
aidl/android.hardware.camera-V1/),后续版本只能新增方法,不能修改或删除已有方法。 - 向后兼容:服务端可以同时实现多个版本接口,客户端通过
getInterfaceVersion()查询服务端支持的版本。
// 版本查询示例
ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str()));
auto service = ICameraDevice::fromBinder(binder);
if (service) {
int32_t version = service->getInterfaceVersion();
if (version >= 2) {
// 调用V2新增的方法
}
}
3.5 本章小结
本章系统回顾了AIDL的核心基础:接口定义语法支持基本类型、Parcelable类型和AIDL接口类型,方向标记in/out/inout控制数据流向;Android 11+的服务注册与发现机制统一使用ServiceManager,通过AServiceManager_addService()和AServiceManager_getService()实现;稳定AIDL的版本化规则确保了接口的长期兼容性。这些基础概念是理解后续Camera HAL AIDL化实践的前提。