vegetableDog

一、Framework部分介绍

Framework部分Camera open流程及其复杂,而且这个部分与isp开发关系不大,只不过如果带着对这部分的疑惑来开发,是没有必要的,对Framework部分的分析也就是大概了解Hal是如何被安卓系统调用的这一过程,可以当作故事听,但介绍到的模块笔者都加了LOG验证过,严谨性还是有一定的保证。

本节的调用流程图:

 

 

 

首先,安卓设备开机后在串口敲入ps|grep camera 后,如果设备启动正常,一定会有这两个进程。

 

 

 

这两个进程,笼统地来说,cameraserver对应的是framework,

android.hardware.camera.provider@2.4-service对应的是HAL层。

研究camera open 流程也就是研究frameworkopen顺序以及自顶向下调用到HALopen的顺序,本文不会具体介绍framework是如何与HAL层进行通信(binder相关,笔者也不懂,权当一个黑盒也无妨,后期再去crack),对framework走读也浅尝辄止(isp工作相关度不高),把重点发在HAL层的走读上(isp工作强相关)

在机器开启时,cameraserverandroid.hardware.camera.provider@2.4-service会被系统rc文件启动。我们不深究于cameraserverandroid.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 INTERFACEROCKCHIPHal分开介绍。

本节的调用流程图:

 

 

 

那么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

上文中FrameworktryGetService()函数最后会调用下面的HIDL_FETCH_ICameraProvider()函数。

 

 

 

 

关注红框处,调用HIDL_FETCH_ICameraProvider()函数会调用getProviderImpl()函数,并返回了一个实例LegacyCameraProviderImpl_2_4实例。

 

 

 

因为被实例化,会调用LegacyCameraProviderImpl_2_4.cpp中的LegacyCameraProviderImpl_2_4结构体的构造函数

 

 

 

而构造方法中调用了下方红框中的initialize()函数,其中调用了我们要寻找的hw_get_module()函数,通过此函数我们终于找到了RK写的HALhw_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.hcamera_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_thardware.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函数,至此我们再看一下ROCKCHIPHAL定义:

 

 

 

至此CameraProvider通过hw_get_module获得的camera_module_t内便有了一个open camera的函数,

此函数的调用过程从FrameworkHalinterface其实还有一条很长的线,但他与我们开发不相关,我只展示代码调用流程末端调用open函数的地方。

位置:hardware/interfaces/camera/common/1.0/default/CameraModule.cpp

会调用其中的CameraModule中的open函数,而在红框中又会调用CameraProvider GET到的camera_module_t中的open函数,到此,FrameworkHal Interfaceopen流程便结束,下文会介绍到ROCKCHIP实现的HALopen流程

 

 

 

四、 ROCKCHIP HAL open camera介绍

这个部分我们需要了解的代码目录结构:

 

 

 

 

本节调用流程图:

 

 

 

 

 

 

 

 

承接上文中的open函数,红框中我们发现其实传入的是同文件中定义的hal_dev_open函数

 

 

 

 

我们在同文件中找到了此函数

 

 

 

 

 

发现其实调用的是同文件中定义的openCameraHardware函数

 

 

 

openCameraHardware函数调用的是halDevinit函数,而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()函数

 

 

 

而红框中表明调用RISIO2CameraHwinit函数便是调用了mControlUnitRKISP2ControlUnit

.cpp)中的init函数

 

 

 

RKISP2ControlUnit.cpp中的init()函数调用了mCtrlLoop(RKISP2CtrlLoop.cpp)中的init()函数

 

 

 

RKISP2CtrlLoop.cpp中的init()函数调用了rkisp_control_loop_impl.cpp(属于camera_engine_rkaiq模块)中的rkisp_cl_rkaiq_init()函数,而到此为止,我们边走通了Halopen流程,下文转到camera_engine_rkaiq模块。

分类:

技术点:

相关文章:

  • 2021-05-26
  • 2021-10-03
  • 2021-04-20
  • 2021-08-29
  • 2021-12-01
  • 2021-06-16
  • 2022-12-23
  • 2021-09-02
猜你喜欢
  • 2021-07-08
  • 2022-12-23
  • 2021-04-24
  • 2022-12-23
  • 2021-09-20
  • 2023-03-02
  • 2021-05-21
相关资源
相似解决方案