深入理解Camera 硬件抽象層
和你一起終身學(xué)習(xí),這里是程序員Android
經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識(shí)點(diǎn):
一、概覽
二、Camera HIDL 接口
三、Camera Provider 主程序
四、Camera HAL3 接口
一、概覽
始于谷歌的Treble開源項(xiàng)目,基于接口與實(shí)現(xiàn)的分離的設(shè)計(jì)原則,谷歌加入了Camera Provider這一抽象層,該層作為一個(gè)獨(dú)立進(jìn)程存在于整個(gè)系統(tǒng)中,并且通過HIDL這一自定義語言成功地將Camera Hal Module從Camera Service中解耦出來,承擔(dān)起了對(duì)Camera HAL的封裝工作,縱觀整個(gè)Android系統(tǒng),對(duì)于Camera Provider而言,對(duì)上是通過HIDL接口負(fù)責(zé)與Camera Service的跨進(jìn)程通信,對(duì)下通過標(biāo)準(zhǔn)的HAL3接口下發(fā)針對(duì)Camera的實(shí)際操作,這儼然是一個(gè)中央樞紐般的調(diào)配中心的角色,而事實(shí)上正是如此,由此看來,對(duì)Camera Provider的梳理變得尤為重要,接下來就以我個(gè)人理解出發(fā)來簡(jiǎn)單介紹下Camera Provider。
Camera Provider通過提供標(biāo)準(zhǔn)的HIDL接口給Camera Service進(jìn)行調(diào)用,保持與Service的正常通信,其中谷歌將HIDL接口的定義直接暴露給平臺(tái)廠商進(jìn)行自定義實(shí)現(xiàn),其中為了極大地減輕并降低開發(fā)者的工作量和開發(fā)難度,谷歌很好地封裝了其跨進(jìn)程實(shí)現(xiàn)細(xì)節(jié),同樣地,Camera Provider通過標(biāo)準(zhǔn)的HAL3接口,向下控制著具體的Camera HAL Module,而這個(gè)接口依然交由平臺(tái)廠商負(fù)責(zé)去實(shí)現(xiàn),而進(jìn)程內(nèi)部則通過簡(jiǎn)單的函數(shù)調(diào)用,將HIDL接口與HAL3接口完美的銜接起來,由此構(gòu)成了Provider整體架構(gòu)。

image
由圖中可以看出Camera Provider進(jìn)程由兩部分組成,一是運(yùn)行在系統(tǒng)中的主程序通過提供了標(biāo)準(zhǔn)的HIDL接口保持了與Camera Service的跨進(jìn)程通訊,二是為了進(jìn)一步擴(kuò)展其功能,通過dlopen方式加載了一系列So庫,而其中就包括了實(shí)現(xiàn)了Camera HAL3接口的So庫,而HAL3接口主要定義了主要用于實(shí)現(xiàn)圖像控制的功能,其實(shí)現(xiàn)主要交由平臺(tái)廠商或者開發(fā)者來完成,所以Camera HAL3 So庫的實(shí)現(xiàn)各式各樣,在高通平臺(tái)上,這里的實(shí)現(xiàn)就是我們本文重點(diǎn)需要分析的CamX-CHI框架。
在開始梳理CamX-CHI之前,不防先從上到下,以接口為主線簡(jiǎn)單梳理下Camera Provider的各個(gè)部分:
二、Camera HIDL 接口
首先需要明確一個(gè)概念,就是HIDL是一種自定義語言,其核心是接口的定義,而谷歌為了使開發(fā)者將注意力落在接口的定義上而不是機(jī)制的實(shí)現(xiàn)上,主動(dòng)封裝了HIDL機(jī)制的實(shí)現(xiàn)細(xì)節(jié),開發(fā)者只需要通過*.hal文件定義接口,填充接口內(nèi)部實(shí)際的實(shí)現(xiàn)即可,接下來來看下具體定義的幾個(gè)主要接口:

