一、Framework部分介绍
Framework部分Camera open流程及其复杂,而且这个部分与isp开发关系不大,只不过如果带着对这部分的疑惑来开发,是没有必要的,对Framework部分的分析也就是大概了解Hal是如何被安卓系统调用的这一过程,可以当作故事听,但介绍到的模块笔者都加了LOG验证过,严谨性还是有一定的保证。
本节的调用流程图:
首先,安卓设备开机后在串口敲入ps|grep camera 后,如果设备启动正常,一定会有这两个进程。
这两个进程,笼统地来说,cameraserver对应的是framework层,
android.hardware.camera.provider@2.4-service对应的是HAL层。
研究camera open 流程也就是研究framework中open顺序以及自顶向下调用到HAL层open的顺序,本文不会具体介绍framework是如何与HAL层进行通信(binder相关,笔者也不懂,权当一个黑盒也无妨,后期再去crack),对framework走读也浅尝辄止(与isp工作相关度不高),把重点发在HAL层的走读上(与isp工作强相关)。
在机器开启时,cameraserver与android.hardware.camera.provider@2.4-service会被系统rc文件启动。我们不深究于cameraserver和android.hardware.camera.provider@2.4-service这两个进程的关系,以及启动顺序,单从代码角度梳理camera启动流程。
首先cameraserver是从main_cameraserver.cpp这个文件中的main函数来启动
其位置:frameworks/av/camera/cameraserver/main_cameraserver.cpp
红框中调用了CameraService中的函数,关注instantiate()(本文所有函数名皆缺省参数),但我们发现CameraService.cpp位置:frameworks/av/services/camera/libcameraservice/CameraService.cpp中并没有instantiate()这个函数的实现,他是来自于其父类BinderService(见下图)中
位置:frameworks/native/libs/binder/include/binder/BinderService.h
而调用instantiate函数其实就是调用publish函数,publish中有两个默认参数,可以直接用缺省参数的方式,即publish()调用,而publish()这个函数会将强指针指向子类CameraService,具体实现不深究,CameraService::instantiate()的意思就是将CameraService发布出去。
在首次被强指针sp指向CameraService之后,会调用CameraService.cpp中的onFirstRef()函数,而onFirstRef()函数会调用同文件中的enumerateProviders()函数
此函数中最重要的便是实例化了一个CameraProviderManager对象并且调用initialize()。
此处转向CameraProviderManager.cpp
位置:frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
在代码中没有CameraProviderManager的构造函数,所以我们关注initialize()函数
关注红框中的addProviderLocked()函数,此函数在同文件中,见下图
可以看到此处调用了tryGetService()函数,此函数在CameraProviderManager.h(同路径)中有定义
实际返回的是一个CameraProvider的类,但是CameraProvider是具体如何通过名字获取,暂时没找到定义,猜测是跟hwservice manager通信,可暂时当做黑盒。
到此CameraService就将CameraProvider联系了起来。
二、HAL INTERFACE流程介绍
往下关注CameraProvider,此处就脱离了Framework层,转到了Hal层的interface部分。此处也是谷歌提供的,本文将HAL INTERFACE和ROCKCHIP的Hal分开介绍。
本节的调用流程图:
那么android.hardware.camera.provider@2.4-service这个进程的入口在service.cpp
目录:hardware/interfaces/camera/provider/2.4/default/service.cpp
由于代码实在太过冗长,此处过程省略一万字,这中间的过程简而言之就是匹配相应版本的CameraProvider并且让上文中Framework找到他。
向下调用,来到了CameraProvider_2_4.cpp,位置:hardware/interfaces/camera/provider/2.4/default/CameraProvider_2_4.cpp
上文中Framework处tryGetService()函数最后会调用下面的HIDL_FETCH_ICameraProvider()函数。
关注红框处,调用HIDL_FETCH_ICameraProvider()函数会调用getProviderImpl()函数,并返回了一个实例LegacyCameraProviderImpl_2_4实例。
因为被实例化,会调用LegacyCameraProviderImpl_2_4.cpp中的LegacyCameraProviderImpl_2_4结构体的构造函数
而构造方法中调用了下方红框中的initialize()函数,其中调用了我们要寻找的hw_get_module()函数,通过此函数我们终于找到了RK写的HAL的hw_module_t结构体。
三、 理解一系列承载HAL的结构体
在hardware/rockchip/camera/Camera3HALModule.cpp目录下,我们可以发现下图的代码,这段代码的意义是:将rk自己写的camera hal模块注册到谷歌的硬件标准结构体中。
我们发现Rockchip将自己写的HAL中很多自己实现的函数以及定义的结构体一层一层的放入了一个camera_module_t结构体中,所以说我们需要清楚camera_module_t是如何定义的,在如下目录中
Hardware/libhardware/include/hardware/camera_common.h的camera_common.h头文件中定义了(源文件中谷歌对每个成员都有详尽的说明,这边考虑篇幅便删去)camera_module_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);
int (*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,
camera_metadata_t **static_metadata);
int (*is_stream_combination_supported)(int camera_id,
const camera_stream_combination_t *streams);
void (*notify_device_state_change)(uint64_t deviceState);
void* reserved[2];
} camera_module_t;
而其定义中包含了一个hw_module_t结构体,与camera open相关的成员只有他,所以我们只关心hw_module_t。
hw_module_t在hardware.h中有定义,
目录:hardware/libhardware/include/hardware/hardware.h
typedef struct hw_module_t {
uint32_t tag;
uint16_t module_api_version;
#define version_major module_api_version
uint16_t hal_api_version;
#define version_minor hal_api_version
const char *id;
const char *name;
const char *author;
struct hw_module_methods_t* methods;
void* dso;
#ifdef __LP64__
uint64_t reserved[32-7];
#else
uint32_t reserved[32-7];
#endif
} hw_module_t;
而其中包含了一个hw_module_methods_t的结构体指针,与camera open相关的成员只有他,所以我们只关心他。
在同文件中有hw_module_methods_t的定义
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
到这我们可以发现这个结构体一层一层赋值了一个open函数,至此我们再看一下ROCKCHIP的HAL定义:
至此CameraProvider通过hw_get_module获得的camera_module_t内便有了一个open camera的函数,
此函数的调用过程从Framework到Hal的interface其实还有一条很长的线,但他与我们开发不相关,我只展示代码调用流程末端调用open函数的地方。
位置:hardware/interfaces/camera/common/1.0/default/CameraModule.cpp
会调用其中的CameraModule中的open函数,而在红框中又会调用CameraProvider GET到的camera_module_t中的open函数,到此,Framework到Hal Interface的open流程便结束,下文会介绍到ROCKCHIP实现的HAL中open流程
四、 ROCKCHIP HAL open camera介绍
这个部分我们需要了解的代码目录结构:
本节调用流程图:
承接上文中的open函数,红框中我们发现其实传入的是同文件中定义的hal_dev_open函数
我们在同文件中找到了此函数
发现其实调用的是同文件中定义的openCameraHardware函数
而openCameraHardware函数调用的是halDev的init函数,而halDev是在上一行实例化的一个Camera3Hal类,此类在Camera3Hal.cpp定义,位置:
Camera3HAL.cpp中的init()函数调用了ICameraHw.cpp中的init()函数(也就是RKISP2CameraHw中的init()函数,RKISP2CameraHw继承于ICameraHw.cpp)
ICamera.cpp:
ICamera.h:
RKISP2CameraHw.h中定义的类 RKISP2CameraHw是继承了ICameraHw.h中的ICameraHw类并且实现了类中的虚函数接口。所以当调用ICameraHw类中原先在ICameraHw.h对应类中的虚函数时其实hi是调用了RKISP2CameraHw.cpp中实现的函数,我们这边只关注init()函数,简单来说就是调用了ICameraHw类中的init()函数其实就是调用了RKISP2CameraHw中的init()函数
而红框中表明调用RISIO2CameraHw的init函数便是调用了mControlUnit(RKISP2ControlUnit
.cpp)中的init函数
RKISP2ControlUnit.cpp中的init()函数调用了mCtrlLoop(RKISP2CtrlLoop.cpp)中的init()函数
RKISP2CtrlLoop.cpp中的init()函数调用了rkisp_control_loop_impl.cpp(属于camera_engine_rkaiq模块)中的rkisp_cl_rkaiq_init()函数,而到此为止,我们边走通了Hal的open流程,下文转到camera_engine_rkaiq模块。