HAL module架构主要分为三个结构体
struct hw_module_t; //硬件抽象模块
struct hw_module_methods_t; //方法
struct hw_device_t; //模块中的设备
hardware/libhardware/include/hardware/hardware.h
1 每一个 hardware 硬件抽象模块必须有一个module结构体,名字是 HAL_MODULE_INFO_SYM,即HMI,这个模块第一个成员变量是 hw_module_t ,
2 hw_module_t 的tag的值必须为 HARDWARE_MODULE_TAG,这个值就是用来标识硬件抽象的结构体
3 id这个属性代表这个module的唯一性
4 methods代表每个硬件抽象模块的方法结构体,hw_module_methods_t
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
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
/** Identifier of module */
const char *id; //模块唯一id
/** Name of this module */
const char *name; //id
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods; //方法的结构体
/** module's dso */
void* dso;
#ifdef __LP64__
uint64_t reserved[32-7];
#else
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
#endif
} hw_module_t;
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);
//id --设备id
//根据id返回设备
} hw_module_methods_t;
hw_device_t 结构体
1 每个硬件需要定义一个 hw_device_t
2 tag为所在硬件模块HARDWARE_DEVICE_TAG,代表是硬件设备结构体
//hardware/libhardware/include/hardware/hardware.h
#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
3 close指针用于关闭设备
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
uint32_t version;
/** reference to the module this device belongs to */
struct hw_module_t* module;
/** padding reserved for future use */
#ifdef __LP64__
uint64_t reserved[12];
#else
uint32_t reserved[12];
#endif
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
struct sensors_poll_device_t {
struct hw_device_t common;
int (*activate)(struct sensors_poll_device_t *dev,
int sensor_handle, int enabled);
int (*setDelay)(struct sensors_poll_device_t *dev,
int sensor_handle, int64_t sampling_period_ns);
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
实现方式
定义结构体
//hardware/libhardware/include/hardware/sensors.h
#define SENSORS_HARDWARE_MODULE_ID "sensors"
struct sensors_module_t {
struct hw_module_t common;
// ...
};
//实现
static struct hw_module_methods_t sensors_module_methods = {
.open = open_sensors
};
struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 1,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "MultiHal Sensor Module",
.author = "Google, Inc",
.methods = &sensors_module_methods,
.dso = NULL,
.reserved = {0},
},
.get_sensors_list = module__get_sensors_list
};
static int open_sensors(const struct hw_module_t* hw_module, const char* name,
struct hw_device_t** hw_device_out) {
// ...
// Create proxy device, to return later.
sensors_poll_context_t *dev = new sensors_poll_context_t();
memset(dev, 0, sizeof(sensors_poll_device_1_t));
dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG;
dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_4;
dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module);
dev->proxy_device.common.close = device__close;
dev->proxy_device.activate = device__activate;
dev->proxy_device.setDelay = device__setDelay;
dev->proxy_device.poll = device__poll;
dev->proxy_device.batch = device__batch;
dev->proxy_device.flush = device__flush;
dev->proxy_device.inject_sensor_data = device__inject_sensor_data;
dev->proxy_device.register_direct_channel = device__register_direct_channel;
dev->proxy_device.config_direct_report = device__config_direct_report;
dev->nextReadIndex = 0;
// ...
return 0;
}
实战
hardware/libhardware/include/hardware/mytest.h
hardware/libhardware/include_all/hardware/mytest.h
#ifndef HARDWARE_MYTEST_H
#define HARDWARE_MYTEST_H
#include <hardware/hardware.h>
__BEGIN_DECLS
#define MYTEST_HARDWARE_MODULE_ID "mytest"
struct mytest_module_t {
struct hw_module_t common;
};
struct mytest_device_t {
struct hw_device_t common;
int (*testAdd)(struct mytest_device_t* dev, int a, int b);
};
__END_DECLS
#endif // HARDWARE_MYTEST_H
hardware/libhardware/modules/mytest/mytest.cpp
#include <malloc.h>
#include <string.h>
#include <hardware/hardware.h>
#include <hardware/mytest.h>
//实现
static int device_close(struct hw_device_t* device) {
mytest_device_t* dev = (mytest_device_t*) device;
delete dev;
return 0;
}
static int device_testAdd(struct mytest_device_t* dev, int a, int b) {
if (dev != NULL) {
}
return a + b * 10;
}
static int open_sensors(const struct hw_module_t* hw_module, const char* name,
struct hw_device_t** hw_device_out) {
if (strcmp(name, "test") != 0) {
//return -EINVAL;
}
// Create proxy device, to return later.
mytest_device_t* dev = new mytest_device_t();
memset(dev, 0, sizeof(mytest_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 1;
dev->common.module = const_cast<hw_module_t*>(hw_module);
dev->common.close = device_close;
// Add your device-specific fields here
dev->testAdd = device_testAdd;
*hw_device_out = &dev->common;
return 0;
}
static struct hw_module_methods_t mytest_module_methods = {
.open = open_sensors
};
struct mytest_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 1,
.id = MYTEST_HARDWARE_MODULE_ID,
.name = "Mytest Sensor Module",
.author = "godv",
.methods = &mytest_module_methods,
.dso = NULL,
.reserved = {0},
},
};
hardware/libhardware/modules/mytest/mytestapp.cpp
#include <string.h>
#include <stdio.h>
#include <hardware/hardware.h>
#include <hardware/mytest.h>
int main(int /* argc */, char** /* argv */)
{
int err;
struct mytest_device_t* device;
struct mytest_module_t* module;
err = hw_get_module(MYTEST_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err != 0) {
printf("hw_get_module() failed (%s)\n", strerror(-err));
return 0;
}
module->common.methods->open(&module->common, "godv", (hw_device_t**)&device);
int result = device->testAdd(device, 3, 4);
printf("testAdd(3, 4) = %d\n", result);
device->common.close(&device->common);
return 0;
}
hardware/libhardware/modules/mytest/Android.bp
package {
default_applicable_licenses: ["hardware_libhardware_license"],
}
cc_library_shared {
name: "mytest.default",
relative_install_path: "hw",
proprietary: true,
srcs: ["mytest.cpp"],
cflags: ["-Wall", "-Werror"],
header_libs: ["libhardware_headers"],
shared_libs: [
"liblog",
],
}
cc_binary {
name: "test-mytest",
srcs: ["mytestapp.cpp"],
cflags: ["-Wall", "-Werror"],
shared_libs: [
"libcutils",
"libhardware",
],
}
hw_get_module 分析
hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
//... 先找 NX563J:/ # getprop | grep ro.hardware
// [ro.hardware]: [qcom]
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
// xxxx.qcom.so
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/*
static const char *variant_keys[] = {
"ro.hardware",
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
*/
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
static int hw_module_exists(char *path, size_t path_len, const char *name,
const char *subname)
{
// ...
/*
#if defined(__LP64__)
#define HAL_LIBRARY_SUBDIR "lib64/hw"
#else
#define HAL_LIBRARY_SUBDIR "lib/hw"
#endif
#define HAL_LIBRARY_PATH1 "/system/" HAL_LIBRARY_SUBDIR
#define HAL_LIBRARY_PATH2 "/vendor/" HAL_LIBRARY_SUBDIR
#define HAL_LIBRARY_PATH3 "/odm/" HAL_LIBRARY_SUBDIR
*/
#else // __ANDROID_APEX__
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH3) && access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH2) && access(path, R_OK) == 0)
return 0;
#ifndef __ANDROID_VNDK__
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (path_in_path(path, HAL_LIBRARY_PATH1) && access(path, R_OK) == 0)
return 0;
#endif
#endif // __ANDROID_APEX__
return -ENOENT;
}
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
//...
#if defined(__ANDROID_RECOVERY__) || !defined(__ANDROID__) || defined(__ANDROID_APEX__)
handle = dlopen(path, RTLD_NOW);
#else
handle = android_load_sphal_library(path, RTLD_NOW);
#endif
}
//...
/* Get the address of the struct hal_module_info.
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
#define HAL_MODULE_INFO_SYM HMI
*/
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;
}
//...
return status;
}
https://blog.csdn.net/we1less/article/details/121129577?spm=1001.2014.3001.5502
801

被折叠的 条评论
为什么被折叠?