在這里插入圖片描述
因?yàn)镠IDL機(jī)制本身是跨進(jìn)程通訊的,所以Camera Service本身通過HIDL接口獲取的對(duì)象都會(huì)有Bn端和Bp端,分別代表了Binder兩端,接下來為了方便理解,我們都省略掉Bn/Bp說法,直接用具體接口類代表,忽略跨進(jìn)程兩端的區(qū)別。
ICameraProvider.hal源碼如下:
package android.hardware.camera.provider@2.4;
import ICameraProviderCallback;
import android.hardware.camera.common@1.0::types;
import android.hardware.camera.device@1.0::ICameraDevice;
import android.hardware.camera.device@3.2::ICameraDevice;
interface ICameraProvider {
setCallback(ICameraProviderCallback callback) generates (Status status);
getVendorTags() generates (Status status, vec<VendorTagSection> sections);
getCameraIdList() generates (Status status, vec<string> cameraDeviceNames);
isSetTorchModeSupported() generates (Status status, bool support);
getCameraDeviceInterface_V1_x(string cameraDeviceName) generates (Status status, android.hardware.camera.device@1.0::ICameraDevice device);
getCameraDeviceInterface_V3_x(string cameraDeviceName) generates (Status status, android.hardware.camera.device@3.2::ICameraDevice device);
};
該文件中定義了ICameraProvider接口類,由CameraProvider繼承并實(shí)現(xiàn),在Camera Provider啟動(dòng)的時(shí)候被實(shí)例化,主要接口如下:
getCameraDeviceInterface_V3_x: 該方法主要用于Camera Service獲取ICameraDevice,通過該對(duì)象可以控制Camera 設(shè)備的諸如配置數(shù)據(jù)流、下發(fā)request等具體行為。
setCallback:將Camera Service 實(shí)現(xiàn)的ICameraProviderCallback傳入Camera Provider,一旦Provider有事件產(chǎn)生時(shí)便可以通過該對(duì)象通知Camera Service。
ICameraProviderCallback.hal源碼如下:
package android.hardware.camera.provider@2.4;
import android.hardware.camera.common@1.0::types;
interface ICameraProviderCallback {
cameraDeviceStatusChange(string cameraDeviceName, CameraDeviceStatus newStatus);
torchModeStatusChange(string cameraDeviceName, TorchModeStatus newStatus);
};
該文件中定義了ICameraProviderCallback回調(diào)接口類,該接口由Camera Service 中的CameraProviderManager::ProviderInfo繼承并實(shí)現(xiàn),在Camera Service 啟動(dòng)的時(shí)候被實(shí)例化,通過調(diào)用ICameraProvider::setCallback接口注冊(cè)到Camera Provider中,其主要接口如下:
cameraDeviceStatusChange:將Camera 設(shè)備狀態(tài)上傳至Camera Service,狀態(tài)由CameraDeviceStatus定義
ICameraDevice.hal源碼如下:
package android.hardware.camera.device@3.2;
import android.hardware.camera.common@1.0::types;
import ICameraDeviceSession;
import ICameraDeviceCallback;
interface ICameraDevice {
getResourceCost() generates (Status status, CameraResourceCost resourceCost);
getCameraCharacteristics() generates (Status status, CameraMetadata cameraCharacteristics);
setTorchMode(TorchMode mode) generates (Status status);
open(ICameraDeviceCallback callback) generates (Status status, ICameraDeviceSession session);
dumpState(handle fd);
};
該文件中定義了ICameraDevice接口類,由CameraDevice::TrampolineDeviceInterface_3_2實(shí)現(xiàn),其主要接口如下:
open:用于創(chuàng)建一個(gè)Camera設(shè)備,并且將Camera Service中繼承ICameraDeviceCallback并實(shí)現(xiàn)了相應(yīng)接口的Camera3Device作為參數(shù)傳入Provider中,供Provider上傳事件或者圖像數(shù)據(jù)。
getCameraCharacteristics:用于獲取Camera設(shè)備的屬性。
ICameraDeviceCallback.hal源碼如下:
package android.hardware.camera.device@3.2;
import android.hardware.camera.common@1.0::types;
interface ICameraDeviceCallback {
processCaptureResult(vec<CaptureResult> results);
notify(vec<NotifyMsg> msgs);
};
該文件中定義了ICameraDeviceCallback接口類,由Camera Service中的Camera3Device繼承并實(shí)現(xiàn),通過調(diào)用ICameraDevice::open方法注冊(cè)到Provider中,其主要接口如下:
processCaptureResult_3_4: 一旦有圖像數(shù)據(jù)產(chǎn)生會(huì)通過調(diào)用該方法將數(shù)據(jù)以及meta data上傳至Camera Service。
notify: 通過該方法上傳事件至Camera Service中,比如shutter事件等。
ICameraDeviceSession.hal源碼如下:
package android.hardware.camera.device@3.2;
import android.hardware.camera.common@1.0::types;
interface ICameraDeviceSession {
constructDefaultRequestSettings(RequestTemplate type) generates (Status status, CameraMetadata requestTemplate);
configureStreams(StreamConfiguration requestedConfiguration) generates (Status status, HalStreamConfiguration halConfiguration);
processCaptureRequest(vec<CaptureRequest> requests, vec<BufferCache> cachesToRemove) generates (Status status, uint32_t numRequestProcessed);
getCaptureRequestMetadataQueue() generates (fmq_sync<uint8_t> queue);
getCaptureResultMetadataQueue() generates (fmq_sync<uint8_t> queue);
flush() generates (Status status); close();
};
該文件中定義了ICameraDeviceSession接口類,由CameraDeviceSession::TrampolineSessionInterface_3_2繼承并實(shí)現(xiàn),其主要接口如下:
constructDefaultRequestSettings:用于創(chuàng)建默認(rèn)的Request配置項(xiàng)。
configureStreams_3_5:用于配置數(shù)據(jù)流,其中包括了output buffer/Surface/圖像格式大小等屬性。
processCaptureRequest_3_4:下發(fā)request到Provider中,一個(gè)request對(duì)應(yīng)著一次圖像需求。
close: 關(guān)閉當(dāng)前會(huì)話。
三 、Camera Provider 主程序
接下來進(jìn)入到Provider內(nèi)部去看看,整個(gè)進(jìn)程是如何運(yùn)轉(zhuǎn)的,以下圖為例進(jìn)行分析:

