众所周知Android是基于Linux内核的开放性系统,我们可以看到Google开放的大部分操作系统实现代码。之所以说它是开放的而不是开源的,是因为Android系统代码不是完全开源的。这始于Linux内核开源协议和第三方厂商隐私安全的矛盾,为了绕过之一矛盾,Google构建了HAL,通过它在在遵守Linux协议的同时,又能保护第三方厂商的利益;既然能这么牛,那么Google是如何做到的呢,秘密就在硬件抽象层(HAL)。So, shutup, Let’s read the fucking sourcecode !
硬件抽象层 (HAL)。HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并会由 Android 系统适时地加载。HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。
为了能够清晰的分析硬件抽象层,我们选取power来分析,一来衔接上一篇中Hw中的服务,二来power部分结构较为简单易于分析理解;
1. HARDWARE抽象结构
hardware/libhardware/include/hardware.h
主要是三个结构体 hw_module_t ,hw_module_methods_t ,hw_device_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 */ 模块识别ID
const char *id;
/** Name of this module */ 模块名
const char *name;
/** 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;
模块方法结构体,用于打开模块对应的设备
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;
具体设备对应的结构体
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;
hardware/libhardware//hardware.c
熟悉的方法 hw_get_module
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
动态库文件和数量
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]));
检查动态库是否存在,查找动态库并执行动态库加载
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};
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) { //模块存在
goto found;
}
}
/* 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); //加载模块
}
按照 class_id, path, module 加载动态库
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;
}
2. Power的调用
回到上上一篇绑定模式下加载动态库时的代码段会执行 hw_get_module 方法
//ServiceManagement.cpp -> PassthroughServiceManager 载入动态库
IPower* HIDL_FETCH_IPower(const char* /* name */) {
const hw_module_t* hw_module = nullptr;
power_module_t* power_module = nullptr;
//取Power驱动模型结构
int err = hw_get_module(POWER_HARDWARE_MODULE_ID, &hw_module);
if (err) {
ALOGE("hw_get_module %s failed: %d", POWER_HARDWARE_MODULE_ID, err);
return nullptr;
}
if (!hw_module->methods || !hw_module->methods->open) {
power_module = reinterpret_cast<power_module_t*>(
const_cast<hw_module_t*>(hw_module)); //强转
} else {
//打开
err = hw_module->methods->open(
hw_module, POWER_HARDWARE_MODULE_ID,
reinterpret_cast<hw_device_t**>(&power_module));
if (err) {
ALOGE("Passthrough failed to load legacy HAL.");
return nullptr;
}
}
return new Power(power_module);
}
hardware/libhardware/include/power.h
头文件中有一个包含 hw_module_t 的结构体
typedef struct power_module {
struct hw_module_t common; // 模块结构体 hw_module_t
void (*init)(struct power_module *module);
void (*setInteractive)(struct power_module *module, int on);
void (*powerHint)(struct power_module *module, power_hint_t hint,
void *data);
void (*setFeature)(struct power_module *module, feature_t feature, int state);
int (*get_platform_low_power_stats)(struct power_module *module,
power_state_platform_sleep_state_t *list);
ssize_t (*get_number_of_platform_modes)(struct power_module *module);
int (*get_voter_list)(struct power_module *module, size_t *voter);
} power_module_t;
hardware\libhardware\modules\power\power.c
static void power_init(struct power_module *module UNUSED_ARGUMENT)
{
}
static void power_set_interactive(struct power_module *module UNUSED_ARGUMENT,
int on UNUSED_ARGUMENT)
{
}
static void power_hint(struct power_module *module UNUSED_ARGUMENT,
power_hint_t hint,
void *data UNUSED_ARGUMENT) {
switch (hint) {
default:
break;
}
}
static struct hw_module_methods_t power_module_methods = {
.open = NULL,
};
//关键数据结构
struct power_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = POWER_MODULE_API_VERSION_0_2,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "Default Power HAL",
.author = "The Android Open Source Project",
.methods = &power_module_methods, //关联 hw_module_methods_t
},
.init = power_init, //关联本地方法
.setInteractive = power_set_interactive,
.powerHint = power_hint,
};
通过结构体转换后就可以绕过Linux协议的限制,通过调用Linux内核的方法打开位于内核之外的驱动。不得不说这种做法保护了各厂商的利益,却失去了打造一个完全开源的操作系统的机会。今天就到这里,再回。