3. AIDL服务端实现:Service注册、onBind方法、Binder线程池配置、服务端生命周期管理

在Camera HAL的AIDL多进程通信架构中,服务端是核心枢纽。它负责注册Service、处理客户端绑定请求、管理Binder线程池以及维护自身的生命周期。本章将深入剖析服务端实现的四个关键环节,确保Camera HAL服务能够稳定、高效地运行在独立的进程中。

3.1 Service注册:向系统宣告服务存在

Service注册是服务端启动的第一步,其核心目的是将Camera HAL服务发布到Android系统的ServiceManager中,使得客户端(如CameraService)能够通过名称查找到并绑定该服务。

关键点: 注册操作必须在Service的onCreate()或onBind()之前完成,以确保服务立即可用。

注册流程通常包含以下步骤:

  1. 获取ServiceManager代理: 通过BinderInternal.getContextObject()或ServiceManager.getService()获取与ServiceManager通信的代理。
  2. 添加服务: 调用ServiceManager.addService(String name, IBinder service),将Camera HAL的Binder实例注册到系统服务列表中。
  3. 权限检查: 注册过程通常需要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线程池在服务端的工作流程:

Binder线程池工作流程 客户端请求1 客户端请求2 客户端请求N Binder线程池 线程1 (处理请求1) 线程2 (处理请求2) 线程3 (等待中) 线程4 (等待中) Camera HAL 服务实现 (处理具体逻辑) 说明: • 客户端请求通过Binder驱动分发到线程池中的空闲线程。 • 线程池大小决定了并发处理能力,需根据Camera HAL的负载特性进行调优。

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生命周期的完整状态转换:

Service生命周期状态转换 未创建 已创建 已绑定 已销毁 onCreate() onBind() onUnbind() onDestroy() 重新创建 生命周期管理要点: • 确保在onDestroy()中释放所有Camera HAL资源,避免服务进程被杀时资源泄漏。

3.5 工程落地检查清单

在完成服务端实现后,建议对照以下清单进行验证:

  • 注册检查: 使用adb shell dumpsys service media.camera.hal确认服务已成功注册。
  • 绑定测试: 编写测试客户端,验证onBind()返回的Binder对象是否有效。
  • 线程池监控: 通过/proc/[pid]/task/查看Binder线程数量是否符合配置。
  • 生命周期测试: 反复启动和停止Service,检查是否有内存泄漏或资源未释放。
  • 并发压力测试: 模拟多个客户端同时绑定和调用,验证线程池是否能够正确处理。