在這里插入圖片描述
在系統(tǒng)初始化的時(shí)候,系統(tǒng)會(huì)去運(yùn)行[email protected]_64程序啟動(dòng)Provider進(jìn)程,并加入HW Service Manager中接受統(tǒng)一管理,在該過程中實(shí)例化了一個(gè)LegacyCameraProviderImpl_2_4對(duì)象,并在其構(gòu)造函數(shù)中通過hw_get_module標(biāo)準(zhǔn)方法獲取HAL的camera_module_t結(jié)構(gòu)體,并將其存入CameraModule對(duì)象中,之后通過調(diào)用該camera_modult_t結(jié)構(gòu)體的init方法初始化HAL Module,緊接著調(diào)用其get_number_of_camera方法獲取當(dāng)前HAL支持的Camera數(shù)量,最后通過調(diào)用其set_callbacks方法將LegcyCameraProviderImpl_2_4(LegcyCameraProviderImpl_2_4繼承了camera_modult_callback_t)作為參數(shù)傳入CamX-CHI中,接受來自CamX-CHI中的數(shù)據(jù)以及事件,當(dāng)這一系列動(dòng)作完成了之后,Camera Provider進(jìn)程便一直便存在于系統(tǒng)中,監(jiān)聽著來自Camera Service的調(diào)用。

