其实挺久之前就了解过HAL的相关内容,只是好久没看有点遗忘,现在刚好写个博客重新学习下。
三个重要的结构体
1 2 3 |
struct hw_module_t; struct hw_module_methods_t; struct hw_device_t; |
下面一个一个结构体来看:
hw_module_t结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * 每个硬件模块都必须要有一个名为HAL_MODULE_INFO_SYM的结构体 * 并且该结构体必须以hw_module_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 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 /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7]; #endif } hw_module_t; |
hw_module_t结构体的内容如上面,该结构体内带有一个hw_module_methods_t结构体,hw_module_methods_t结构体的内容下面再列出,其次就是hw_module_t结构体主要注意最前面的注释就好,其他没什么好说的。
hw_module_methods_t结构体
1 2 3 4 5 6 |
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的方法指针,如上面的内容所示,该结构体的内容被包含在hw_module_t结构体中。所以,获得了特定设备的hw_module_t结构体内容,就可以通过open函数指针来回调device的open方法了。
hw_device_t结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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; |
hw_device_t结构体内含有一个close函数指针。在设备卸载的时候会调用到。
这三个结构体的内容就这些,下面拿个实际的例子来看看。代码在AOSP源码的hardware/libhardware/include/hardware/fingerprint.h
文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
typedef struct <font color='red'>fingerprint_module</font> { /** * Common methods of the fingerprint module. This *must* be the first member * of fingerprint_module as users of this structure will cast a hw_module_t * to fingerprint_module pointer in contexts where it's known * the hw_module_t references a fingerprint_module. */ struct hw_module_t common; } fingerprint_module_t; typedef struct <font color='red'>fingerprint_device</font> { /** * Common methods of the fingerprint device. This *must* be the first member * of fingerprint_device as users of this structure will cast a hw_device_t * to fingerprint_device pointer in contexts where it's known * the hw_device_t references a fingerprint_device. */ struct hw_device_t common; fingerprint_notify_t notify; int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify); uint64_t (*pre_enroll)(struct fingerprint_device *dev); int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat, uint32_t gid, uint32_t timeout_sec); int (*post_enroll)(struct fingerprint_device *dev); uint64_t (*get_authenticator_id)(struct fingerprint_device *dev); int (*cancel)(struct fingerprint_device *dev); int (*enumerate)(struct fingerprint_device *dev); int (*remove)(struct fingerprint_device *dev, uint32_t gid, uint32_t fid); int (*set_active_group)(struct fingerprint_device *dev, uint32_t gid, const char *store_path); int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid); void *reserved[4]; } fingerprint_device_t; |
上面的代码中定义了两个和fingerprint相关的结构体。首先是fingerprint_module_t结构体,里面只包含一个hw_module_t结构体,看源码注释可以知道如果自己定义一个hardware module的话,必须将hw_module_t作为自定义结构体的第一个字段,主要是为了方便在代码中做hw_module_t结构体和自定义结构体之间进行转化,下面会在代码中进行讲解。
另一个结构体就是fingerprint_device_t结构体了,这个结构体的要求和hw_module_t的要求类似,也是要将hw_device_t结构体作为第一个字段,然后可以在自定义的device结构体后添加一些设备的操作函数指针。
所以,要添加自己的Hardware module就简单很多了,自定义两个结构体,一个xxx_module_t结构体,该结构体的第一个字段为hw_module_t结构体,另一个xxx_device_t结构体,该结构体的第一个字段为hw_devict_t结构体即可。
hardware module的加载过程
上面了解了基本的结构体后,接下来看看hardware module的加载过程。
源码在AOSP的hardware/libhardware/hardware.c
文件下,获取hardware module以hw_get_module函数作为入口,例如获取fingerprint时,就是在hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
文件下调用的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
...... fingerprint_device_t* BiometricsFingerprint::openHal() { int err; const hw_module_t *hw_mdl = nullptr; ALOGD("Opening fingerprint hal library..."); // 调用hw_get_module获取到hardware的hw_module_t内容 // 其中 FINGERPRINT_HARDWARE_MODULE_ID被define为"fingerprint" if (0 != (err = <font color='red'>hw_get_module</font>(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) { ALOGE("Can't open fingerprint HW Module, error: %d", err); return nullptr; } ...... // id字符串"fingerprint"的首地址 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_by_class函数,下面看看hw_get_module_by_class函数的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
#if defined(__LP64__) #define HAL_LIBRARY_PATH1 "/system/lib64/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib64/hw" #define HAL_LIBRARY_PATH3 "/odm/lib64/hw" #else #define HAL_LIBRARY_PATH1 "/system/lib/hw" #define HAL_LIBRARY_PATH2 "/vendor/lib/hw" #define HAL_LIBRARY_PATH3 "/odm/lib/hw" #endif static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" }; // class_id="fingerprint", inst = NULL int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module) { int i = 0; char prop[PATH_MAX] = {0}; char path[PATH_MAX] = {0}; char name[PATH_MAX] = {0}; char prop_name[PATH_MAX] = {0}; // 这里inst为NULL,所以name=class_id="fingerprint" if (inst) snprintf(name, PATH_MAX, "%s.%s", class_id, inst); else strlcpy(name, class_id, PATH_MAX); // 这里开始查找对应module的so库,主要是到系统默认的路径下面查找,默认路径已在上面列出 snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name); // 查询是否有ro.hardware.fingerprint这个属性 if (property_get(prop_name, prop, NULL) > 0) { // 结合hw_module_exit的代码,在上面列出的路径下检查是否存在fingerprint.$(prop)的这个文件 if (hw_module_exists(path, sizeof(path), name, prop) == 0) { goto found; } } // 检查是否存在variant_keys对应的属性,获取属性值,然后从默认路径下检查对应文件是否存在 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. */ // 最后找到对应so库的话,就将其load到系统中 return load(class_id, path, module); } static int hw_module_exists(char *path, size_t path_len, const char *name, const char *subname) { snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH3, name, subname); if (access(path, R_OK) == 0) return 0; snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, subname); if (access(path, R_OK) == 0) return 0; snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, subname); if (access(path, R_OK) == 0) return 0; return -ENOENT; } static int load(const char *id, const char *path, const struct hw_module_t **pHmi) { int status = -EINVAL; void *handle = NULL; struct hw_module_t *hmi = NULL; if (strncmp(path, "/system/", 8) == 0) { /* If the library is in system partition, no need to check * sphal namespace. Open it with dlopen. */ handle = dlopen(path, RTLD_NOW); } else { handle = android_load_sphal_library(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; } hmi->dso = handle; /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status; } |
这样HAL层的so库就被加载到系统中了。接下来说明一下为什么需要将hw_device_t和hw_module_t作为自定义结构体的第一个字段。
我们以BiometricsFingerprint作为实例看看
BiometricsFingerprint::openHal简单分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
fingerprint_device_t* BiometricsFingerprint::openHal() { int err; const hw_module_t *hw_mdl = nullptr; ALOGD("Opening fingerprint hal library..."); // 调用hw_get_module方法,获取hardware module保存到hw_mdl中 if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) { ALOGE("Can't open fingerprint HW Module, error: %d", err); return nullptr; } if (hw_mdl == nullptr) { ALOGE("No valid fingerprint module"); return nullptr; } // 通过reinterpret_cast将hw_module_t类型的hw_mdl强制转换为fingerprint_module_t类型 fingerprint_module_t const *module = reinterpret_cast<const fingerprint_module_t*>(hw_mdl); if (module->common.methods->open == nullptr) { ALOGE("No valid open method"); return nullptr; } hw_device_t *device = nullptr; // 调用module里面的open函数,获取到对应的hw_device_t if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) { ALOGE("Can't open fingerprint methods, error: %d", err); return nullptr; } if (kVersion != device->version) { // enforce version on new devices because of [email protected] translation layer ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); return nullptr; } // 通过reinterpret_cast将hw_device_t类型的fp_device强制转换为fingerprint_device_t类型 fingerprint_device_t* fp_device = reinterpret_cast<fingerprint_device_t*>(device); // 设置Fingerprint的notify函数 if (0 != (err = fp_device->set_notify(fp_device, BiometricsFingerprint::notify))) { ALOGE("Can't register fingerprint module callback, error: %d", err); return nullptr; } return fp_device; } |
所以从这里可以知道为什么在自定义硬件设备的module结构体和device结构体时需要将第一个字段分别设置为hw_module_t结构体和hw_device_t结构体。一切的一切都是为了在使用reinterpret_cast进行强制类型转换的时候能够兼容。