【Android系统】hardware.c Android硬件抽象层的代码结构

好记性不如烂笔头

看过很多遍,记忆力不行,能理解记不住

还是要以树的形式写一遍,感觉树形比较好记忆。
本文流程:
        1.hardware.h 和 hardware.c的文件内容。             (三个结构体 + 四个函数)
        2.代码流程与简单注释
        3.实际中jni找到so,并打开的调用传参流程
hardware/libhardware/include/hardware/hardware.h
------------------------------------------------
文件内容,3个结构体

|---------- struct hw_module_t
|
|---------- struct hw_module_methods_t
|
|---------- struct hw_device_t



1. struct hw_module_t 里面有一个struct hw_module_methods* methods指针成员

2. struct hw_module_methods_t 里面只有一个 

                int(*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device)函数指针

3. struct hw_device_t里面有一个struct hw_module_t* module指针成员 和 int(*close)(struct hw_device_t* device)函数指针


hardware/libhardware/hardware.c
----------------------------------
文件内容, 4个函数
  
|------ load(const char* id, const char *path, const struct hw_module_t **pHmi)
|
|------ hw_module_exists(char* path, size_t path_len, const char *name, const char *subname)
|
|------ hw_get_module_by_class(const char *class_id, const char *inst, const char hw_module_t **module)        //inst指针未使用,暂无意义
|
|------ hw_get_module(const char *id, const struct hw_module_t **module)

-------------------
面对过程的代码流程:
        
hw_get_module
    |
hw_get_module_by_class
    |
    |---- 1.检查so在系统文件目录中的位置, 用hw_module_exists判断是否找到so
    |---- 2.用load()函数加载module

-----------------------------------------------
简单注释:
        
hw_get_module()
    ---> hw_module_by_class(id, null, module)
            //这个里面主要是检查system和vendor的lib64/hw目录下是否有so文件
            //如果有so文件就调用load

           //参数是模块ID,system/lib64/hw/name.subname.so, struct hw_module_t**pHmi
          --->load(class_id, path, module);
        
 //load里面,先用dlopen打开so返回一个句柄,再把句柄传给dlsym返回符号地址pmi,
//最后让通过*pHmi = pmi传出去
实际调用:
------------
framework/base/service/core/jni/*******.cpp
------------


JNIEXPORT jint JNICALL ***open(JNIENV *env, jclass cls)
{
    hw_module_t *hw_module = NULL;
    hw_device_t *hw_device = NULL;

    err = hw_get_module(HARDWARE_MODULE_ID, &hw_module);        //传入指针的地址

    /* 这里实际判断的是load函数返回0
     * 也就是:
     *      1.找到so
     *      2.load成功执行
     *    
     * 结果是:
     *      handle = dlopen(so_path_in_system, RTLD_NOW);            //在dlopen()返回之前,将解析共享对象中的所有未定义符号。如果无法执行此操作,则会返回错误。(undefine symbol:错误)
     *      const char *sym = HAL_MODEULE_INFO_SYM_AS_STR = "HMI";
     *      hw_module = *pHmi = hmi = (struct hw_module_t*)dlsym(handle, sym)
     */
    if (err == 0) 
    {
            /**
             *    这个open就到自己写的hal.c里面的open函数了,然后就是是open设备驱动文件
             *    返回fd句柄。该文件提供的其他接口,使用fd作为参数通过ioctl调用驱动提供的函数机制
            **/
            err = module->methods->open(module, NULL, *device);
    }
}
    
----------------------
2021.04.27更新

下面再理解下 framework/.../jni 里面代码 


framwork/base/services/core/jni/com_android_service_ChaoService.cpp


这个里面实现能力是:

          framework里面使用hardware里面自定义的结构,如struct gpio_device_t *device;

    通过device指针,使用framework jni里面的接口名称,能够调用对应底层驱动里的函数。

------------
结构地址的对接

struct gpio_device_t {
	struct hw_device_t common;
				|
				|-------typedef struct hw_device_t {
					
							uint32_t tag;												//HARDWARE_DEVICE_TAG
							uint32_t version;
							struct hw_module_t *module;
										|
										|----- typedef struct hw_module_t {
											
													uint32_t tag;						//HARDWARE_DEVICE_TAG
													uint16_t module_api_version;
													uint16_t hal_api_version;
													const char *id;
													const char *name;
													const char *author;
													struct hw_module_methods_t *methods;
																|
																|----- int (*open)(const struct hw_module_t* module, const char * id, struct hw_device_t **device);
												}hw_module_t;
										
							int (*close)(struct hw_device_t* device);
							
						}hw_device_t;
	
	void (*gpio_open)(struct gpio_device_t *);
	void (*gpio_close)(struct gpio_device_t *);
	void (*device_setGpioHigh)(struct gpio_device_t *, int id);
	void (*device_setGpioLow)(struct gpio_device_t *, int id);
	void (*device_doSomeMagic)(struct gpio_device_t *, int id);
}

framwork/base/services/core/jni/com_android_service_ChaoService.cpp
-------------------------------------------------------------------

#include <hardware/hardware.h>
#inlude <hardware/hao_hal.h>

struct gpio_device_t *gpio_device;     //framework jni里面可以使用hardware里自定义hal里的结构体

JNIEXPORT jint JNICALL AAAAAA_Open(JNIEnv *env, jclass cls)
{
    hw_module_t *module;
    hw_device_t *device;

    err = hw_get_module("chao_hal", (hw_module_t const **)&module );     //framework jni 层通过ID,找到so,module指针是用于传出到上层用于调用,传到底层是用于地址挂钩连起来 

    //....

    /*
     * hw_module_t结构体里的hw_module_methods结构体的open函数
     *
     * 这个open函数定义在自定义hal.c里面
     */
    err = module->methods->open(module, NULL, &device)
    
    //...
}

----------------
自定义hal.c, hardware/libhardware/modules/chaohal.c

static int gpio_device_open(const struct hw_module_t *module, const char *id __unused, struct hw_device_t **device)
{
    /* common 是自定义hal头文件里面的自定义结构体里的 hw_device_t类型
     *
     * hw_device_t结构里面有一个hw_module_t*
     *
     */
    gpio_dev.common.module = (hw_module_t*)module;
    *device = (hw_device_t *)&gpio_dev;
    return 0;
}




概述不清了,有点乱,后面再梳理下

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值