在应用申请了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
/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