在這里插入圖片描述
接下來以上圖為例簡(jiǎn)單介紹下Provider中幾個(gè)重要流程:
Camera Service通過調(diào)用ICameraProvider的getCameraDeviceInterface_v3_x接口獲取ICameraDevice,在此過程中,Provider會(huì)去實(shí)例化一個(gè)CameraDevice對(duì)象,并且將之前存有camera_modult_t結(jié)構(gòu)體的CameraModule對(duì)象傳入CameraDevice中,這樣就可以在CameraDevice內(nèi)部通過CameraModule訪問到camera_module_t的相關(guān)資源,然后將CameraDevice內(nèi)部類TrampolineDeviceInterface_3_2(該類繼承并實(shí)現(xiàn)了ICameraDevice接口)返回給Camera Service。
Camera Service通過之前獲取的ICameraDevice,調(diào)用其open方法來打開Camera設(shè)備,接著在Provider中會(huì)去調(diào)用CameraDevice對(duì)象的open方法,在該方法內(nèi)部會(huì)去調(diào)用camera_module_t結(jié)構(gòu)體的open方法,從而獲取到HAL部分的camera3_device_t結(jié)構(gòu)體,緊接著Provider會(huì)實(shí)例化一個(gè)CameraDeviceSession對(duì)象,并且將剛才獲取到的camera3_device_t結(jié)構(gòu)體以參數(shù)的方式傳入CameraDeviceSession中,在CameraDeviceSession的構(gòu)造方法中又會(huì)調(diào)用CameraDeviceSession的initialize方法,在該方法內(nèi)部又會(huì)去調(diào)用camera3_device_t結(jié)構(gòu)體的ops內(nèi)的initialize方法開始HAL部分的初始化工作,最后CameraDeviceSession對(duì)象被作為camera3_callback_ops的實(shí)現(xiàn)傳入HAL,接收來自HAL的數(shù)據(jù)或者具體事件,當(dāng)一切動(dòng)作都完成后,Provider會(huì)將CameraDeviceSession::TrampolineSessionInterface_3_2(該類繼承并實(shí)現(xiàn)了ICameraDeviceSession接口)對(duì)象通過HIDL回調(diào)的方法返回給Camera Service中。
Camera Service通過調(diào)用ICameraDevcieSession的configureStreams_3_5接口進(jìn)行數(shù)據(jù)流的配置,在Provider中,最終會(huì)通過調(diào)用之前獲取的camera3_device_t結(jié)構(gòu)體內(nèi)ops的configure_streams方法下發(fā)到HAL中進(jìn)行處理。
Camera Service通過調(diào)用ICameraDevcieSession的processCaptureRequest_3_4接口下發(fā)request請(qǐng)求到Provider中,在Provider中,最終依然會(huì)通過調(diào)用獲取的camera3_device_t結(jié)構(gòu)體內(nèi)ops中的process_capture_request方法將此次請(qǐng)求下發(fā)到HAL中進(jìn)行處理。
從整個(gè)流程不難看出,這幾個(gè)接口最終對(duì)應(yīng)的是HAL3的接口,并且Provider并沒有經(jīng)過太多復(fù)雜的額外的處理。
四、Camera HAL3 接口
HAL硬件抽象層(Hardware Abstraction Layer),是谷歌開發(fā)的用于屏蔽底層硬件抽象出來的一個(gè)軟件層, 每一個(gè)平臺(tái)廠商可以將不開源的代碼封裝在這一層,僅僅提供二進(jìn)制文件。
該層定義了自己的一套通用標(biāo)準(zhǔn)接口,平臺(tái)廠商務(wù)必按照以下規(guī)則定義自己的Module:
每一個(gè)硬件模塊都通過hw_module_t來描述,具有固定的名字HMI
每一個(gè)硬件模塊都必須實(shí)現(xiàn)hw_module_t里面的open方法,用于打開硬件設(shè)備,并返回對(duì)應(yīng)的操作接口集合
硬件的操作接口集合使用hw_device_t 來描述,并可以通過自定義一個(gè)更大的包含hw_device_t的結(jié)構(gòu)體來拓展硬件操作集合
其中代表硬件模塊的是hw_module_t,對(duì)應(yīng)的設(shè)備是通過hw_device_t來描述,這兩者的定義如下:
hw_module_t/hw_device_t源碼如下:
typedef struct hw_module_t {
uint32_t tag; //HMI
struct hw_module_methods_t* methods;
} hw_module_t;
typedef struct hw_module_methods_t {
int (*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device);
} hw_module_methods_t;
typedef struct hw_device_t {
struct hw_module_t* module;
int (*close)(struct hw_device_t* device);
} hw_device_t;
從上面的定義可以看出,主要是通過hw_module_t 代表了模塊,通過其open方法用來打開一個(gè)設(shè)備,而該設(shè)備是用hw_device_t來表示,其中除了用來關(guān)閉設(shè)備的close方法外,并無其它方法,由此可見谷歌定義的HAL接口,并不能滿足絕大部分HAL模塊的需要,所以谷歌想出了一個(gè)比較好的解決方式,那便是將這兩個(gè)基本結(jié)構(gòu)嵌入到更大的結(jié)構(gòu)體內(nèi)部,同時(shí)在更大的結(jié)構(gòu)內(nèi)部定義了各自模塊特有的方法,用于實(shí)現(xiàn)模塊的功能,這樣,一來對(duì)上保持了HAL的統(tǒng)一規(guī)范,二來也擴(kuò)展了模塊的功能。
基于上面的方式,谷歌便針對(duì)Camera 提出了HAL3接口,其中主要包括了用于代表一系列操作主體的結(jié)構(gòu)體以及具體操作函數(shù),接下來我們分別進(jìn)行詳細(xì)介紹:
1. 核心結(jié)構(gòu)體解析
HAL3中主要定義了camera_module_t/camera3_device_t/camera3_stream_configuration/camera3_stream以及camera3_stream_buffer幾個(gè)主要結(jié)構(gòu)體。
其中camera_module_t以及camera3_device_t代碼定義如下:
typedef struct camera_module {
hw_module_t common;
int (*get_number_of_cameras)(void);
int (*get_camera_info)(int camera_id, struct camera_info *info);
nt (*set_callbacks)(const camera_module_callbacks_t *callbacks);
void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
int (*open_legacy)(const struct hw_module_t* module, const char* id, uint32_t halVersion, struct hw_device_t** device);
int (*set_torch_mode)(const char* camera_id, bool enabled);
int (*init)();
int (*get_physical_camera_info)(int physical_camera_id, int (*is_stream_combination_supported)(int camera_id,const camera_stream_combination_t *streams);
int (*is_stream_combination_supported)(int camera_id, const camera_stream_combination_t *streams);
void (*notify_device_state_change)(uint64_t deviceState);
} camera_module_t;
typedef struct camera3_device {
hw_device_t common;
camera3_device_ops_t *ops; //拓展接口,Camera HAL3定義的標(biāo)準(zhǔn)接口
void *priv;
} camera3_device_t;
由定義不難發(fā)現(xiàn),camera_module_t包含了hw_module_t,主要用于表示Camera模塊,其中定義了諸如get_number_of_cameras以及set_callbacks等擴(kuò)展方法,而camera3_device_t包含了hw_device_t,主要用來表示Camera設(shè)備,其中定義了camera3_device_ops操作方法集合,用來實(shí)現(xiàn)正常獲取圖像數(shù)據(jù)以及控制Camera的功能。
結(jié)構(gòu)體camera3_stream_configuration代碼定義如下:
typedef struct camera3_stream_configuration {
uint32_t num_streams;
camera3_stream_t **streams;
uint32_t operation_mode;
const camera_metadata_t *session_parameters;
} camera3_stream_configuration_t;
該結(jié)構(gòu)體主要用來代表配置的數(shù)據(jù)流列表,內(nèi)部裝有上層需要進(jìn)行配置的數(shù)據(jù)流的指針,內(nèi)部的定義簡(jiǎn)單介紹下:
num_streams: 代表了來自上層的數(shù)據(jù)流的數(shù)量,其中包括了output以及input stream。
streams: 是streams的指針數(shù)組,包括了至少一條output stream以及至多一條input stream。
operation_mode: 當(dāng)前數(shù)據(jù)流的操作模式,該模式在camera3_stream_configuration_mode_t中被定義,HAL通過這個(gè)參數(shù)可以針對(duì)streams做不同的設(shè)置。
session_parameters: 該參數(shù)可以作為缺省參數(shù),直接設(shè)置為NULL即可,CAMERA_DEVICE_API_VERSION_3_5以上的版本才支持。
結(jié)構(gòu)體camera3_stream_t的代碼定義如下:
typedef struct camera3_stream {
int stream_type;
uint32_t width;
uint32_t height;
int format;
uint32_t usage;
uint32_t max_buffers;
void *priv;
android_dataspace_t data_space;
int rotation;
const char* physical_camera_id;
}camera3_stream_t;
該結(jié)構(gòu)體主要用來代表具體的數(shù)據(jù)流實(shí)體,在整個(gè)的配置過程中,需要在上層進(jìn)行填充,當(dāng)下發(fā)到HAL中后,HAL會(huì)針對(duì)其中的各項(xiàng)屬性進(jìn)行配置,這里便簡(jiǎn)單介紹下其內(nèi)部的各個(gè)元素的意義:
stream_type: 表示數(shù)據(jù)流的類型,類型在camera3_stream_type_t中被定義。
width:表示當(dāng)前數(shù)據(jù)流中的buffer的寬度。
height: 表示當(dāng)前數(shù)據(jù)流中buffer的高度。
format: 表示當(dāng)前數(shù)據(jù)流中buffer的格式,該格式是在system/core/include/system/graphics.h中被定義。
usage:表示當(dāng)前數(shù)據(jù)流的gralloc用法,其用法定義在gralloc.h中。
max_buffers:指定了當(dāng)前數(shù)據(jù)流中可能支持的最大數(shù)據(jù)buffer數(shù)量。
data_space: 指定了當(dāng)前數(shù)據(jù)流buffer中存儲(chǔ)的圖像數(shù)據(jù)的顏色空間。
rotation:指定了當(dāng)前數(shù)據(jù)流的輸出buffer的旋轉(zhuǎn)角度,其角度的定義在camera3_stream_rotation_t中,該參數(shù)由Camera Service進(jìn)行設(shè)置,必須在HAL中進(jìn)行設(shè)置,該參數(shù)對(duì)于input stream并沒有效果。
physical_camera_id:指定了當(dāng)前數(shù)據(jù)流從屬的物理camera Id。
結(jié)構(gòu)體camera3_stream_buffer_t定義如下:
typedef struct camera3_stream_buffer {
camera3_stream_t *stream;
buffer_handle_t *buffer
int status;
int acquire_fence;
int release_fence;
} camera3_stream_buffer_t;
該結(jié)構(gòu)體主要用來代表具體的buffer對(duì)象,其中重要元素如下:
stream: 代表了從屬的數(shù)據(jù)流
buffer:buffer句柄
2. 核心接口函數(shù)解析
HAL3的核心接口都是在camera3_device_ops中被定義,代碼定義如下:
typedef struct camera3_device_ops {
int (*initialize)(const struct camera3_device *, const camera3_callback_ops_t *callback_ops);
int (*configure_streams)(const struct camera3_device *, camera3_stream_configuration_t *stream_list);
int (*register_stream_buffers)(const struct camera3_device *,const camera3_stream_buffer_set_t *buffer_set);
const camera_metadata_t* (*construct_default_request_settings)(const struct camera3_device *, int type);
int (*process_capture_request)(const struct camera3_device *, camera3_capture_request_t *request);
void (*get_metadata_vendor_tag_ops)(const struct camera3_device*, vendor_tag_query_ops_t* ops);
void (*dump)(const struct camera3_device *, int fd);
int (*flush)(const struct camera3_device *);
void (*signal_stream_flush)(const struct camera3_device*, uint32_t num_streams, const camera3_stream_t* const* streams);
int (*is_reconfiguration_required)(const struct camera3_device*, const camera_metadata_t* old_session_params, const camera_metadata_t* new_session_params);
} camera3_device_ops_t;
從代碼中可以看見,該結(jié)構(gòu)體定義了一系列的函數(shù)指針,用來指向平臺(tái)廠商實(shí)際的實(shí)現(xiàn)方法,接下來就其中幾個(gè)方法簡(jiǎn)單介紹下:
a) initialize
該方法必須在camera_module_t中的open方法之后,其它c(diǎn)amera3_device_ops中方法之前被調(diào)用,主要用來將上層實(shí)現(xiàn)的回調(diào)方法注冊(cè)到HAL中,并且根據(jù)需要在該方法中加入自定義的一些初始化操作,另外,谷歌針對(duì)該方法在性能方面也有嚴(yán)格的限制,該方法需要在5ms內(nèi)返回,最長(zhǎng)不能超過10ms。
b) configure_streams
該方法在完成initialize方法之后,在調(diào)用process_capture_request方法之前被調(diào)用,主要用于重設(shè)當(dāng)前正在運(yùn)行的Pipeline以及設(shè)置新的輸入輸出流,其中它會(huì)將stream_list中的新的數(shù)據(jù)流替換之前配置的數(shù)據(jù)流。在調(diào)用該方法之前必須確保沒有新的request下發(fā)并且當(dāng)前request的動(dòng)作已經(jīng)完成,否則會(huì)引起無法預(yù)測(cè)的錯(cuò)誤。一旦HAL調(diào)用了該方法,則必須在內(nèi)部配置好滿足當(dāng)前數(shù)據(jù)流配置的幀率,確保這個(gè)流程的運(yùn)行的順暢性。
其中包含了兩個(gè)參數(shù),分別是camera3_device以及stream_list(camera3_stream_configuration_t ),其中第二個(gè)參數(shù)是上層傳入的數(shù)據(jù)流配置列表,該列表中必須包含至少一個(gè)output stream,同時(shí)至多包含一個(gè)input stream。
另外,谷歌針對(duì)該方法有著嚴(yán)格的性能要求,平臺(tái)廠商在實(shí)現(xiàn)該方法的時(shí)候,需要在500ms內(nèi)返回,最長(zhǎng)不能超過1000ms。
c) construct_default_request_settings
該方法主要用于構(gòu)建一系列默認(rèn)的Camera Usecase的capture 設(shè)置項(xiàng),通過camera_metadata_t來進(jìn)行描述,其中返回值是一個(gè)camera_metadata_t指針,其指向的內(nèi)存地址是由HAL來進(jìn)行維護(hù)的,同樣地,該方法需要在1ms內(nèi)返回,最長(zhǎng)不能超過5ms。
d) process_capture_request
該方法用于下發(fā)單次新的capture request到HAL中, 上層必須保證該方法的調(diào)用都是在一個(gè)線程中完成,而且該方法是異步的,同時(shí)其結(jié)果并不是通過返回值給到上層,而是通過HAL調(diào)用另一個(gè)接口process_capture_result()來將結(jié)果返回給上層的,在使用的過程中,通過in-flight機(jī)制,保證短時(shí)間內(nèi)下發(fā)足夠多的request,從而滿足幀率要求。
該方法的性能依然受到谷歌的嚴(yán)格要求,規(guī)定其需要在一幀圖像處理完的時(shí)長(zhǎng)內(nèi)返回,最長(zhǎng)不超過4幀圖像處理完成的時(shí)長(zhǎng),比如當(dāng)前預(yù)覽幀率是30幀,則該方法的操作耗時(shí)最長(zhǎng)不能超過120ms,否則便會(huì)引起明顯的幀抖動(dòng),從而影響用戶體驗(yàn)。
e) dump
該方法用于打印當(dāng)前Camera設(shè)備的狀態(tài),一般是由上層通過dumpsys工具輸出debug dump信息或者主動(dòng)抓取bugreport的時(shí)候被調(diào)用,該方法必須是非阻塞實(shí)現(xiàn),同時(shí)需要保證在1ms內(nèi)返回,最長(zhǎng)不能超過10ms。
f) flush
當(dāng)上層需要執(zhí)行新的configure_streams的時(shí)候,需要調(diào)用該方法去盡可能快地清除掉當(dāng)前已經(jīng)在處理中的或者即將處理的任務(wù),為配置數(shù)據(jù)流提供一個(gè)相對(duì)穩(wěn)定的環(huán)境,其具體工作如下:
所有的還在流轉(zhuǎn)的request會(huì)盡可能快的返回
并未開始進(jìn)行流轉(zhuǎn)的request會(huì)直接返回,并攜帶錯(cuò)誤信息
任何可以打斷的硬件操作會(huì)立即被停止
任何無法進(jìn)行打斷的硬件操作會(huì)在當(dāng)前狀態(tài)下進(jìn)行休眠
flush會(huì)在所有的buffer都得以釋放,所有request都成功返回后才真正返回,該方法需要在100ms內(nèi)返回,最長(zhǎng)不能超過1000ms。
上面的一系列方法是上層直接對(duì)下控制Camera Hal,而一旦Camera Hal產(chǎn)生了數(shù)據(jù)或者事件的時(shí)候,可以通過camera3_callback_ops中定義的回調(diào)方法將數(shù)據(jù)或者事件返回至上層,該結(jié)構(gòu)體定義如下:
typedef struct camera3_callback_ops {
void (*process_capture_result)(const struct camera3_callback_ops *, const camera3_capture_result_t *result);
void (*notify)(const struct camera3_callback_ops *, const camera3_notify_msg_t *msg);
camera3_buffer_request_status_t (*request_stream_buffers)(
const struct camera3_callback_ops *,
uint32_t num_buffer_reqs,
const camera3_buffer_request_t *buffer_reqs,
/*out*/uint32_t *num_returned_buf_reqs,
/*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
void (*return_stream_buffers)( const struct camera3_callback_ops *, uint32_t num_buffers, const camera3_stream_buffer_t* const* buffers);
} camera3_callback_ops_t;
其中常用的回調(diào)方法主要有兩個(gè):用于返回?cái)?shù)據(jù)的process_capture_result以及用于返回事件的notify,接下來分別介紹下:
a) process_capture_result
該方法用于返回HAL部分產(chǎn)生的metadata和image buffers,它與request是多對(duì)一的關(guān)系,同一個(gè)request,可能會(huì)對(duì)應(yīng)到多個(gè)result,比如可以通過調(diào)用一次該方法用于返回metadata以及低分辨率的圖像數(shù)據(jù),再調(diào)用一次該方法用于返回jpeg格式的拍照數(shù)據(jù),而這兩次調(diào)用時(shí)對(duì)應(yīng)于同一個(gè)process_capture_request動(dòng)作。
同一個(gè)Request的Metadata以及Image Buffers的先后順序無關(guān)緊要,但是同一個(gè)數(shù)據(jù)流的不同Request之間的Result必須嚴(yán)格按照Request的下發(fā)先后順序進(jìn)行依次返回的,如若不然,會(huì)導(dǎo)致圖像數(shù)據(jù)顯示出現(xiàn)順序錯(cuò)亂的情況。
該方法是非阻塞的,而且并且必須要在5ms內(nèi)返回。
b) notify
該方法用于異步返回HAL事件到上層,必須非阻塞實(shí)現(xiàn),而且要在5ms內(nèi)返回。
谷歌為了將系統(tǒng)框架和平臺(tái)廠商的自定義部分相分離,在Android上推出了Treble項(xiàng)目,該項(xiàng)目直接將平臺(tái)廠商的實(shí)現(xiàn)部分放入vendor分區(qū)中進(jìn)行管理,進(jìn)而與system分區(qū)保持隔離,這樣便可以在相互獨(dú)立的空間中進(jìn)行各自的迭代升級(jí),而互不干擾,而在相機(jī)框架體系中,便將Camera HAL Module從Camera Service中解耦出來,放入獨(dú)立進(jìn)程Camera Provider中進(jìn)行管理,而為了更好的進(jìn)行跨進(jìn)程訪問,谷歌針對(duì)Provider提出了HIDL機(jī)制用于Camera Servic對(duì)于Camera Provier的訪問,而HIDL接口的實(shí)現(xiàn)是在Camera Provider中實(shí)現(xiàn),針對(duì)Camera HAL Module的控制又是通過谷歌制定的Camera HAL3接口來完成,所以由此看來,Provider的職責(zé)也比較簡(jiǎn)單,通過HIDL機(jī)制保持與Camera Service的通信,通過HAL3接口控制著Camera HAL Module。
原文鏈接:https://blog.csdn.net/u012596975/article/details/107137523
相關(guān)文章友情推薦
1. Android開發(fā)干貨分享
至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡(luò)的文章,小編覺得很優(yōu)秀,歡迎點(diǎn)擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請(qǐng)聯(lián)系小編刪除,歡迎您的建議與指正。同時(shí)期待您的關(guān)注,感謝您的閱讀,謝謝!
點(diǎn)個(gè)在看,方便您使用時(shí)快速查看!
