Camera Hal3在Framework架构(五):CameraService篇

(1)CameraService架构

Camera Service是随着系统启动而运行,主要目的是向外暴露AIDL接口给Framework进行调用,同时通过调用Camera Provider的HIDL接口,建立与Provider的通信,并且在内部维护从Framework以及Provider获取到的资源,且按照一定的框架结构保持整个Service在稳定高效的状态下运行。

当系统启动的时候会首先运行main_cameraserver程序,紧接着调用了CameraService的instantiate方法,该方法最终会调用到CameraService的onFirstRef方法,在这个方法里面便开始了整个CameraService的初始化工作。
Camera Hal3在Framework架构(五):CameraService篇_第1张图片
通过以上的动作,Camera Service进程便运行起来了,获取了Camera Provider的代理,同时也将自身关于Camera Provider的回调注册到了Provider中,这就建立了与Provider的通讯,另一边,通过服务的形式将AIDL接口也暴露给了Framework,静静等待来自Framework的请求。

(2)处理App请求

当打开了相机应用,便会去调用CameraManager的openCamera方法进而走到Framework层处理,Framework通过内部处理,最终将请求下发到Camera Service中,而在Camera Service主要做了获取相机设备属性、打开相机设备,然后App通过返回的相机设备,再次下发创建Session以及下发Request的操作。

(A)获取属性

由于在Camera Service启动初始化的时候已经获取了相应相机设备的属性配置,并存储在DeviceInfo3中,所以该方法就是从对应的DeviceInfo3中取出属性返回即可。

(B)打开相机

对于打开相机设备动作,主要由connectDevice来实现,当CameraFramework通过调用ICameraService的connectDevice接口的时候,主要做了两件事情:

  • 一个是创建CameraDeviceClient;
  • 一个是对CameraDeviceClient进行初始化,并将其给Framework;

而其中创建CameraDevcieClient的工作是通过makeClient方法来实现的,在该方法中首先实例化一个CameraDeviceClient,并且将来自Framework针对ICameraDeviceCallbacks的实现类CameraDeviceImpl.CameraDeviceCallbacks存入CameraDeviceClient中,这样一旦有结果产生便可以将结果通过这个回调回传给Framework,其次还实例化了一个Camera3Device对象。

其中的CameraDeviceClient的初始化工作是通过调用其initialize方法来完成的,在该方法中:

  • 首先调用父类Camera2ClientBase的initialize方法进行初始化;
  • 其次实例化FrameProcessorBase对象并且将内部的Camera3Device对象传入其中,这样就建立了FrameProcessorBase和Camera3Device的联系,之后将内部线程运行起来,等待来自Camera3Device的结果;
  • 最后将CameraDeviceClient注册到FrameProcessorBase内部,这样就建立了与CameraDeviceClient的联系;

而在Camera2ClientBase的intialize方法中会调用Camera3Device的intialize方法对其进行初始化工作,并且通过调用Camera3Device的setNotifyCallback方法将自身注册到Camera3Device内部,这样一旦Camera3Device有结果产生就可以发送到CameraDeviceClient中。

而在Camera3Device的初始化过程中,首先通过调用CameraProviderManager的openSession方法打开并获取一个Provider中的ICameraDeviceSession代理,其次实例化一个HalInterface对象,将之前获取的ICameraDeviceSession代理存入其中,最后将RequestThread线程运行起来,等待Request的下发。

而对于CameraProviderManager的openSession方法,它会通过内部的DeviceInfo保存的ICameraDevice代理,调用其open方法从Camera Provider中打开并获取一个ICameraDeviceSession远程代理,并且由于Camera3Device实现了Provider中ICameraDeviceCallback方法,会通过该open方法传入到Provider中,接收来自Provider的结果回传。

至此,整个connectDevice方法已经运行完毕,此时App已经获取了一个Camera设备,紧接着,由于需要采集图像,所以需要再次调用CameraDevice的createCaptureSession操作,到达Framework,再通过ICameraDeviceUser代理进行了一系列操作,分别包含了cancelRequest/beginConfigure/deleteStream/createStream以及endConfigure方法来进行数据流的配置。

