1. 安卓HAL模块基本

2. 定义hal层代码的5个特性

1)硬件抽象层具有与硬件的密切相关性。

2) 硬件抽象层具有与操作系统无关性。

3) 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功能。

4) 接口简单明了,太多接口函数会增加软件模拟的复杂性。

5) 具有可预测的接口设计有利于系统的软、硬件测试和集成。

3. 安卓中hal层相关目录

1)libhardware_legacy :过去的目录,采取链接库模块观念来架构

2)libhardware: 新版的目录,被调整为用HAL stub 观念来架构

3)ril: 是Radio 接口层

4)msm7k : 和QUAL 平台相关的信息

4. hal module基本介绍

4.1 hal module有3个结构体

4.1.1 struct hw_module_t

/*

  • Value for the hw_module_t.tag field

    */

define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))

define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')

/**

  • Every hardware module must have a data structure named HAL_MODULE_INFO_SYM

  • and the fields of this data structure must begin with hw_module_t

  • followed by module specific information.

    /

    typedef struct hw_module_t {

    /
    * tag must be initialized to HARDWARE_MODULE_TAG */

    uint32_t tag;

    /**

    • The API version of the implemented module. The module owner is
    • responsible for updating the version when a module interface has
    • changed.
    • The derived modules such as gralloc and audio own and manage this field.
    • The module user must interpret the version field to decide whether or
    • not to inter-operate with the supplied module implementation.
    • For example, SurfaceFlinger is responsible for making sure that
    • it knows how to manage different versions of the gralloc-module API,
    • and AudioFlinger must know how to do the same for audio-module API.
    • The module API version should include a major and a minor component.
    • For example, version 1.0 could be represented as 0x0100. This format
    • implies that versions 0x0100-0x01ff are all API-compatible.
    • In the future, libhardware will expose a hw_get_module_version()
    • (or equivalent) function that will take minimum/maximum supported
    • versions as arguments and would be able to reject modules with
    • versions outside of the supplied range.

      */

      uint16_t module_api_version;

define version_major module_api_version

/**
* version_major/version_minor defines are supplied here for temporary
* source code compatibility. They will be removed in the next version.
* ALL clients must convert to the new version format.
*/ /**
* The API version of the HAL module interface. This is meant to
* version the hw_module_t, hw_module_methods_t, and hw_device_t
* structures and definitions.
*
* The HAL interface owns this field. Module users/implementations
* must NOT rely on this value for version information.
*
* Presently, 0 is the only valid value.
*/
uint16_t hal_api_version;

define version_minor hal_api_version

/** Identifier of module */
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;

  1. 从hw_module_t 注释可以看出,每个硬件抽象层模块都必须有一个名称为 HAL_MODULE_INFO_SYM 的结构体,且这个结构体的第一个字段必须是hw_module_t
  2. hw_module_t.tag 的值必须是 HARDWARE_MODULE_TAG ,即(H) << 24) | ((W) << 16) | ((M) << 8) | (T) ,用来标识硬件抽象层模块结构体。
  3. hw_module_t.methods定义了一个硬件抽象层模块的操作列表

4.1.2 struct hw_modulemethods_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;

  1. hw_module_methods_t 只有一个函数指针成员变量,用来打开硬件抽闲层模块中的硬件设备。

    2)成员变量的参数module表示要打开的硬件设备所在模块;

    3)成员变量的参数id表示要打开的硬件设备的ID;

    4)成员变量的参数device是一个输出参数,用来描述一个已经打开的硬件设备。

  2. struct hw_device_t

define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')

/**

  • Every device data structure must begin with hw_device_t

  • followed by module specific public methods and attributes.

    /

    typedef struct hw_device_t {

    /
    * tag must be initialized to HARDWARE_DEVICE_TAG */

    uint32_t tag;

    /**

    • Version of the module-specific device API. This value is used by
    • the derived-module user to manage different device implementations.
    • The module user is responsible for checking the module_api_version
    • and device version fields to ensure that the user is capable of
    • communicating with the specific module implementation.
    • One module can support multiple devices with different versions. This
    • can be useful when a device interface changes in an incompatible way
    • but it is still necessary to support older implementations at the same
    • time. One such example is the Camera 2.0 API.
    • This field is interpreted by the module user and is ignored by the
    • HAL interface itself.

      */

      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;

1)从hw_device_t 注释可以看出硬件抽象层模块的每一个硬件设备都必须自定义一个硬件设备结构体,且他的第一个成员变量的类型必须是hw_device_t。

2)hw_device_t.tag 的值必须是 **HARDWARE_DEVICE_TAG ** ,即(H) << 24) | ((W) << 16) | ((D) << 8) | (T) ,用来标识硬件抽象中的硬件设备结构体。

3)结构体hw_device_t 的成员变量close是一个函数指针,它用来关闭一个硬件设备。

4.1.4

4.2 hal module有两个变量

4.3 hal module有一个函数接口

函数hw_get_module()。

5. hal源码分析

5.1 hardware.c

5.1.1 hal模块文件命名规范

define LOG_TAG "HAL"

/** Base path of the hal modules */

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

