HAL的全称是Hardware Abstraction Layer, 即硬件抽象层。

HAL层是介于Android内核与上层之间抽象出来的一层结构,它是对linux驱动的一个封装,对上层提供统一接口,上层应用不必知道下层是如何实现的,它屏蔽了底层的实现细节。

1. HAL的由来

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有一些特殊的需求

2. HAL的演进

HAL以前是以module来被调用的。所谓module,就是将c文件编译成so文件,然后在jni中加载调用。此种方式现在在源码的libhardware_legacy文件夹下。后来HAL的架构改变,变成了以stub的形式来被上层调用。这样就有种面向对象的思想了。虽然也是编译成so文件然后加载,但是JNI是直接调用c对象。这种层次更清晰,而且更易于维护和扩展。

3. 源码目录

hardware/libhardware/include/hardware/gps.h

hardware/qcom/gps/loc_api/gps.c

其中gps.h中定义了GPS相关的结构体接口,在“重要结构体及接口”中已经介绍,在此不再赘述。

我们来看一下gps.c文件:

首先定义了gps设备模块实例,下面的注释很重要,说明了如何构建一个模块,这是Android中标准的构建模块写法。

/**
* 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.
*/
struct hw_module_t HAL_MODULE_INFO_SYM = {.tag = HARDWARE_MODULE_TAG,.module_api_version = 1,.hal_api_version = 0,.id = GPS_HARDWARE_MODULE_ID,.name = "loc_api GPS Module",.author = "Qualcomm USA, Inc.",.methods = &gps_module_methods,
};

这里的id用来指定模块库文件名的,methods指向gps.c文件中的gps_module_methods:

static struct hw_module_methods_t gps_module_methods = {.open = open_gps
};

gps_module_methods定义了设备的open函数为open_gps,我们来看open_gps函数:

static int open_gps(const struct hw_module_t* module, char const* name,struct hw_device_t** device)
{struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));if(dev == NULL)return -1;memset(dev, 0, sizeof(*dev));dev->common.tag = HARDWARE_DEVICE_TAG;dev->common.version = 0;dev->common.module = (struct hw_module_t*)module;dev->get_gps_interface = gps__get_gps_interface;*device = (struct hw_device_t*)dev;return 0;
}

此处可以看作是GPS设备的初始化函数,在使用设备前必须执行此函数。函数里面指定了hw_device_t的module成员,以及gps_device_t的get_gps_interface成员。上层可通过gps_device_t的get_gps_interface调用gps__get_gps_interface函数。gps__get_gps_interface的定义如下:

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{return get_gps_interface();
}

get_gps_interface的实现是在gps/loc_api/Loc.cpp:

