HAL 层简介

HAL 层简介简介 HAL 层又称硬件抽象层 HAL 层在 Android 体系中有着深远的意义 因为 Android 究竟是完全开源还是完全不开源的秘密就在这一层 Google 将硬件厂商的驱动程序放在这一层 正是因

大家好,欢迎来到IT知识分享网。

简介:

1、认识 HAL 层

HAL 层简介

1.1.1 HAL 层的发展

硬件抽象层大概分为一下 6种HAL:

  • 上层软件
  • 虚拟驱动,设置管理模块
  • 内部通信Server
  • 内部以太网
  • 内部通信Client
  • 用户接入口

定义硬件抽象层接口的代码具有一下5个特点:

  • 硬件抽象层具有与硬件的密切相关性
  • 硬件抽象层具有与操作系统无关性
  • 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功能
  • 接口简单明了,太多接口函数会增加软件模拟的复杂性
  • 具有可预测的接口设计有利于系统的软、硬件测试和集成。

在Android 源码中,HAL 主要被保存在下面的目录中:

  • libhardware_legacy :过去的目录,采取链接库模块观念来架构
  • libhardware: 新版的目录,被调整为用HAL stub 观念来架构
  • ril: 是Radio 接口层
  • msm7k : 和QUAL 平台相关的信息

HAL 层简介

1.1.2 过去和现在的区别

  • HAL_legacy:这是过去HAL的模块,采用共享库形式,在编译时会调用到。由于采用functroncall形式调用,因此可被多个进程使用,但会被mapping到多个进程窄间中,造成浪费,同时需要考虑代码能否安全重入的问题(ThreadSafe)。
  • HAL:这是新式的HAL,采用了HALmodule和HAL stub 结合形式。HALstub不是一个共
    享库,在编译时上层只拥有访问HALstub的函数指针,并不需要HAL stub-在上层通过HAL
    module提供的统一接口获取并操作HAL stub,所以,文件只会被映射到一个进程,而不会存
    在重复映射和重入问题。


2.2 分析HAL 层源码

2.2.1 分析 HAL moudle 

在 HAL moudle 中主要分为如下3个结构:

  • struct hw_module
  • struct hw_modulemethods_t
  • struct hw_device_t

上述 3 个结构的集成关系 如图 6-4 所示

HAL 层简介

接下来分析 hardware.c 源码。

函数hw_get_module() 的具体实现代码如下:

代码 /hardware/libhardware/hardware.c

   (1) 通过配置变量 循环寻找一个模块

·······

(2)数组variant_keys 在上述函数中,需要用到数组variant_keys,因为HAL_VARIANT_KEYS_COUNT就是数组variant_keys的大小。定义此数组的代码如下:

然后通过此数组,并使用如下代码获取操作权限:

(3) 将路径和文件名保存到 path , 接下来将通过如下代码将路径和文件保存在path 中:

通过上述代码,把 HAL_LIBRARY_PATH/id.*.so 保存到 path 中,其中   就是上面 variant_keys 中各个元素的值。

(4) 载入相应的库,并把他们的 HMI 不保存到 module 中,具体代码如下

    return -ENOENT;

(5)打开相应的库并获得 hw_module_t 结构体,具体代码如下:

    hmi->dso = handle;

    *pHmi = hmi;

2.2.2  分析mokoid 工具

# svn checkout  http://mokoid.googlecode.com/svn/trunk/mokoid-read-only

下载 mokoid 工程之后,目录结构如图6-5所示,

需要通过 JNI 来实现 Android 的HAL, JNI 是Java 程序可以调用C/C++ 写的动态链接库,所以HALkeyi shiyong C/C++语言编写,这样效率更高。在Android 下有以下两种访问HAL 的方式:

  • Android 的app 直接通过 service 调用.so 格式的JNI : 此方法比较简单高效,但是不正规。
  • 经过 Manager 调用 Service : 此方法实现起来比较复杂,但是更符合目前的Android 框架。在此方法中,在进程 LegManager 和 LedService (Java) 中需要通过进程通信的方式实现通信。

在 mokoid 工程中分别实现上述两种方法,下面将详细介绍这两种方法实现原理:

1.直接调用 Service 方法的实现代码

(1)HAL 层的实现代码

文件 hardware/modules/led/led.c 的实现代码如下:

#define LOG_TAG “MokoidLedStub”

#include <hardware/hardware.h>

#include <mokoid/led.h>

/*/

    *device = &dev->common;      //  将实例化的 led_control_device_t 地址返回给 Jni 层

(2) JNI 层的实例代码

文件 frameworks/base/service/jni/com_mokoid_server_LedService.cpp 的实现代码如下:

// —————————————————————————-

struct led_control_device_t *sLedDevice = NULL;

static jboolean mokoid_setOn(JNIEnv* env, jobject thiz, jint led) {

    LOGI(“LedService JNI: mokoid_setOn() is invoked.”);

static jboolean mokoid_setOff(JNIEnv* env, jobject thiz, jint led) {

    LOGI(“LedService JNI: mokoid_setOff() is invoked.”);

/ helper APIs */

