Android HAL层库加载原理

Android HAL层的由来:由于市面做移动芯片的厂商很多,大部分厂商考虑到自己硬件的设计架构、安全、专利等方面原因,不愿意公开自己的这方面代码,也出于不同厂商硬件架构不太一样,适配开发难度周期长,GOOGLE在kernel之上加了一个HAL层,只要各个厂商实现Android 所需要的功能接口,可以以库的方式提供不用开源。

问题来了,android如何实现针对不同的Hardware Module进行通用性调用的呢?

以加载camera HAL层库为例:

#define CAMERA_HARDWARE_NODULE_ID "camera"

首先在 void CameraService::onFirstRef()

{

............略..............

  camera_module_t *rawModule;

    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&rawModule);

............略..............

}

通过hw_get_module()函数以CAMERA_HARDWARE_MODULE_ID 参数获得 camera_module_t 指针来初始化和调用CMAERA 我们再看hw_get_module()的实现:

int hw_get_module(const char *id, const struct hw_module_t **module)

{

    return hw_get_module_by_class(id, NULL, module);

}

而hw_get_module()又是通过 hw_get_module_by_class():

int hw_get_module_by_class(const char *class_id, const char *inst,

                          const struct hw_module_t **module)

{

.................核心看......................

return load(class_id, path, module);

}

static int load(const char *id,const char *path,const struct hw_module_t **pHmi)

{

..........................................................................................

    handle = dlopen(path, RTLD_NOW);

    if (handle == NULL) {

        char const *err_str = dlerror();

        ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

        status = -EINVAL;

        goto done;

    }

    /* Get the address of the struct hal_module_info. */

    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

    hmi = (struct hw_module_t *)dlsym(handle, sym);

    if (hmi == NULL) {

        ALOGE("load: couldn't find symbol %s", sym);

        status = -EINVAL;

        goto done;

    }

    /* Check that the id matches */

    if (strcmp(id, hmi->id) != 0) {

        ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);

        status = -EINVAL;

        goto done;

    }

.................................................................................

}

有load函数可发现,它是通过dlopen()加载camera.so库,通过dlsym()查询HAL_MODULE_INFO_SYM_AS_STR全局变量的地址,通过强制指针转换可以获得HAL_MODULE_INFO_SYM_AS_STR变量,并检查传进来的id和获得id是否一致。HAL_MODULE_INFO_SYM_AS_STR是个宏定义如下:

              #define HAL_MODULE_INFO_SYM_AS_STR "HMI"

也就是说camera.so库中肯定有一个名字为HMI 数据类型为struct hw_module_t的全局变量。

我们通过linux自带的readelf工具查看camera.so的符号表:

JEFF$  readelf -s camera.msm8937.so

Symbol table '.dynsym' contains 336 entries:

  Num:    Value  Size Type    Bind  Vis      Ndx Name

    0: 00000000    0 NOTYPE  LOCAL  DEFAULT  UND

    1: 00000000    0 FUNC    GLOBAL DEFAULT  UND __cxa_finalize@LIBC (2)

    2: 00000000    0 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@LIBC (2)

    3: 00000000    0 FUNC    GLOBAL DEFAULT  UND __register_atfork@LIBC (2)

    4: 00000000    0 FUNC    GLOBAL DEFAULT  UND __aeabi_memcpy8@LIBC_N (3)

    5: 00000000    0 FUNC    GLOBAL DEFAULT  UND __android_log_print

    6: 00000000    0 FUNC    GLOBAL DEFAULT  UND __gnu_Unwind_Find_exidx@LIBC_N (3)

    7: 00000000    0 FUNC    GLOBAL DEFAULT  UND dladdr@LIBC (4)

    ..................................................................................................................................

  187: 000112c7    16 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  188: 00010eaa    17 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  189: 00006a25    28 FUNC    GLOBAL DEFAULT  13 start_recording

  190: 00012af8    44 OBJECT  WEAK  DEFAULT  18 _ZTVN7android12SortedVect

  191: 0001134b    13 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  192: 00006ab1    28 FUNC    GLOBAL DEFAULT  13 cancel_auto_focus

  193: 0001120d    10 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  194: 00013158  176 OBJECT  GLOBAL DEFAULT  23 HMI

  195: 00006901    40 FUNC    GLOBAL DEFAULT  13 get_camera_info

  196: 00010e9a    16 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  197: 0001114c    7 OBJECT  GLOBAL DEFAULT  15 _ZN7android21SunmiCameraP

  198: 0000af79    20 FUNC    GLOBAL DEFAULT  13 _Z11mjpegDecodeiiPciS_i

  199: 00006b05    28 FUNC    GLOBAL DEFAULT  13 set_parameters

  200: 0000791d    40 FUNC    WEAK  DEFAULT  13 _ZNK7android12SortedVecto

  201: 0001109b    9 OBJEC

