Android Camera(四) 从CameraService到HAL:getCameraIdList的跨层调用与状态同步机制
1. 从CameraManager到CameraService的调用链当我们在Android应用中调用CameraManager.getCameraIdList()时这个看似简单的API背后隐藏着跨越四层架构的复杂通信机制。让我们先看看Java框架层发生了什么在CameraManager.java中实际工作交给了CameraManagerGlobal单例。我曾在调试时发现这里的关键在于一个叫mDeviceStatus的ArrayMap结构。这个Map保存了所有相机设备的ID和状态它的数据来源有两个途径// CameraManagerGlobal.java核心逻辑 public String[] getCameraIdList() { synchronized(mLock) { connectCameraServiceLocked(); // 连接服务并注册监听 // 过滤掉NOT_PRESENT和ENUMERATING状态的设备 return mDeviceStatus.keySet().toArray(new String[0]); } }connectCameraServiceLocked()方法做了三件重要的事通过ServiceManager获取CameraService的Binder代理调用addListener将自己注册为监听器接收初始相机列表并更新mDeviceStatus这里有个容易踩坑的地方addListener是同步调用而后续的状态更新是通过异步回调。我在项目中就遇到过因时序问题导致的列表不一致解决方案是在首次获取列表后增加状态验证。2. CameraService的枢纽作用CameraService作为承上启下的关键层维护着两个核心数据结构mCameraStates记录所有相机设备状态mListenerList存储注册的监听器当CameraService收到addListener调用时它会执行以下操作// CameraService.cpp片段 Status CameraService::addListener(...) { mListenerList.push_back(listener); // 注册监听器 for (auto state : mCameraStates) { // 返回当前所有设备状态 cameraStatuses-emplace_back(state.first, state.second-getStatus()); } }我在分析日志时发现mCameraStates的更新来源于两种事件主动枚举系统启动时通过enumerateProviders()触发被动通知HAL层检测到设备插拔时回调特别要注意的是状态同步机制。CameraService使用StatusInternal枚举来管理内部状态这个状态需要与HAL层的CameraDeviceStatus进行映射。在Android P版本中这种映射关系曾导致某些厂商设备的兼容性问题。3. HAL层的双向通信CameraProvider作为HAL层的实现者通过getCameraIdList和setCallback建立起双向通信通道// CameraProvider.cpp关键代码 Returnvoid CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) { for (auto device : mCameraDeviceNames) { if (mCameraStatusMap[device.first] PRESENT) { deviceNameList.push_back(device.second); } } _hidl_cb(Status::OK, deviceNameList); }这里有个设计精妙之处mCameraDeviceNames和mCameraStatusMap的维护。通过分析源码我发现它们的更新路径是初始化时通过addDeviceNames填充状态变更时通过sCameraDeviceStatusChange回调更新在真实设备上测试时如果厂商没有正确实现camera_module_callbacks_t会导致热插拔事件无法通知上层。这时就需要检查HAL实现是否符合CDD要求。4. 状态同步的监听者模式整个架构最精彩的部分是其状态同步机制它采用了多级监听者模式Java层监听CameraManagerGlobal实现ICameraServiceListenerNative层监听CameraService实现CameraProviderManager::StatusListenerHAL层监听CameraProvider继承camera_module_callbacks_t这种设计带来一个挑战状态变更的线程安全问题。我在性能分析时发现当频繁插拔USB摄像头时如果锁粒度控制不好会导致回调阻塞。Android P的解决方案是使用mServiceLock保护核心状态回调处理采用异步队列状态变更合并处理在实际开发中如果需要扩展这种机制建议参考CameraService的updateStatus方法它展示了如何处理状态冲突和去重。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2495037.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!