(C)配置数据流

  • cancelRequest对应的方法是CameraDeviceClient的cancelRequest方法,在该方法中会去通知Camera3Device将RequestThread中的Request队列清空,停止Request的继续下发;
  • beginConfigure方法是空实现,这里不进行阐述;
  • deleteStream/createStream 分别是用于删除之前的数据流以及为新的操作创建数据流;
  • endConfigure方法,该方法对应着CameraDeviceClient的endConfigure方法,该方法中会调用Camera3Device的configureStreams的方法,而该方法又会去通过ICameraDeviceSession的configureStreams_3_4的方法最终将需求传递给Provider。

到这里整个数据流已经配置完成,并且App也获取了Framework中的CameraCaptureSession对象,之后便可进行图像需求的下发了,在下发之前需要先创建一个Request,而App通过调用CameraDeviceImpl中的createCaptureRequest来实现,该方法在Framework中实现,内部会再去调用Camera Service中的AIDL接口createDefaultRequest,该接口的实现是CameraDeviceClient,在其内部又会去调用Camera3Device的createDefaultRequest方法,最后通过ICameraDeviceSession代理的constructDefaultRequestSettings方法将需求下发到Provider端去创建一个默认的Request配置,一旦操作完成,Provider会将配置上传至Service,进而给到App中。

(D)处理图像需求(预览+拍照)

在创建Request成功之后,便可下发图像采集需求了,这里大致分为两个流程,一个是预览,一个拍照,两者差异主要体现在Camera Service中针对Request获取优先级上,一般拍照的Request优先级高于预览,具体表现是当预览Request在不断下发的时候,来了一次拍照需求,在Camera3Device 的RequestThread线程中,会优先下发此次拍照的Request。这里我们主要梳理下下发拍照request的大体流程:

下发拍照Request到Camera Service,其操作主要是由CameraDevcieClient的submitRequestList方法来实现,在该方法中,会调用Camera3Device的setStreamingRequestList方法,将需求发送到Camera3Device中,而Camera3Device将需求又加入到RequestThread中的RequestQueue中,并唤醒RequestThread线程,在该线程被唤醒后,会从RequestQueue中取出Request,通过之前获取的ICameraDeviceSession代理的processCaptureRequest_3_4方法将需求发送至Provider中,由于谷歌对于processCaptureRequest_3_4的限制,使其必须是非阻塞实现,所以一旦发送成功,便立即返回,在App端便等待这结果的回传。

(E)接收图像结果

针对结果的获取是通过异步实现,主要分别两个部分,一个是事件的回传,一个是数据的回传,而数据中又根据流程的差异主要分为Meta Data和Image Data两个部分,接下来我们详细介绍下:

在下发Request之后,首先从Provider端传来的是Shutter Notify,因为之前已经将Camera3Device作为ICameraDeviceCallback的实现传入Provider中,所以此时会调用Camera3Device的notify方法将事件传入Camera Service中,紧接着通过层层调用,将事件通过CameraDeviceClient的notifyShutter方法发送到CameraDeviceClient中,之后又通过打开相机设备时传入的Framework的CameraDeviceCallbacks接口的onCaptureStarted方法将事件最终传入Framework,进而给到App端。

在Shutter事件上报完成之后,当一旦有Meta Data生成,Camera Provider便会通过ICameraDeviceCallback的processCaptureResult_3_4方法将数据给到Camera Service,而该接口的实现对应的是Camera3Device的processCaptureResult_3_4方法,在该方法会通过层层调用,调用sendCaptureResult方法将Result放入一个mResultQueue中,并且通知FrameProcessorBase的线程去取出Result,并且将其发送至CameraDeviceClient中,之后通过内部的CameraDeviceCallbacks远程代理的onResultReceived方法将结果上传至Framework层,进而给到App中进行处理。

随后Image Data前期也会按照类似的流程走到Camera3Device中,但是会通过调用returnOutputBuffers方法将数据给到Camera3OutputStream中,而该Stream中会通过BufferQueue这一生产者消费者模式中的生产者的queue方法通知消费者对该buffer进行消费,而消费者正是App端的诸如ImageReader等拥有Surface的类,最后App便可以将图像数据取出进行后期处理了。

(3)总结

谷歌将平台厂商的实现放入vendor分区中,彻底将系统与平台厂商在系统分区上保持了隔离,此时,谷歌便顺势将Camera HAL Moudle从Camera Service中解耦出来放到了vendor分区下的独立进程Camera Provider中,所以之后,Camera Service 的职责便是承接来自Camera Framework的请求,之后将请求转发至Camera Provider中,作为一个中转站的角色存在在系统中。

你可能感兴趣的:(Android,Camera专项,Hal3架构)