整體架構概述
Android Camera整體框架主要包括三個進程:app進程、camera server進程、hal進程。進程之間的通信都是通過binder實現,其中app和camera server通信使用aidl,camera server和hal通信使用hidl。Android Camera2整體架構如下圖:
大致分爲這幾個部分:
- Application framework
這一層是用於給APP提供訪問hardware的Camera API2,通過binder來訪問camera service。有兩個主要的類:
- 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;
}
- CameraDevice:CameraDevice是連接在安卓設備上的單個相機的抽象表示。通過ICameraDeviceUser調用到CameraDeviceClient。
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;
}
- AIDL
基於Binder實現的一個用於讓App fw代碼訪問natice fw代碼的接口。其實現存在於下述路徑:frameworks/av/camera/aidl/android/hardware。其中:
(1) ICameraService 是相機服務的接口。用於請求連接、添加監聽等。
(2) ICameraDeviceUser 是已打開的特定相機設備的接口。應用框架可通過它訪問具體設備。
(3) ICameraServiceListener 和 ICameraDeviceCallbacks 分別是從 CameraService 和 CameraDevice 到應用框架的回調。 - Natice framework
代碼路徑位於:frameworks/av/。提供了ICameraService、ICameraDeviceUser、ICameraDeviceCallbacks、ICameraServiceListener等aidl接口的實現。以及camera server的main函數。 - Binder IPC interface
提供進程間通信的接口,APP和CameraService的通信、CameraService和HAL的通信。其中,AIDL、HIDL都是基於Binder實現的。 - Camera Service
代碼路徑:frameworks/av/services/camera/。同APP、HAL交互的服務,起到了承上啓下的作用。 - HAL
Google的HAL定義了可以讓Camera Service訪問的標準接口。對於供應商而言,必須要實現這些接口。
核心概念: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。