zoukankan      html  css  js  c++  java
  • 【转】【Android】HAL分析

    原文网址:http://www.cnblogs.com/lcw/p/3335505.html

    HAL概述

      以下是基于android4.0.3,对应其他低版本的代码,可能有所差异,但基本大同小异。

          Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚。

      思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。

      也正是因为Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中删除。GPL和硬件厂商目前还是有着无法弥合的裂痕。Android想要把这个问题处理好也是不容易的。

        总结下来,Android HAL存在的原因主要有:

    1. 并不是所有的硬件设备都有标准的linux kernel的接口
    2. KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去用HAL方 式绕过GPL。
    3. 针对某些硬件,An有一些特殊的需求

    Android架构

    源码位置

    /hardware/libhardware_legacy/    - 旧的架构、采取链接库模块的方式

    /hardware/libhardware          新架构、调整为 HAL stub 目录的结构如下:

    /hardware/libhardware/hardware.c  编译成libhardware.s置于/system/lib

    /hardware/libhardware/include/hardware目录下包含如下头文件:

    hardware.h                             通用硬件模块头文件

    copybit.h                               copybit模块头文件

    gralloc.h                                gralloc模块头文件

    lights.h                                 背光模块头文件

    overlay.h                              overlay模块头文件

    qemud.h                               qemud模块头文件

    sensors.h                             传感器模块头文件

    /hardware/libhardware/modules  目录下定义了很多硬件模块

    /hardware/msm7k 

    /hardware/qcom 

    /hardware/ti 

    /device/Samsung 

    /device/moto            各个厂商平台相关的hal

       这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录。

    HAL层的实现方式

      目前HAL存在两种构架,位于libhardware_legacy目录下的“旧HAL架构”和位于libhardware目录下的“新HAL架构”。

      两种框架如下图所示:

    libhardware_legacy 

      libhardware_legacy 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。

      当然,应用程序也可以不需要通过 JNI 的方式进行,直接加载 *.so (dlopen)的做法调用*.so 里的符号(symbol)也是一种方式。

      总而言之是没有经过封装,上层可以直接操作硬件。

    libhardware 

      现在的libhardware 架构,就有stub的味道了。

      HAL stub 是一种代理人(proxy)的概念,stub 虽然仍是以 *.so檔的形式存在,但HAL已经将 *.so 档隐藏起来了。

      Stub 向 HAL提供操作函数(operations),而 runtime 则是向 HAL 取得特定模块(stub)的 operations,再 callback 这些操作函数。

      这种以 indirect function call 的架构,让HAL stub 变成是一种包含关系,即 HAL 里包含了许许多多的 stub(代理人)。

      Runtime 只要说明类型,即 module ID,就可以取得操作函数。

      对于目前的HAL,可以认为Android定义了HAL层结构框架,通过几个接口访问硬件从而统一了调用方式。

    JNI

      Android的HAL的实现需要通过JNI(Java Native Interface)。

      JNI简单来说就是java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。

      JNI->通用硬件模块->硬件模块->内核驱动接口,具体一点:JNI->libhardware.so->xxx.xxx.so->kernel,具体来说:android frameworks中JNI调用hardware.c中定义的hw_get_module函数来获取硬件模块,然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能

    访问HAL方式

      在Android下访问HAL大致有以下两种方式。

    经过service调用

      Android的app可以直接通过service调用.so格式的jni。

    经过Manager调用service

      上面两种方法应该说是各有优缺点:

      第一种方法简单高效,但不正规。

      第二种方法实现起来比较复杂,但更符合目前的Android框架。

      第二种方法中,LedManager和LedService(java)在两个进程中,需要通过进程通讯的方式来通讯。

      在现在的android框架中,这两种方式都存在,比如对于lights,是直接透过LightsService调用JNI,而对于sensor,中间则是通过SensorsManager来调用JNI的。

    通用硬件模块(libhardware.so)

       一般来说HAL moudle需要涉及的是三个关键结构体:

    struct hw_module_t;   
    struct hw_module_methods_t;
    struct hw_device_t;

      这三个结构体定义在hardware.h中(/hardware/libhardware/include/hardware/hardware.h)。

      头文件中主要定义了通用硬件模块结构体hw_module_t,声明了JNI调用的接口函数hw_get_module、hw_module_t。

      定义如下:

     View Code

      如注释所说,所有的hal模块都要有一个以HAL_MODULE_INFO_SYM命名的结构,而且这个结构要以hw_module_t开始,即要继承hw_module_t这个结构。

      比如lights,sensor:

    复制代码
     1 struct sensors_module_t 
     2 {
     3  struct hw_module_t common;
     4 int (*get_sensors_list)(struct sensors_module_t* module,
     5             struct sensor_t const** list);
     6 };
     7 
     8 /*
     9  * The lights Module
    10  */
    11 struct light_module_t HAL_MODULE_INFO_SYM = {
    12     common: {
    13         tag: HARDWARE_MODULE_TAG,
    14         version_major: 1,
    15         version_minor: 0,
    16         id: LIGHTS_HARDWARE_MODULE_ID,
    17         name: "Lights module",
    18         author: "Rockchip",
    19         methods: &light_module_methods,
    20     }
    21 };
    22 
    23 const struct sensors_module_t HAL_MODULE_INFO_SYM = {
    24     .common = {
    25         .tag = HARDWARE_MODULE_TAG,
    26         .version_major = 1,
    27         .version_minor = 0,
    28         .id = SENSORS_HARDWARE_MODULE_ID,
    29         .name = "Stingray SENSORS Module",
    30         .author = "Motorola",
    31         .methods = &sensors_module_methods,
    32     },
    33     .get_sensors_list = sensors__get_sensors_list
    34 };
    复制代码

      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);
    } hw_module_methods_t;
    复制代码

      该方法在定义HAL_MODULE_INFO_SYM的时候被初始化。目前该结构中只定义了一个open方法,其中调用的设备结构体参数hw_device_t定义如下:

    复制代码
     1  /**
     2  * Every device data structure must begin with hw_device_t
     3  * followed by module specific public methods and attributes.
     4  */
     5 
     6 typedef struct hw_device_t
     7 {
     8     /** tag must be initialized to HARDWARE_DEVICE_TAG */
     9     uint32_t tag;
    10 
    11     /** version number for hw_device_t */
    12     uint32_t version;
    13 
    14     /** reference to the module this device belongs to */
    15     struct hw_module_t* module;
    16 
    17     /** padding reserved for future use */
    18     uint32_t reserved[12]; 
    19 
    20     /** Close this device */
    21     int (*close)(struct hw_device_t* device);
    22 } hw_device_t;
    23 
    24 struct light_device_t 
    25 {
    26     struct hw_device_t common;
    27     int (*set_light)(struct light_device_t* dev,
    28             struct light_state_t const* state);
    29 };
    30 
    31 /**
    32  * Every device data structure must begin with hw_device_t
    33  * followed by module specific public methods and attributes.
    34  */
    35 
    36 struct sensors_poll_device_t 
    37 {
    38     struct hw_device_t common;
    39     int (*activate)(struct sensors_poll_device_t *dev,
    40             int handle, int enabled);
    41     int (*setDelay)(struct sensors_poll_device_t *dev,
    42             int handle, int64_t ns);
    43     int (*poll)(struct sensors_poll_device_t *dev,
    44             sensors_event_t* data, int count);
    45 };
    复制代码

      亦如注释所说,每一个设备的数据结构都必须也以hw_device_t开始。

      hw_get_module函数声明如下:

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

      参数id为模块标识,定义在/hardware/libhardware/include/hardware录下的硬件模块头文件中。

      参数module是硬件模块地址,定义在/hardware/libhardware/include/hardware/hardware.h中

    调用关系

      

    QQ联系方式:lcw@v.gg欢迎联系十狼
    邮箱:wwwlllll@126.com
    本文申明:本文版权归作者和博客园共有,欢迎转载,转载请注明出处.
  • 相关阅读:
    计算机网络
    git学习总结
    MySQL性能优化的21条最佳经验【转】
    为什么Laravel是最成功的PHP框架?
    分布式集群系统下的高可用session解决方案
    浏览器中输入URL到返回页面的全过程
    真正的inotify+rsync实时同步 彻底告别同步慢
    memcache中的add和set方法区别
    php 接口 implements 使用
    Redis的PHP操作手册(自用)
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4615264.html
Copyright © 2011-2022 走看看