/**

  • 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. */ //emulator : 仿真器;pick up :获取

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

  1. 硬件抽象模块文件的命名规范为“<MODULE_ID>.variant.so”,其中MODULE_ID 标识模块的ID,variant 表示四个系统属性 ro.hardware、ro.product.board、ro.board.platform、ro.arch之一。
  2. 系统在加载硬件抽象层模块时,依次按照 ro.hardware.MODULE_ID、ro.hardware、ro.product.board、ro.board.platform、ro.arch的顺序来取他们的属性值。
  3. 如果其中一个系统属性存在,那么就把它的值作为variant的值,然后在检查对应的文件是否存在,如果存在,那么就找到要加载的硬件抽象层文件了;
  4. 如果四个属性都不存在,或者四个属性对应的系统硬件抽象层文件不存在,就是用 “<MODULE_ID>.default.so” 来作为要加载的硬件抽象层模块文件的名称

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));

/**

  • Load the file defined by the variant and if successful

  • return the dlopen handle and the hmi.

  • @return 0 = success, !0 = failure.

    */

    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;

    /*

    • load the symbols resolving undefined symbols before
    • dlopen returns. Since RTLD_GLOBAL is not or'd in with
    • RTLD_NOW the external symbols will not be global

      /

      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;

    }

/*

  • Check if a HAL with given name and subname exists, if so return 0, otherwise

  • otherwise return negative. On success path will contain the path to the HAL.

    */

    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;

    }

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 (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX); /*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/ /* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
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);

}

int hw_get_module(const char *id, const struct hw_module_t **module)

{

return hw_get_module_by_class(id, NULL, module);

}

HAL层分析的更多相关文章

  1. Android中基于CGroup的memory子系统HAL层分析-lmkd

    Android在内存管理上于Linux有些小的区别,其中一个就是引入了lowmemorykiller.从lowmemorykiller.c位于drivers/staging/android也可知道,属 ...

  2. Android Hal层简要分析

    Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...

  3. ZT Android4.2关于bluetooth在HAL层的分析(1)

    我的电子杂烩饭 http://blog.sina.com.cn/wuchuchu2012 [订阅][手机订阅] 首页 博文目录 图片 关于我 正文 字体大小:大 中 小 Android4.2关于blu ...

  4. 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一

    作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...

  5. Android HAL层与Linux Kernel层驱动开发简介

    近日稍微对Android中的驱动开发做了一些简要的了解. HAL:Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件厂商为了保护自己硬 ...

  6. Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  7. 如何在 kernel 和 hal 层读取同一个标志

    很多时候我们需要从 HAL 层(Hardware Abstract Layer)传一个标志给 kernel 层.一般这种传递是不能直接通过定义全局变量来实现的. 此时可以通过读写文件来实现该标志. 譬 ...

  8. 高通HAL层之Sensor HAL

    高通的HAL层其实分为两种,一种是直接从kernel这边报数据上来的,由sensor HAL层来监听,另一种是走ADSP的模式,HAL层是通过qmi的形式进行监听的: 走ADSP架构的可以看下面的博客 ...

  9. 【Android】Sensor框架HAL层解读

    Android sensor构建 Android4.1 系统内置对传感器的支持达13种,他们分别是:加速度传感器(accelerometer).磁力传感器(magnetic field).方向传感器( ...

  10. 〖Android〗OK6410a的Android HAL层代码编写笔记

    一.编写LED灯的Linux驱动程序代码 之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理: 所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维: 1. l ...

随机推荐

  1. vue 移动端px转rem

    1.安装lib-flexible 终端执行命令:npm i lib-flexible --save 2.在main.js引入lib-flexible 3.终端执行命令:npm install post ...

  2. JQuery 页面滚动至指定元素位置

    $(window).scrollTop($("#id").offset().top - 20);

  3. 如何修改Mac文件默认打开方式?

    熟悉Mac电脑的用户都知道,在 OS X 中,Finder 存储的文件总会以指定的某个默认应用程序打开,比如图片类型的文件默认以「预览」打开.但由于经常需要使用图片编辑工具 PS打开图片类型的文件,每 ...

  4. Jmeter进行服务器性能压力测试遇问题及解决方案

    最近再给公司的一个项目进行服务器性能进行压测,要出一些报告图形展示,放弃了用boom工具我选择了用jmeter工具进行压测过程中遇到了一些问题下面将一一列出及解决方案希望帮助到你们!!! 1.装第三方 ...

  5. 其他4-shell脚本后台运行知识

    1. 用途和方法 在实际工作中,一般会通过ssh连接服务器,隐藏可能就会有脚本或命令在执行期间不能中断的需求,若中断,则不仅前功尽弃,还可能破坏系统数据,下面是防止脚本执行终端的3种方法: 1)使用s ...

  6. Windows,easygui 安装

    在官网下载了easygui,但是根据网上的方法解压后将 easygui 文件夹(创建文件:easygui,只放easygui.py)放到Python36\Lib\site-packages下不行,有模 ...

  7. Cubemx 生成工程代码失败的原因

    折腾了好久(躺)翻了很多解答试了试终于捣鼓正常了,就在这里汇总一下看到过的问题 1.文件名.工程名或者工程文件路径/库路径上有中文名 2.Cubemx的版本过高 3.java环境的版本不适配 4.可能 ...

  8. 西瓜书6.2 matlab的libsvm使用

    因为python的教程没有找到详细的所以就改用matlab了 使用的是matlab r2016a,libsvm3-24,具体的安装配置教程就直接参考谦恭大大的了: https://blog.csdn. ...

  9. switch组件的使用

    正常情况下,path和component是一一对应的关系 switch可以提高路由匹配效率(单一匹配)

  10. 2月28日Android开发学习

    界面显示与逻辑处理 Android Studio利用XML标记描绘应用界面,使用java代码书写程序逻辑. 把App界面设计与代码逻辑分开的好处 使用XML文件描述App界面,可以很方便地在Adroi ...