3. AIDL服务端实现:Service注册、onBind方法、Binder线程池配置、服务端生命周期管理
在Camera HAL的AIDL多进程通信架构中,服务端是核心枢纽。它负责注册Service、处理客户端绑定请求、管理Binder线程池以及维护自身的生命周期。本章将深入剖析服务端实现的四个关键环节,确保Camera HAL服务能够稳定、高效地运行在独立的进程中。
3.1 Service注册:向系统宣告服务存在
Service注册是服务端启动的第一步,其核心目的是将Camera HAL服务发布到Android系统的ServiceManager中,使得客户端(如CameraService)能够通过名称查找到并绑定该服务。
关键点: 注册操作必须在Service的
onCreate()或onBind()之前完成,以确保服务立即可用。
注册流程通常包含以下步骤:
- 获取ServiceManager代理: 通过
BinderInternal.getContextObject()或ServiceManager.getService()获取与ServiceManager通信的代理。 - 添加服务: 调用
ServiceManager.addService(String name, IBinder service),将Camera HAL的Binder实例注册到系统服务列表中。 - 权限检查: 注册过程通常需要
android.permission.ADD_SYSTEM_SERVICE权限,确保只有系统级进程才能注册关键服务。
以下是一个典型的注册代码片段:
// CameraHalService.java
public class CameraHalService extends Service {
private static final String TAG = "CameraHalService";
private ICameraHalService.Stub mBinder;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "CameraHalService onCreate");
mBinder = new CameraHalServiceImpl();
// 注册到ServiceManager
ServiceManager.addService("media.camera.hal", mBinder);
Log.d(TAG, "Service registered: media.camera.hal");
}
// ...
}
工程建议: 在注册前,建议先检查服务是否已被注册,避免重复注册导致异常。可以使用
ServiceManager.checkService()进行预检。
3.2 onBind方法:建立客户端与服务端的桥梁
onBind()是Service生命周期中用于返回Binder对象的关键方法。当客户端通过bindService()发起连接请求时,系统会调用此方法,并将返回的IBinder对象传递给客户端。
在Camera HAL场景中,onBind()的实现需要满足以下要求:
- 返回AIDL接口的Stub实现: 必须返回实现了
ICameraHalService.Stub的Binder对象。 - 支持多客户端并发绑定: 同一个Binder实例可以被多个客户端共享,系统会为每个客户端创建独立的Binder代理。
- 权限验证: 可以在
onBind()中通过checkCallingPermission()验证客户端是否具有访问Camera HAL的权限。
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind called, intent: " + intent);
// 权限检查示例
if (checkCallingPermission("android.permission.CAMERA")
!= PackageManager.PERMISSION_GRANTED) {
Log.w(TAG, "Client does not have CAMERA permission");
return null; // 拒绝绑定
}
return mBinder;
}
注意: 如果
onBind()返回null,客户端将无法建立连接,且ServiceConnection.onServiceConnected()不会被调用。务必确保在服务可用时返回有效的Binder对象。
3.3 Binder线程池配置:掌控并发与性能
Binder线程池是处理客户端IPC请求的核心资源池。默认情况下,Binder线程池的大小为16个线程,但在高并发的Camera HAL场景中,可能需要根据实际负载进行调整。
配置Binder线程池主要通过BinderInternal类提供的接口:
| 配置项 | 方法 | 说明 | 推荐值(Camera HAL) |
|---|---|---|---|
| 最大线程数 | BinderInternal.setMaxThreads(int) |
设置Binder线程池的最大线程数量 | 32 ~ 64 |
| 线程名称前缀 | 通过Thread.setDefaultUncaughtExceptionHandler()间接控制 |
便于调试时识别Binder线程 | “CameraBinder” |
| 线程优先级 | 在Binder回调中通过Process.setThreadPriority()调整 |
确保Camera处理线程具有实时性 | THREAD_PRIORITY_URGENT_DISPLAY |
以下是一个在Service启动时配置Binder线程池的示例:
@Override
public void onCreate() {
super.onCreate();
// 配置Binder线程池
BinderInternal.setMaxThreads(48);
Log.d(TAG, "Binder thread pool configured: maxThreads=48");
// 注册服务
mBinder = new CameraHalServiceImpl();
ServiceManager.addService("media.camera.hal", mBinder);
}
性能考量: 增加线程数可以提高并发处理能力,但也会增加上下文切换开销。建议通过压力测试确定最优值,避免线程数过多导致CPU资源耗尽。
下图展示了Binder线程池在服务端的工作流程:
3.4 服务端生命周期管理
Service的生命周期直接影响Camera HAL服务的可用性和资源管理。服务端需要妥善处理创建、绑定、销毁等各个阶段,确保资源正确释放。
生命周期管理的关键节点包括:
| 生命周期方法 | 触发时机 | Camera HAL中的典型操作 |
|---|---|---|
onCreate() |
Service首次创建时 | 初始化Binder对象、注册Service、配置线程池、加载HAL库 |
onBind() |
客户端发起绑定请求时 | 权限验证、返回Binder实例、记录客户端连接数 |
onUnbind() |
客户端解除绑定时 | 清理客户端资源、减少连接计数、判断是否可销毁 |
onDestroy() |
Service被销毁时 | 释放HAL资源、关闭Camera设备、注销Service |
以下是一个完整的生命周期管理实现:
public class CameraHalService extends Service {
private ICameraHalService.Stub mBinder;
private int mClientCount = 0;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service created");
// 初始化Binder线程池
BinderInternal.setMaxThreads(48);
// 创建Binder实现
mBinder = new CameraHalServiceImpl();
// 注册服务
ServiceManager.addService("media.camera.hal", mBinder);
}
@Override
public IBinder onBind(Intent intent) {
mClientCount++;
Log.d(TAG, "Client bound, total clients: " + mClientCount);
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
mClientCount--;
Log.d(TAG, "Client unbound, remaining clients: " + mClientCount);
// 如果没有客户端绑定,可以准备销毁
if (mClientCount <= 0) {
// 可以触发垃圾回收或资源清理
}
return false; // 不支持重新绑定
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service destroyed");
// 释放Camera HAL资源
CameraHalNative.release();
// 从ServiceManager移除服务(可选)
// ServiceManager.removeService("media.camera.hal");
}
}
最佳实践: 在
onDestroy()中,务必确保所有Camera设备已关闭、所有分配的Buffer已释放,避免内存泄漏或设备锁死。
下图展示了Service生命周期的完整状态转换:
3.5 工程落地检查清单
在完成服务端实现后,建议对照以下清单进行验证:
- 注册检查: 使用
adb shell dumpsys service media.camera.hal确认服务已成功注册。 - 绑定测试: 编写测试客户端,验证
onBind()返回的Binder对象是否有效。 - 线程池监控: 通过
/proc/[pid]/task/查看Binder线程数量是否符合配置。 - 生命周期测试: 反复启动和停止Service,检查是否有内存泄漏或资源未释放。
- 并发压力测试: 模拟多个客户端同时绑定和调用,验证线程池是否能够正确处理。