............................................................................................................................

可以看出来确实存在一个全局类型为OBJECT 名字为HMI的变量

那这个变量谁定义的呢?

我们看到hardware/qcom/camera/qcamera2/QCamera2Hal.cpp有这样的定义:

static hw_module_t camera_common = {

    .tag                    = HARDWARE_MODULE_TAG,

    .module_api_version    = CAMERA_MODULE_API_VERSION_2_4,

    .hal_api_version        = HARDWARE_HAL_API_VERSION,

    .id                    = CAMERA_HARDWARE_MODULE_ID,

    .name                  = "QCamera Module",

    .author                = "Qualcomm Innovation Center Inc",

    .methods                = &qcamera::QCamera2Factory::mModuleMethods,

    .dso                    = NULL,

    .reserved              = {0}

};

camera_module_t HAL_MODULE_INFO_SYM = {

    .common                = camera_common,

    .get_number_of_cameras  = qcamera::QCamera2Factory::get_number_of_cameras,

    .get_camera_info        = qcamera::QCamera2Factory::get_camera_info,

    .set_callbacks          = qcamera::QCamera2Factory::set_callbacks,

    .get_vendor_tag_ops    = qcamera::QCamera3VendorTags::get_vendor_tag_ops,

    .open_legacy            = qcamera::QCamera2Factory::open_legacy,

    .set_torch_mode        = qcamera::QCamera2Factory::set_torch_mode,

    .init                  = NULL,

    .reserved              = {0}

};

可以看到有一个static hw_module_t camera_common变量的定义,就是我们通过dlsym()要获取的变量类型,但是这个变量也不叫 HMI 啊,我们再看这变量是被camera_module_t HAL_MODULE_INFO_SYM使用的,我们来看这个结构体定义:

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)();

    void* reserved[5];

} camera_module_t;

可以看出来 hw_module_t 是这个结构体的第一个变量,这样定义有个好处,可以实现类似C++的继承效果,camera_module继承于hw_module_t,可以通过hw_module_t控制camera_module,所以外面理论上应该通过HAL_MODULE_INFO_SYM 获得hw_module_t的,全局搜索HAL_MODULE_INFO_SYM 发现所有的HAL层模块都会有一个HAL_MODULE_INFO_SYM的定义,还发现HAL_MODULE_INFO_SYM其实是个宏定义:

#define HAL_MODULE_INFO_SYM      HMI

也就是说

camera_module_t HAL_MODULE_INFO_SYM = {

编译解释为:

camera_module_t HMI = {

这样整个HAL层调用通用性就解释的通了。



作者:JEFF_张
链接:https://www.jianshu.com/p/b426fe563380
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更多相关文章

  1. Android中RatingBar的自定义效果
  2. 自定义PopupWindow的实现
  3. 一起Talk Android吧(第一百四十七回:Android自定义View之Layout四)
  4. Android进阶自定义控件之滑动开关
  5. Android中自定义SeekBar的背景颜色,进度条颜色,以及滑块的图片
  6. android之控件自定义(seekBar)
  7. 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

随机推荐

  1. 【Android】debug 状态下其签名文件 debu
  2. Android控件抖动效果
  3. Android热修复框架AndFix核心代码分析并
  4. 【安卓】关于 Android(安卓)默认字体以及
  5. Andriod ADB Interface驱动安装失败Confi
  6. Android的消息机制
  7. 绿色守护简单使用教程
  8. Android(安卓)IPC(进程间通信)
  9. android 实现欢迎界面
  10. Android(安卓)10、11 存储完全适配(上)