每个模块对应的动态链接库的名字是遵循HAL的命名规范的。举例说明,以GPS模块为例,
硬件抽象模块的动态链接库文件名命名规范定义在:\hardware\libhardware\hardware.c:
/**
* There are a set of variant filename for modules. The form of the filename
* is "<MODULE_ID>.variant.so" so for the led module the Dream variants
* of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
*
* led.trout.so
* led.msm7k.so
* led.ARMV6.so
* led.default.so
*/
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"
};
//后面会用到
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
------ 这里理解为4个大类,"ro.hardware.%s" , 后面可以自定义,当你选择新hardware后,
需要在.rc 文件中, 添加setprop ro.hardware.%s sec
编译hal so MK 配置 LOCAL_MODULE := nfc_nci.sec, 生成lib库名 libnfc_nci.sec.so
Hal 调用Open So库,传入名字 dlOpen(“nfc_nci.sec”);
Java Server调用 open .id = CAMERA_HARDWARE_MODULE_ID,
HAL会按照variant_keys[]定义的属性名称的顺序逐一来读取属性值,若值存在,则作为variant的值加载对应的动态链接库。
如果没有读取到任何属性值,则使用<MODULE_ID>.default.so
作为默认的动态链接库文件名来加载硬件模块。
-
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
-
if (property_get(prop_name, prop, NULL) > 0) {
首先根据class_id生成module name,这里就是hw_get_module函数传进来的id;
根据属性名称“ro.hardware.<id>”获取属性值,如果存在,则作为variant值调用前面提到的hw_module_exits检查目标是否存在。
如果存在,执行load。
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
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_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;
if (hw_module_exists(path, sizeof(path), name, "default") == 0) 默认是default
如果不存在,则遍历variant_keys数组中定义的属性名称来获取属性值,得到目标模块库名字,检查其是否存在;
如果根据属性值都没有找到模块共享库,则尝试检查default的库是否存在;如果仍然不存在,返回错误。
如果上述任何一次尝试找到了目标共享库,path就是目标共享库的文件路径,调用load执行真正的加载库的工作。