Architecture Legacy
Android Camera当前提供了两套API:API1.0和API2.0。API1.0和API2.0的区别是:
(1) API1.0相对简单且易于使用,应用可以做的事情不多。
(2) API2.0则要复杂得多,但是应用程序可以对底层相机有更多的控制权。比如:efficient zero-copy burst/streaming flows and per-frame controls of exposure, gain, white balance gains, color conversion, denoising, sharpening, and more.
由于Android软件每次更新总是会做到向前兼容,所以在现在的版本上API1.0的相机也是可以跑起来的。但是当前API1.0 Google已经不再提供更新,它会逐渐被淘汰掉。
有关更多Android各版本的细节参考:https://source.android.google.cn/devices/camera/versioning
整体架构概述(Camera2 + HAL3)
Android Camera整体框架主要包括三个进程:app进程、camera server进程、hal进程(provider进程)。进程之间的通信都是通过binder实现,其中app和camera server通信使用 AIDL(Android Interface Definition Language) ,camera server和hal(provider进程)通信使用HIDL(HAL interface definition language) 。
Android Camera2整体架构如下图:
上图Kernel层没有画出来,其它基本可以和Android系统框架对应起来。
大致分为这几个部分:
-
Application framework
这一层是用于给APP提供访问hardware的Camera API2,通过binder来访问camera service。有两个主要的类:(1) CameraManager,CameraManager是一个独一无二地用于检测、连接和描述相机设备的系统服务,负责管理所有的CameraDevice相机设备。通过ICameraService调用到CameraService。
// CameraManager.java private void connectCameraServiceLocked() { // CameraManager是一个系统服务,应该是开机就会被创建起来 IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME); ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder); // 返回Stub.Proxy对象,也就是ICameraServiceProxy CameraStatus[] cameraStatuses = cameraService.addListener(this); // 注册 ICameraServiceListener mCameraService = cameraService; }
(2) CameraDevice:CameraDevice是连接在安卓设备上的单个相机的抽象表示。通过ICameraDeviceUser调用到CameraDeviceClient。
CameraDevice是抽象类,CameraDeviceImpl.java继承了CameraDevice.java,并完成了抽象方法的具体实现。private CameraDevice openCameraDeviceUserAsync() { CameraDevice device = null; ICameraDeviceUser cameraUser = null; android.hardware.camera2.impl.CameraDeviceImpl deviceImpl = // CameraDeviceImp继承自CameraDevice new android.hardware.camera2.impl.CameraDeviceImpl(cameraId, ...); ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks(); // 获取CameraDevice的回调函数 ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); cameraUser = cameraService.connectDevice(callbacks, cameraId, ...); // connect到camera service,并将camera device callback注册进去 // 返回的ICameraDeviceUser就是CameraDeviceClient的本地接口 deviceImpl.setRemoteDevice(cameraUser); device = deviceImpl; return device; }
-
Native framework
代码路径位于:frameworks/av/camera/。提供了ICameraService、ICameraDeviceUser、ICameraDeviceCallbacks、ICameraServiceListener等aidl接口的实现。以及camera server的main函数。
AIDL基于Binder实现的一个用于让App fw代码访问native fw代码的接口。其实现存在于下述路径:frameworks/av/camera/aidl/android/hardware。(1) ICameraService 是相机服务的接口。用于请求连接、添加监听等。
(2) ICameraDeviceUser 是已打开的特定相机设备的接口。应用框架可通过它访问具体设备。
(3) ICameraServiceListener 和 ICameraDeviceCallbacks 分别是从 CameraService 和 CameraDevice 到应用框架的回调。 -
Camera Service
代码路径:frameworks/av/services/camera/。向上向APP提供服务,向下从HAL获取数据。(1) CameraService:如其名,相机服务,手机启动时会生成该类的对象。应用对ICameraService的函数调用,会访问到CameraService。
(2) CameraDeviceClient:当应用调用 openCamera() 打开指定相机设备时,会生成一个对应的CameraDeviceClient。应用通过对ICameraDeviceUser的函数调用,会访问到CameraDeviceClient。
(3) CameraProviderManager:CameraService对象生成时,创建的对象。同HAL交互。
(4) Camera3Device:应用调用 openCamera() 时生成该类的对象,即具体的Camera设备。作为系统工程师,Camera3Device的逻辑重点搞明白,这里是相当于是HAL的控制逻辑起始处,下图是Camera3Device和CameraProviderManager的UML类图:
-
HAL
Google的HAL定义了可以让Camera Service访问的标准接口。有关这些接口的具体实现则交由硬件厂商。代码路径:/hardware/interfaces/camera,下面是从该目录的 README.md 里面的内容。
The camera.* HAL tree is used by the Android camera service to discover and operate camera devices available on the device.
More details and versioning information can be found within each particular HAL.
More complete information about the Android camera HAL and subsystem can be found at source.android.com.
核心概念:Request
request是贯穿camera2数据处理流程最为重要的概念,应用框架是通过向camera子系统发送request来获取其想要的result。request有下述几个重要特征:
- 一个request可以对应一系列的result。
- request应当包含所有必要的配置信息,存放于metadata中。如:分辨率和像素格式;sensor、镜头、闪光等的控制信息;3A 操作模式;RAW 到 YUV 处理控件;以及统计信息的生成等。
- request需要携带对应的surface(也就是框架里面的stream),用于接收返回的图像。
- 多个request可以同时处于in-flight状态,并且submit request是non-blocking方式的。也就是说,上一个request没有处理完,也可以submit新的request。
- 队列中request的处理总是按照FIFO的形式。
- snapshot的request的preview的request拥有更高的优先级。
request的整体处理流程如下图:
- open 流程(黑色箭头线条)
- CameraManager注册AvailabilityCallback回调,用于接收相机设备的可用性状态变更的通知。
- CameraManager通过调用getCameraIdList()获取到当前可用的camera id,通过getCameraCharacteristcs()函数获取到指定相机设备的特性。
- CameraManager调用openCamera()打开指定相机设备,并返回一个CameraDevice对象,后续通过该CameraDevice对象操控具体的相机设备。
- 使用CameraDevice对象的createCaptureSession()创建一个session,数据请求(预览、拍照等)都是通过session进行。在创建session时,需要提供Surface作为参数,用于接收返回的图像。
- configure stream流程(蓝色箭头线条)
- 申请Surface,如上图的OUTPUT STREAMS DESTINATIONS框,用于在创建session时作为参数,接收session返回的图像。
- 创建session后,surface会被配置成框架的stream。在框架中,stream定义了图像的size及format。
- 每个request都需要携带target surface用于指定返回的图像是归属到哪个被configure的stream的。
- request处理流程(橙色箭头线条)
- CameraDevice对象通过createCaptureRequest()来创建request,每个reqeust都需要有surface和settings(settings就是metadata,request包含的所有配置信息都是放在metadata中的)。
- 使用session的capture()、captureBurst()、setStreamingRequest()、setStreamingBurst()等api可以将request发送到框架。
- 预览的request,通过setStreamingRequest()、setStreamingBurst()发送,仅调用一次。将request set到repeating request list里面。只要pending request queue里面没有request,就将repeating list里面的request copy到pending queue里面。
- 拍照的request,通过capture()、captureBurst()发送,每次需要拍照都会调用。每次触发,都会直接将request入到pending request queue里面,所以拍照的request比预览的request的优先级更高。
- in-progress queue代表当前正在处理的request的queue,每处理完一个,都会从pending queue里面拿出来一个新的request放到这里。
- 数据返回流程(紫色箭头线条)
- 硬件层面返回的数据会放到result里面返回,会通过session的capture callback回调响应。
request在HAL的处理方式
- framework发送异步的request到hal。
- hal必须顺序处理request,对于每一个request都要返回timestamp(shutter,也就是帧的生成时间)、metadata、image buffers。
- 对于request引用的每一类steam,必须按FIFO的方式返回result。比如:对于预览的stream,result id 9必须要先于result id 10返回。但是拍照的stream,当前可以只返回到result id 7,因为拍照和预览用的stream不一样。
- hal需要的信息都通过request携带的metadata接收,hal需要返回的信息都通过result携带的metadata返回。
HAL处理request的整体流程如下图。
- request处理流程(黑色箭头线条)
- framework异步地submit request到hal,hal依次处理,并返回result。
- 每个被submit到hal的request都必须携带stream。stream分为input stream和output stream:input stream对应的buffer是已有图像数据的buffer,hal对这些buffer进行reprocess;output stream对应的buffer是empty buffer,hal将生成的图像数据填充的这些buffer里面。
- input stream处理流程(图像的INPUT STREAM 1)
- request携带input stream及input buffer到hal。
- hal进行reprocess,然后新的图像数据重新填充到buffer里面,返回到framework。
- output stream处理流程(图像的OUTPUT STREAM 1…N)
- request携带output stream及output buffer到hal。
- hal经过一系列模块的的处理,将图像数据写到buffer中,返回到frameowork。