Camera2 openCamera源码分析

在应用申请了camera权限后,camera2应用就可以调用CameraManager#openCamera打开指定的camera设备。在这个方法中,会先调用openCameraForUid添加uid参数,并最终在openCameraDeviceUserAsync方法中完成设备的打开流程。在这个方法中主要完成3件事情:1)创建CameraDeviceImpl,这个类是CameraDevice的实现类;2)通过CameraService的connectDevice接口获取底层camera设备类对ICameraDeviceUser;3)通过setRemote方法将设备类对象设置到CameraDeviceImp中。

/frameworks/base/core/java/android/hardware/camera2/CameraManager.java

在CameraDeviceImpl的setRemoteDevice流程中,主要完成的是将底层binder对象封装成ICameraDeviceUserWrapper并注册死亡通知,然后通过执行器在线程中完成camera设备打开的状态回调,最终camera应用获取到打开的camera对象,后续可以通过这个camera对象来完成camera命令的调用。

/frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java

在CameraService的connectDevice流程中,实际上是调用模板方法connectHelper来完成camera设备的打开。在这个方法中,主要完成3件事情:1)检查Camera权限和有效性校验;2)camera设备连接冲突检查;3)创建camera设备类对象并执行初始化流程。

/frameworks/av/service/camera/libcameraservice/CameraService.cpp

在CameraService的validateConnectLocked方法流程中,先通过validateConnectLocked方法检查camera uid和pid是否有效(由于上层下发的时候USE_CALLING_XXX,这个地方去应用进程对应的uid和pid)及检查camera设备权限(有public、system_only和hidden_secure三种,只有第一种设备能被应用访问)和camera使用权限是否匹配。然后再检查CameraService启动时CameraProviderManager的初始化状态,如果初始化成功,则会有设备信息上报,接下来获取camera id对应的设备是否存在及设备状态是否正常。

/frameworks/av/service/camera/libcameraservice/CameraService.cpp

在CameraService中的handleEvictionsLocked流程中,主要是通过mActiveClientManager获取当前所有已连接的camera设备的应用信息,然后创建当前camera id对应的DescriptorPtr,再通过mActiveClientManager#wouldEvict查找和当前DescriptorPtr冲突的设备列表。如果设备冲突列表中存在当前camera id对应的记录,则直接返回错误;否则将冲突列表中的所有camera设备断连。最后再检查一下camera设备状态是否正常,如果正常,则开始后续的camera创建和初始化操作。

/frameworks/av/service/camera/libcameraservice/CameraService.cpp

接下来分析一下mActiveClientManager#wouldEvict冲突列表获取流程,最终调用是在ClientManager.h文件中的wouldEvictLocked中完成。在这个方法中,主要是通过比较当前设备优先级和当前已打开设备应用优先级是否冲突,检查当前设备和已打开设备两者camera id是否一致,当前设备和已打开设备两者的冲突camera id列表(由hal层camera属性配置来决定)是否冲突,以及整体camera cost是否超过限制等因素来决定冲突列表。

/frameworks/av/service/camera/libcameraservice/utils/ClientManager.h

在CameraService中makeClient流程中,主要根据设备版本号和camera api的版本号来创建camera相关的设备。在camera2设备创建流程中主要是牵涉到三个类的创建,具体是CameraDeviceClient,Camera2ClientBase,Camera3Device。创建CameraDeviceClient对象流程中,由于CameraDeviceClient本身集成模板类Camera2ClientBase<CameraDeviceClientBase>,会调用Camera2ClientBase的构造函数,进而创建最终设备处理类Camera3Device。

/frameworks/av/service/camera/libcameraservice/CameraService.cpp

/frameworks/av/service/camera/libcameraservice/common/Camera2ClientBase.cpp

接下来分析CameraService中设备类CameraDeviceClient的initialize流程。在这个方法中,会调用到CameraDeviceClient#initializeImpl方法,然后调用Camera2ClientBase#initialize方法,最终调用到Camera2ClientBase#initializeImpl方法。在这个方法中,主要完成3件事情:1)调用CameraService::BasicClient#startCameraOps方法通知camera已经打开;2)调用Camera3Device的initialize流程;3)向Camera3Device注册通知回调。

/frameworks/av/service/camera/libcameraservice/common/Camera2ClientBase.cpp

/frameworks/av/service/camera/libcameraservice/CameraService.cpp

/frameworks/av/service/camera/libcameraservice/device3/Camera3Device.cpp

接下来着重分析一下Camera3Device的initialize流程。在这个流程中,主要完成5件事情:1)通过CameraProviderManager创建CameraDeviceSession,打开camera设备,后续通过session和hal camera进行通信;2)通过CameraProviderManager获取camera特征值和判断camera是否是逻辑camera;3)获取CameraDeviceSession中创建的RequestQueue和ResultQueue;4)将CameraDeviceSession和RequestQueue封装成HalInterface,作为后续Camera3Device中RequestThread和CameraDeviceSession之间通信的媒介;5)调用Camera3Device中initializeCommonLocked方法完成Camera3Device中PrepareThread和RequestThread线程的初始化。接下来主要分析1)和5)流程。

/frameworks/av/service/camera/libcameraservice/device3/Camera3Device.cpp

接下来分析CameraProviderManager中的OpenSession流程。在这个流程中,查找本地保存的camera id对应的deviceInfo3,并调用deviceInfo3#startDeviceInterface获取对应的CameraDevice,最终再执行CameraDevice的open方法打开camera并创建CameraDeviceSession。在deviceInfo3#startDeviceInterface方法中,获取provider对象,这个对象在系统启动的时候会获取并保存,这里是LegacyCameraProviderImpl_2_4对象,然后调用getCameraDeviceInterface_V3_x获取CameraDevice对象。

/frameworks/av/service/camera/libcameraservice/common/CameraProviderManager.cpp

/hardware/interfaces/camera/provider/2.4/default/LegacyProviderManager_2_4.cpp

通过CameraProviderManager中的deviceInfo3获取到CameraDevice后,会调用open创建CameraDeviceSession。在这个流程中,主要完成3件事情:1)通过Camera module打开hal层camera id对应的camera设备;2)通过Camera module获取hal camera信息,创建CameraDeviceSession,并将Camera3Device传递的ICameraDeviceCallback作为参数填入到CameraDeviceSession中,后续会通过这个回调上报Camera帧数据命令处理结果。3)通过Camera3Device参数回调传递创建的CameraDeviceSession。至此,Camera3Device#initialize流程中的openSession分析完成。

/hardware/interfaces/camera/device/3.2/default/CameraDevice.cpp

接下来分析Camera3Device#initializeCommonLocked流程中。在这个方法中,主要创建了PreparerThread和RequestThread两个线程,PrepareThread线程处理camera设备配置相关操作,RequestThread线程处理camera数据帧命令发送操作。执行其中的RequestThread,等待camera状态准备完成和命令发送。至此,整个openCamera流程分析完成。对于应用而言,获取到底层创建的CameraDevice对象。对于native层,创建了Camera相关设备类Camera3Device,通过camera module打开hal 层camera设备;创建了CameraDeviceSession用于和hal层进行通信;最后在Camera3Device中封装了HalInterface和CameraDeviceSession进行通信,并创建了PreparerThread和RequestThread来处理应用的命令和等待发送帧数据请求命令。

/frameworks/av/service/camera/libcameraservice/device3/Camera3Device.cpp

相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui