AndroidCamera学习笔记四 Framework调用流程

Framework层流程

以个人的学习历程来看,在直接追代码看调用流程之前还是先来宏观看清楚Framework的结构层次比较好,有了宏观的层次结构再追代码看细节就很清晰明了了。

Framework的调用层次结构

在这里插入图片描述
在这张图中就比较清晰地看出Framework中的多层调用关系,网上有各种各样的资料,也对Framewrk层有各种不同的层次图,无所谓对错,只是Android版本不同造成的框架结构改变而已。比如在之前仅有HAL1和API1时就不需要选择client、device版本直接调,所以就没有图中的Service中的复杂结构。这张图就是在API1、API2、HAL1、HAL3共存的Android版本中的比较通用的结构图,当然不包括一些新版本细节上作出的修改。所以说这张图还是比较新的,适用于当下的大部分Android版本,同样也是来源与网络,如涉及侵权立即删除。
在这张图中可以看出API1和API2有一个很大的不同就是JNI层,API1通过JNI而API2没有。这是因为早期的版本需要通过JNI(可以看做是JAVA代码调用C++代码的一个转换层)来实现调用本地的C++代码。越接近底层越是使用高效率的编程语言,而API2中则并没有使用JNI的方式,而是直接使用IPCBinder机制实现与下层的交互。IPCBinder是一种跨进程通信机制利用了内核共享方式实现,简单来说就是在内存中开辟一个Binder区域让服务器与客户端在这里交互,让服务器向Binder中注册入信息,客户端向Binder取得信息通过Binder驱动与服务器进程通信。其他也有各种各样的不同,从API1到API2,HAL1到HAL3中经历了多次结构改变,虽然总的C/S架构未发生改变,但是交互及调用方式却发生了极大的变化。

API1调用流程

一、APP调用open()后执行Camera中的open方法()在open()方法中new了一个Camera对象,在构造函数中调用了cameraInit函数返回值来判断是否打开了Camera
在cameraInit函数中调用jni函数native_setup从这里开始进入到JNI层,在JNI层native_setup指向的是android_hardware_Camera_native_setup()方法,
三、在此方法中执行三个工作:
1、将clientPackageName从jstring转换为String16格式得到clientName
2、根据传过来的halVersion值来确定调用的connect函数
3、调用Camera::connect()/connectLegacy()方法去 请求连接CameraService服务
由此开始进入client端(以Hal1为例执行connectLegacy)
三、在connectLegacy函数中
1、拿到已经被打开的camera的ICamera接口
2、再获取ICameraClient接口
3、通过CameraBaseT::getCameraService()拿到ICameraService接口
4、通过cs.get是拿到CameraService,并调用connectLegacy,传入ICameraClient cl、ICamera /out/&(c→mCamera)等参数。
四、在connectLegacy函数中调用封装的函数connectHelper()并指定API_1
五、在connectHelper()主要是通过调用makeClient去拿到 Client,并调用client→initialize去初始化 CameraClient。
API1的执行方式比较单一,是初期比较简单的直接调用及回调结果的方法,从顶到低流程逐步调用,执行拍照录像预览也类似,这里就不展开了,毕竟本人的学习重点并不在Framework。

API2调用流程

在这里插入图片描述在API2流程中首先是由CameraManager通过IPCBinder机制获取一个在Java层的 CameraService的实例:在openCameraDeviceUserAsync()中首先获取 CameraService,然后通过它来开启指定的Camera,在开启成功后,Runtime层会 返回一个CameraDevice代理对象,然后在farmework层对其进行相应封装,变成一 个CameraDeviceImpl对象,至此,只需要对cameraDevice进行操作就会调用 CameraDeviceImpl对象的相关方法,并通过ICameraDeviceUser以及Java IPC Binder来与本地的Camera device进行通信
具体流程调用:
1、在openCamera()方法中调用了openCameraForUid方法
2、在openCameraForUid()中调用了openCameraDeviceUserAsync()
3、在openCameraDeviceUserAsync()中使用 CameraService binder 服务来获得camera 的信息并通过binder调用到 CameraService.cpp 的getCameraCharacteristics函数
RPC 跨进程调用 cameraService::connectDevice
通过binder调用到 CameraService.cpp 的connectDevice函数得到camerauser
调用setRemoteDevice(Camerauser)
4、这里开始进入Runtime层,跨进程调用connectDevice,在此方法中调用了 connectHelper,接收binder传过来的参数传给connectHelper
5、connectHelper中调用makeClient将数据绑定到client(CameraDeviceClient 对象)
在makeClient中根据不同的API版本及HAL版本调用不同的方法,在这里API2new 了一个CameraDeviceClient()
6、CameraDeviceClient构造函数之后会调用initialize初始化函数,在initialize中会将父 类初始化,传入了 CameraProviderManager
7、在Camera2ClientBase的构造函数中创建了Camera3Device调用进入HAL层
8、在setRemoteDevice中回调cameraDevicecallback中的onOpened,将 cameraDeciceImpl返回去
9、App层通过将返回的cameraDeciceImpl绑定到定义的CameraDevice中实现APP对 CameraDevice的操作即是操作cameraDeciceImpl
在这里插入图片描述API2中是管道和代理的思想,通过操作代理对象来映射实际操作。请求是在Framework开始分发的,例如预览和录像Framework并不是发了一个请求,而是多个,一个请求是一帧图像,HAL每次处理返回一帧图像。预览和录像在Framework是放在一个Repeat queue中处理的,不断地向HAL发图像请求。拍照则是一个请求,优先级大于预览。需要注意的是Framework层是分开两个进程处理的,在相机运行时,APP及Cameraservice之前的Framework是在一个进程中运行的,而CameraService是在开机时就注册到系统的ServiceManager中的作为独立进程与APP进行交互,这里可以看作APP为客户端,Cameraservice为服务器,是Camera一直以来的C/S架构。在Android8之后加入了Trable机制,就实现了HAL与Framework之间的HIDL机制。所以HAL也是独立运行的进程,与Framework通过HIDL进行交互。

总结

由于本人学习重点并不是Framework层,而且Framework层的东西确实不少,这部分是属于Android的架构,并不需要过分的更改。所以对于Framework层没有深究代码,想深入学习的同学可以下载一份最新的安卓源码进行阅读(看旧版的Android源码个人感觉意义不大,Android每年版本更迭改动不小)。Framework层更多的是理解Android的应用框架结构及交互方式,在实际生产中厂商对Framework改动很小,基本都是对请求内部一些内容的修改,更多的实现方式其实是放在了HAL,厂商提供的功能特异性都是在HAL实现的。简单来说,不同的厂商拿到的都是相同版本的Android源码是一样的,Framework是写好的,但是HAL是只留了接口需要厂商去填充实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值