// for gps.c
extern "C" const GpsInterface* get_gps_interface()
{unsigned int target = TARGET_DEFAULT;loc_eng_read_config();target = loc_get_target();LOC_LOGD("Target name check returned %s", loc_get_target_name(target));int gnssType = getTargetGnssType(target);switch (gnssType){case GNSS_GSS://APQ8064gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB);gss_fd = open("/dev/gss", O_RDONLY);if (gss_fd < 0) {LOC_LOGE("GSS open failed: %s\n", strerror(errno));}else {LOC_LOGD("GSS open success! CAPABILITIES %0lx\n",gps_conf.CAPABILITIES);}break;case GNSS_NONE://MPQ8064LOC_LOGE("No GPS HW on this target. Not returning interface.");return NULL;case GNSS_QCA1530:// qca1530 chip is presentgps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB);LOC_LOGD("qca1530 present: CAPABILITIES %0lx\n", gps_conf.CAPABILITIES);break;}return &sLocEngInterface;
}

sLocEngInterface的定义如下:

// Defines the GpsInterface in gps.h
static const GpsInterface sLocEngInterface =
{sizeof(GpsInterface),loc_init,loc_start,loc_stop,loc_cleanup,loc_inject_time,loc_inject_location,loc_delete_aiding_data,loc_set_position_mode,loc_get_extension
};

sLocEngInterface 指定了GpsInterface结构体的各个回调函数,如启动定位/取消定位等,这些回调函数的实现均在Loc.cpp中实现。

Android GPS学习笔记—HAL实现相关推荐

  1. Android GPS学习笔记(三)定位数据如何从GPS芯片到应用层

    定位的基础知识: 1.定位芯片和CPU之间通过串口进行通信 2.串口和CPU之间传输的是ASCII格式的NMEA(National Marine Electronics Association)信息, ...

  2. java/android 设计模式学习笔记(1)--- 单例模式

    前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使 ...

  3. Android Binder 学习笔记

    前言: Binder是Android给我们提供的一种跨进程通信方式.理解Binder能帮助我们更好的理解Android的系统设计,比如说四大组件,AMS,WMS等系统服务的底层通信机制就都是基于Bin ...

  4. Android:日常学习笔记(8)———探究UI开发(2)

    Android:日常学习笔记(8)---探究UI开发(2) 对话框 说明: 对话框是提示用户作出决定或输入额外信息的小窗口. 对话框不会填充屏幕,通常用于需要用户采取行动才能继续执行的模式事件. 提示 ...

  5. Android:日常学习笔记(6)——探究活动(3)

    Android:日常学习笔记(6)--探究活动(3) 活动的生命周期 返回栈 Android中的活动是可以叠加的,我们每启动一个新活动,就会覆盖在原来的活动上,点击Back以后销毁最上面的活动,下面的 ...

  6. Android:日常学习笔记(8)———探究UI开发(5)

    Android:日常学习笔记(8)---探究UI开发(5) ListView控件的使用 ListView概述 A view that shows items in a vertically scrol ...

  7. Android Studio --- [学习笔记]TCP(第2弹)、GridView、ScrollView

    说明 这篇主要接上一篇Android Studio - > [学习笔记]RadioButton.CheckBox.ImageView.ListView.TCP的三次握手 对上面回答的细解,并用J ...

  8. Android Studio --- [学习笔记]RadioButton、CheckBox、ImageView、ListView、TCP的三次握手

    说明 源代码 在2.x里有TCP的三次挥手与四次握手,先对它进行简单的回答(百度).预计在下一篇里,会继续说明TCP 接上一篇: Android Studio - > [学习笔记]Button. ...

  9. Android动画学习笔记

    Android实战经验之图像处理及特效处理的集锦 https://www.oschina.net/question/231733_44154 Android动画学习笔记 3.0以前,android支持 ...

  10. Android 开发学习笔记:七大知识点板块汇总

    前言 我从事 Android 开发行业也有些年头,工作期间也接触过很多 Android 开发者, 因此也非常清楚 程序员最大的限制并非年龄而是实力: 但大多数初中级Android工程师,想要提升技能, ...

最新文章

  1. 程序员的朋友圈应该是这样的。。。
  2. 使用深度神经网络进行自动呼叫评分(二)
  3. 得到文件的服务器路径,如何获取服务器上的路径?
  4. Python基础----python的使用(二)
  5. Python文件与目录操作
  6. python布尔系列_python数据分析类库系列-Numpy之布尔型索引
  7. 猜数字if循环(1)
  8. mysql 堵塞_Mysql解决USE DB堵塞详解
  9. 关于AI与高性能计算加速融合,这里有英伟达最新的4个应用案例
  10. ubuntu保护眼睛的设置
  11. 中兴配置dhcp服务器,中兴F623路由器如何投入使用dhcp服务器
  12. C++实现身份证校验和归属地查询
  13. win7无法查看win10工作组计算机,win7不显示工作组解决方法
  14. oracle数据库赋权
  15. flash AS3常用公式
  16. SQL读取Excel数据
  17. CSS背景图片background如何改变大小以及样式设置
  18. html设置长宽高代码_html设置高等于宽
  19. VB.NET中IIF和IF使用效率分析
  20. JAVA RPG游戏

热门文章

  1. Linux虚拟机挂载新的硬盘
  2. 遥感原理与应用_专家报告 | 叶绿素荧光卫星遥感—原理与应用
  3. html5调查问卷的计分实验,问卷调查实验
  4. VMware安装苹果虚拟机-亲测有效
  5. php 中英文互换,php做项目进行中英文的切换,如何快速实现
  6. Win10无法安装 文鼎CS行楷.TTF
  7. 4、LED1602液晶模组介绍及其编程使用
  8. StarUML3.0.2——超好用的UML画图工具推荐
  9. 【unity】解决3d max导出的fbx在unity贴图丢失的问题
  10. 吐血推荐 | 5+1款源代码管理笔记本(全平台)