Android Camera 系统采用典型的三层架构设计,从上到下依次为:
这三层通过 Binder 和 HIDL 两种 IPC 机制实现跨进程通信。我在实际项目中发现,理解数据在架构中的流转路径对解决预览卡顿、拍照延迟等问题至关重要。
当应用调用 Camera.open() 时:
ServiceManager 获取 CameraService 代理CameraClient 对象并注册回调接口CameraService.connect() 建立连接关键代码示例:
cpp复制// frameworks/av/camera/CameraBase.cpp
sp<Camera> Camera::connect(int cameraId) {
sp<Camera> c = new Camera(cameraId);
sp<ICameraClient> cl = c;
sp<ICamera> camera;
cameraService->connect(cl, cameraId, ..., &camera);
c->mCamera = camera; // 保存服务端代理
}
跨进程通信时主要涉及两类数据:
CameraMetadata 传递参数配置GraphicBuffer 共享内存缓冲区我在调试时发现,错误配置 CameraMetadata 会导致 HAL 层返回 ILLEGAL_ARGUMENT 错误。建议使用 CameraMetadata#dump() 方法验证参数有效性。
Camera HAL 服务启动流程:
init 进程解析 android.hardware.camera.provider@2.4-service.rcandroid.hardware.camera.provider@2.4-impl.sodefaultPassthroughServiceImplementation 注册服务关键日志标记:
code复制cameraserver: CameraProviderManager::initialize
camera-provider: HIDL_FETCH_ICameraProvider
CameraService 通过 HIDL 调用 HAL 接口:
cpp复制// frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
status_t CameraProviderManager::initialize() {
mServiceProxy->getService("legacy/0", &interface);
interface->getCameraIdList([&](auto status, auto& devices) {
// 枚举设备列表
});
}
我在小米设备上实测发现,部分厂商会自定义 ICameraProvider 实现,导致设备枚举耗时差异可达 200ms 以上。
完整数据链路:
code复制HAL → Camera3Device → BufferQueue → Surface → SurfaceTexture → GL纹理
关键节点:
process_capture_result:HAL 返回图像数据Camera3OutputStream:管理输出流缓冲区IGraphicBufferProducer:跨进程传递 GraphicBuffer特殊处理环节:
CameraCaptureSession.CaptureCallbackCameraService 中高频调用接口:
connect():平均耗时 15msconfigureStreams():耗时 50-200mssubmitRequest():每帧调用,需 <5ms建议采用 异步调用+状态缓存 降低 IPC 开销。我在华为 P30 上实测,优化后预览延迟降低 23%。
典型 HAL 接口调用序列:
cpp复制// hardware/interfaces/camera/device/3.4/ICameraDeviceSession.hal
interface ICameraDeviceSession {
configureStreams(StreamConfiguration config);
processCaptureRequest(CaptureRequest request);
getCaptureResultMetadataQueue();
};
推荐配置:
GraphicBufferGraphicBuffer + 1 个 JPEG 缓冲区GraphicBuffer错误配置会导致 DEADLINE_EXCEEDED 错误。通过 dumpsys media.camera 可以查看当前缓冲区状态。
减少 CameraMetadata 更新的技巧:
ANDROID_REQUEST_ID 标记请求TEMPLATES常见错误日志:
code复制E Camera3-Device: RequestThread: waitUntilDrained timed out
W Binder: Transaction failed 29201
解决方案:
camera.provider 进程的 binder 线程数CameraMetadata 序列化大小检测方法:
shell复制adb shell dumpsys SurfaceFlinger --frametimeline
泄漏特征:
GraphicBuffer 计数STALE 状态的 buffer 未释放根本原因往往是未正确调用 releaseOutputBuffer()。建议实现 BufferQueue#onBufferReleased 回调进行监控。