好记性不如烂笔头
看过很多遍,记忆力不行,能理解记不住
还是要以树的形式写一遍,感觉树形比较好记忆。
本文流程:
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;
}
概述不清了,有点乱,后面再梳理下