OpenCamera流程详细分析(Camera1+Hal1)

以本文记录下学习sdm660 camera模块的经验总结。

整体思路:

1 android camera系统架构图

2 opencamera

(1)Bn Bp对象的理解

说明了camera工作时对象之间的关系.

(2)回调函数的注册与监听

为以后camera事件的回调打下基础.

(3)aidl—ICameraService,hidl--ICameraDevice

aidl是app层和framework层进程间通信的接口(CameraClient进程和CameraService进程),hidl是framework层和hal层进程间通信的接口.

3 takepicture(zsl)

4 参考资料

opencamera是preview、takepicture、record的基础,opencamera过程会初始化很多对象,而preview、takepicture、record等操作是围绕着这些对象进行操作的,所以这里用opencamera来理清各个对象间的交互关系,用takepicture作为对象间交互关系的一个实例来讨论。

1 android camera系统架构图

 android camera系统架构图

我将Camera模块的系统架构分为四层,从上到下分别是package文件夹下的java层,framework文件夹下的framework层,hardware文件夹下的hal层和kernel文件夹下的driver层。其中framework层下又细分为java framework,jni framework和hardwareinterface framework层;hal层下又细分为hardwareinterface层和mmcamera层。

aidl是发生在jni framework层与hardwareinterface framework层进程间通信的接口,即CameraClient进程与CameraService进程的交互;hidl是发生在frame层和hal层进程间通信的接口。

aidl与hidl的对比:

下面,我会按照java,framework,hal这三层来讲解下opencamera的流程,一直到hal层的mmcamera层。

2 opencamera 

2.1 Java layer

我们从java层看下camera模块是如何发送请求,并接收回调的:

Java层是通过AndroidCameraManagerImpl这个类来进行消息发送和数据回调的,其中的CameraHandler子类负责根据不同的消息类型调用不同的framework层接口,我们可以看到不同类型的消息是用宏定义区分的,需要注意的是拍照的请求单独在一个公有接口里。

回调则是通过不同的回调子类处理,previewCallback处理preview回调数据流,ShutterCallback和PictureCallback处理拍照回调,shuttercallback与拍照完成瞬间的声音及动画有关,picturecallback是用来保存jpeg图片的。需要注意的是这里回调的具体实现是在各个Module模块里,比如ShutterCallback的onshutter方法和PictureCallback的onPictureTaken方法具体是在PhotoModule.java里实现的!在之后的回调分析中可以看到每一层都有相应的回调函数,会向上传递事件和数据,而最终处理事件和数据的地方是在Module模块里。

接下来我们顺着OPEN_CAMERA继续向下看:

2.2 Framework layer

2.2.1 Java framework layer

如之前所说,framework层里分为三层,这里先看java framework层:

java framework层主要看的是camera类,sdm660里使用的是camera1接口,所以这里调用的是openLegacy接口,这里要注意的是在创建Camera对象时创建了EventHandler对象,EventHandler对象会在一个线程里轮询事件消息,当有回调上来时,会根据不同的消息类型调用不同的回调函数。

接下来我们顺着native_setup这条线继续往下看,android_hardware_Camera_native_setup就到了Jni framework层!

2.2.2 Jni framework layer

上图说明了opencamera在jni framework层做的事情,分别是

1 请求连接

2 设置监听

3 接收回调

4 转移回调

5 传回上层

native_setup里主要做了两件事:

1 请求连接,这里是调用connectLegacy接口

2 设置监听函数

这里需要注意下设置监听的作用,从hardwareinterface framework层接收到数据或消息回调后,会调用到BnCameraClient相应的回调接口,但并不是由BnCameraClient直接对上层进行数据或消息的回调,而是先进行回调转移到JNICameraContext对象,之后再通过JNICameraContext对象传回上层。这与java层与native层的交互总是要经过Jni层是一个道理。

接下来就是整个framework层的核心了,我们看到这里有个BnCameraClient对象,这个对象到底是什么呢,我们来看下面这张图:

图中6个蓝色对象贯穿了Camera Client进程与Camera Service进程的整个交互过程,我们一行行来看:

1 请求连接,即刚才看到的connectLegacy操作,该操作是通过实现ICameraService的接口而完成的

2 请求预览,拍照和录像等操作,这些操作是通过实现ICamera的接口而完成的

3 通知消息,回调等,这些操作是通过实现ICameraClient接口而完成的

刚开始看到这6个对象时我是晕头转向的,首先是不知道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本地对象是指实际处理事件的对象,而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方法。这里有疑问的,因为只继承了ICameraClient接口,派生类应该只有回调方法,其他方法哪里来的?原来,这里注意下camera对象的基类,是个模板类,分别有两个成员,一个返回ICameraService对象,另一个是TCamUser成员,而TCamUser实际上是Icamera的类型别名。这时所有疑问就都打开了:原来CameraClient进程中的camera对象就是BnCameraClient对象,而BpCamera对象和BpCameraService对象则是BnCameraClient对象的两个成员!

同理:

CameraService进程中的cameraclient对象就是BnCamera对象,而BpCameraClient对象则是BnCamera对象的一个成员。

CameraService进程中的cameraservice对象就是BnCameraService对象。

总结:

根据如上所说的,其实就是3个对象在相互作用:分别是CameraClient进程中的camera对象、CameraService进程的cameraclient对象和cameraservice对象。

CameraService进程的cameraservice对象是在手机开机过程中创建的,那么现在还剩最后一个问题,CameraClient进程中的camera对象和CameraService进程的cameraclient对象是何时创建的?

其实就是在opencamera中的这个openLegacy!我们来看下openLegacy流程图:

由上图可以看出,CameraClient进程的Camera类的connectLegacy函数会通过aidl调用到CameraService进程的CameraService类的connectLegacy函数。Camera类的connectLegacy的最后一个参数为输出参数,对应BnCameraClient,就是camera对象;CameraService类的connectLegacy的最后一个参数为输出参数,对应BnCamera,就是cameraclient对象。

继续往下讲,CameraService类的的connectLegacy会调用到CameraClient::initialize,到了下一层hardwareinterface framework layer.

2.2.3 Hardwareinterface framework layer

这是Framework层的最后一层hardwareinterface层,hardwareinterface层主要工作有2个:

1 openSession,然后通过hidl实现与Hal层的交互(Hal层进程叫?)

2 设置回调函数

2.3 Hal layer

Hal层也有对应的hardwareinterface层,QCamera2HardwareInterface::openCamera():

首先创建了hardwareinterface类的实例,然后调用到mm_camera_open接口并register_event_notify注册了事件通知器,其中mm_camera_open主要完成一下操作:

打开设备节点,创建socket,起相关线程。

3 takepicture(zsl)

3.1 发送请求流程

Java,Framework层和Hal层依次下发takepicture请求,主要的流程同之前的分析所描述;

这里主要说下HAL,从流程图中可以看出两点:

zsl takepictre的流程主要分两步:

pre_take_picture

takpicture

以消息队列的方式处理消息事件

3.2 接收回调流程

Takepicture涉及到的回调函数主要有两个,分别是shutterCallbackjpepCallback:

从图中我们可以看到:

Hardwareinterface hal layer对应的叫playShuterprocessJpegNotify

而之后HAL层向上每个layer会有对应的notifycallbackdatacallback。

4 参考资料

https://blog.csdn.net/armwind

linux_camera_software_design_document.pdf

camera_frontend_code_walkthrough_for_msm8974_msm8x26_linux_camera_software.pdf

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值