以本文记录下学习sdm660 camera模块的总结:
首先特别感谢https://blog.csdn.net/armwind博主的文章
(一)目录
一. android camera系统架构图
二. opencamera
(1)Bn Bp对象的理解
(2)回调函数的注册,监听
(3)aidl—ICameraService,hidl--ICameraDevice
三. takepicture(zsl)
四. 参考资料
说明:
首先是按照我的理解绘制出了android camera系统架构图,
然后说明opencamera和takepicture(zsl)两个过程,其中重点是在opencamera,
通过这些天的学习,我发现opencamera是preview takepicture record的基础,
opencamera会初始化很多对象,而preview takepicture record等操作是围绕着这些对象进行操作的,
所以这里我用opencamera来理清各个对象间的交互关系,
用takepicture作为对象间交互关系的一个实例来讲解。
这里opencamera下列出的是需要注意的地方,opencamera时会说明
(1)Bn Bp对象的理解说明了camera工作时对象之间的关系
(2)回调函数的注册,监听为以后camera事件的回调打下基础
(3)aidl hidl涉及到binder IPC的相关内容,
aidl是CameraClient进程和CameraService进程交互的接口,
Hidl是framework层和hal层交互的接口!
(二)android camera系统架构图
android camera系统架构图
我将Camera模块的系统架构分为四层,
从上到下分别是package文件夹下的java层,framework文件夹下的framework层,hardware文件夹下的hal层和kernel文件夹下的driver层。
其中framework层下又细分为java framework,jni framework和hardwareinterface framework层;
hal层下又细分为hardwareinterface hal和mmcamera层;
而aidl是发生在jni framework层与hardwareinterface framework层交互的接口,即CameraClient进程与CameraService进程的交互;
hidl是发生在frame层和hal层交互的接口。
下面,我会按照java,framework,hal这三层来捋下opencamera的流程,一直捋到hal层的mmcamera层!
(三)opencamera
1.Java layer
我们先通过一张类图从java层看下camera模块是如何发送请求,并接收回调的:
Java层是通过AndroidCameraManagerImplemetation这个类来进行消息发送和数据回调的,
其中的CameraHandler类负责根据消息的不同类型调用不同的framework层接口,我们可以看到不用类型的消息用宏定义区分,
需要注意的是拍照的请求单独在一个公有接口里.
回调则是通过不同的回调类处理,这里previewCallback处理preview回调数据流,
ShutterCallback和PictureCallback处理拍照回调,shuttercallback与拍照完成瞬间的声音及动画有关,picturecallback是用来保存jpeg图片的。
需要注意的是这里回调的具体实现是在各个Module模块里,比如ShutterCallback的onshutter方法和PictureCallback的onPictureTaken方法具体是在PhotoModule.java里实现的!
在之后的回调分析中可以看到每一层都有相应的回调函数,会向上传递事件和数据,而最终处理事件和数据的地方是在Module模块里。
接下来我们根据OPEN_CAMERA继续向下看:
1.Framework layer
(1)Java framework layer
如之前说的,framework层里分为三个小层,这里先看java framework层:
Java framework层主要看的是camera类,660里使用的是camera1接口,所以这里调用的是openLegacy接口,
这里要注意的是在创建Camera对象时创建了EventHandler对象,
EventHandler对象会在一个线程里轮询事件消息,当有回调上来时,会根据消息类型调用不同的回调函数。
接下来我们顺着Native_setup这条线继续往下看,android_hardware_Camera_native_setup就到了Jni framework层!!!
(2)Jni framework layer
此图说明了opencamera在jni framework层做的事情,分别是
1请求连接 2设置监听 3接收回调 4转移回调 5传回上层
native_setup里主要做了两件事:
一是请求连接,这里调用到connectLegacy接口,
二是设置监听函数。
这里需要注意下设置监听的作用,从hardwareinterface framework层接收回调后,会调用到BnCameraClient的回调接口,
但并不是由BnCameraClient对象进行回调的上层回传,而是先进行回调转移到JNICameraContext对象,之后再通过JNICameraContext对象传回上层。
这与java层与cpp层的交互总是要经过Jni层是一个道理。
接下来就是整个framework层的核心了,我们看到这里有个BnCameraClient对象,这个对象到底是什么,我们来看下面这张图:
图中六个蓝色对象贯穿了整个Camera Client与Camera Service的交互过程:
我们一行行来看:
(1)请求连接,即刚才看到的connectLegacy操作,该操作是通过实现ICameraService的接口而完成的
(2)请求预览,拍照和录像等操作,这些操作是通过实现ICamera的接口而完成的
(3)通知消息,回调等,这些操作是通过实现ICameraClient接口而完成的
刚开始看到这六个对象时我是晕头转向的,
首先不知道Bn Bp的含义,
再者就是在我看的代码中只看到了CameraClient进程中的camera对象和CameraService进程中的cameraclient对象,哪里来的这么多对象???
为此,我们画一个简化的IInterface类图来慢慢说明!!!
这张IInerface类图的信息量比较大,主要包含以下几点:
(1)第一,我们看下接口负责的功能:
ICameaClient类负责定义回调等接口;
Icamera类负责定义请求预览,拍照,录像,自动对焦等接口;
ICameraService类则负责定义请求连接connectLegacy这个接口;
(2)第二,Bp Bn对象的说明:
这里Bn是指Binder native对象,即Binder本地对象;Bp是指Binder proxy对象,即Binder代理对象;
本地对象是指实际处理事件的对象,而代理对象的作用是通过Binder机制通知本地对象去处理相应的事件。
这里我们以BpCamera和BnCamera为例来说明下:
CameraClient进程的BpCamera对象发送startPreview请求后,会通过remote Binder IPC的方式找到
CameraService进程的BnCamera对象,进而调用BnCamera的startPreview方法。
(3)第三,我们来看下由ICameraClient ICameraService和Icamera衍生出来的对象:
首先是ICameraClient的衍生对象是CameraClient进程的camera对象,但观察camera对象可以看到camera对象不仅有ICameaClient的回调方法,
还有ICamera的预览拍照等方法,ICameraService的connectLegacy方法,刚开始这是有疑问的,
这里注意下camera对象的基类,是个模板类,分别有两个成员,
一个返回ICameraService对象,另一个是TCamUser成员,而TCamUser实际上是Icamera的类型别名,
这时所有疑问就都打开了:
原来CameraClient进程中的camera对象就是BnCameraClient对象,而BpCamera对象和BpCameraService对象则是BnCameraClient对象的两个成员!!!
同理:
CameraService进程中的cameraclient对象就是BnCamera对象,而BpCameraClient对象则是BnCamera对象的一个成员!!!
CameraService进程中的cameraservice对象就是BnCameraService对象.
(4)说明上一页PPT对应的三组操作对应的函数接口
根据如上所说的,就是三个对象在相互作用,CameraClient进程中的camera对象和CameraService进程的cameraclient对象 cameraservice对象。
Cameraservice对象是在手机开机过程中创建的,
那么现在还剩最后一个问题,CameraClient进程中的camera对象和CameraService进程的cameraclient对象是何时创建的?
其实就是在opencamera中的这个openLegacy!!!我们来看下openLegacy流程图:
说明下CameraClient进程中的camera对象和CameraService进程的cameraclient对象是如何创建的:
由此图可以看出,Camera的connectLegacy会调用到CameaService的connectLegacy,
Camera的connectLegacy的最后一个参数为输出参数,就是camera对象,对应BnCameraClient;
CameraService的connectLegacy的最后一个参数对应BnCamera,就是CameraClient对象。
CameraService的connectLegacy会调用到CameraClient::initialize,到下一层hardwareinterface framework layer.
(3)Hardwareinterface framework layer
这是Framework层的最后一层hardware接口层:
hardware接口层主要工作有两个:
(1)openSession,然后通过hidl实现与HAL层的交互
(2)第二,就是设置回调函数了
3.Hal layer
Hal层也有对应的hardware接口层,openCamera:
首先创建了hardware接口类的实例,然后调用到mm_camera_open接口并register_event_notify注册了事件通知器,
其中mm_camera_open主要完成一下操作:
打开节点,创建socket,起相关线程。
(四)takepicture(zsl)
1.发送请求流程
Java层,framework层和hal层依次下发takepicture请求,主要的流程同之前的分析所描述;
这里主要说下HAL层,从流程图中可以看出两点:
(1)Zsl takepictre的流程主要分两步:
Pre_take_picture
takpicture
(2)以消息队列的方式处理消息事件
2.接收回调流程
Takepicture涉及到的回调函数主要有两个:分别是shutterCallback jpepCallback
从图中我们可以看到:
Hardwareinterface hal layer对应的叫playShuter和processJpegNotify
而之后HAL层向上每个layer会有对应的notifycallback 和 datacallback
(五)参考资料
1.https://blog.csdn.net/armwind
2.linux_camera_software_design_document.pdf
3.camera_frontend_code_walkthrough_for_msm8974_msm8x26_linux_camera_software.pdf