// —————————————————————————-

// —————————————————————————-

(3) Service 的实现代码

这里的service 属于 Framwork 层,文件 framworks/base/service/java/com/mokoid/server/LedService.java 的实现代码:

package com.mokoid.server;

public final class LedService extends ILedService.Stub {    

(4) App 测试程序的实现代码

这里的测试程序属于 APP 层,文件 apps/LedClient/src/com/mokoid/LedClient/LedClient.java 的实现代码如下:

2、通过 manager 调用 Service 的实现代码

(1) Manager 的实现代码

APP 通过 此 Manager 和 Service 实现通信功能,文件 framwork/base/core/java/mokoid/hardware/Ledmanager.java

package mokoid.hardware;

因为 LedService 和 Ledmanager 分别不属于不同的进程,所以在此需要考虑不同进程间的通信问题,此时,在 manager 中可以增加一个aidl 文件来描述通信接口,文件 

framworks/base/core/java/mokoid/hardware/ILedService.aidl 的代码实现如下:

package mokoid.hardware;

(2) SystemService 的实现代码

此处的 SystemServer 属于 App 层,文件 apps /LedTest/src/com/mokoid/LedTest/Ledsystem/Server.java 的代码如下:

package com.mokoid.LedTest;

import com.mokoid.server.LedService;

public class LedSystemServer extends Service {

3.App 测试程序

这里的app测试程序属于APP 层,文件 mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedTest.java 的实现代码如下:

    public void onClick(View v) {

4、使用HAL 的方法 总结

(1)Native code 通过hw_get_module 调用获取 HAL stub.

hw_get_module (LED_HARDWARE_MODULE_ID,(const hw_module_t )&module)

(2) 通过继承 hw_module_methods_t 的 callback 拉打开设备。

module->methods->open(module,LED_HARDWARE_MODULE_ID,(struct hw_device_t)device);

(3) 通过继承 hw_device_t 的callback (回访) 来控制设备

sLedDevice -> set_on(sLedDevice,led);

sLedDevice-> set_off(sLedDevice,led);

4.1. 编写 HAL stub 的方法

编写HAL stub 的基本流程入下图所示。

1)自定义 HAL 结构体,编写 头文件 led.h 和 hardware/hardware.h 主要代码如下:

struct ledmodulet {

        struct hw_module_t common;

}

struct led_control_device_t {

        struct hw_device_t common;

        int  fd ;  // 文件描述符 的 LED 装置

        int (*set_on) (struct led_control_device_t *dev, int32_t led);   // 支持控制的 api

        int (*set_off) (struct led_control_device_t *dev,int32_t led);

}

(2) 编写 文件 led.c 实现 HAL stub 注册功能

(3)设置 led_module_methods 继承于 hw_module_methods_t,并实现对 open() 方法的回访,

struct hw_module_methods_t led_module_methods = {

        open : led_device_open

};

(4) 使用 HAL_MODULE_INFO_SYM 实例,led_module_t, 注意 这个名称不可修改,

const struct led_module_t HAL_MODULE_INFO_SYM = {

        common : {

        tag : HARDWARE_MODULE_TAG,

        version_major:1,

        version_minor:0,

        id:LED_HARDWARE_MODULE_ID,

        name:”Sample LED Stub”,

        author: “The Mokoid Open Source Project”,

        methods: &led_module_methods,

        }

// 支持 api 

};

(5) open() 是一个必须实现的回调 API ,用于负责 申请 结构体空间并填充信息,还可以注册具体操作API 接口, 并打开 Linux 驱动。但是系因为存在多重继承关系,所以只需要对结构体hw_device_t 对象申请空间即可。

    *device = &dev->common;

        // 初始化硬件接口

      dev->fd = open(LED_DEVICE,o_RDONLY);

       if (dev->fd < 0 ) {

                return -1;        

        }

        led_off(dev,LED_C608);

        led_off(dev,LED_C609);

(6) 填充具体 API 操作,具体代码如下:

int led_on (struct led_control_device_t *dev,int32_t led) {

        int fd;

        LOGI(“LED Stub: set %d on.”,led);

        fd = dev->fd;

        switch(led) {

                case LED_C608:

                        ioctl(fd,1,&led);

                        break;

                case LED_C609:

                          ioctl(fd,1,&led)

                        break;

                default:

                           return -1;

        }

return 0;

}

int led_off (struct led_control_device_t *dev,int32_t led) {

        int fd;

        LOGI(”LED Stub : set %d off.”,led);

        fd = dev-> fd;

        switch(led) {

                case LED_C608:

                        ioctl(fd,2,&led);

                        break;

                  case LED_C609:

                        ioctl(fd,2,&led);

                        break;

                default:

                        return -1;

        }

        return  0;

}

文章摘自:

《Android 底层接口和驱动开发技术详解》

相关资料下载跳转

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/123035.html

(0)
上一篇 2025-10-12 09:33
下一篇 2025-10-12 10:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信