Android Telephony原理解析与开发指南
上QQ阅读APP看书,第一时间看更新

1.3 Android Telephony框架结构

通过前面对Android手机操作系统整体框架结构及每一层的简单分析和说明,相信大家对Android智能手机操作系统已经有了一些基本的了解和认识。结合Android手机操作系统的整体框架,我们接着学习Android Telephony涉及的框架结构,首先看图1-3。

图1-3 Android Telephony框架结构

通过图1-3不难发现Android Telephony框架结构的一些规律,总结如下:

• Android Telephony的业务应用跨越AP和BP,AP与BP相互通信,符合前面介绍的智能手机的硬件基本结构。

• Android系统在AP上运行,而Telephony运行在Linux Kernel之上的用户空间。

• Android Telephony也采用了分层结构的设计,共跨越了三层:应用层、应用框架层和系统运行库层,与Android操作系统整体分层结构保持一致;

• Android Telephony从上到下共分三层:Telephony应用、Telephony框架、RIL(Radio Interface Layer,无线通信接口层,主要位于系统运行库层的HAL中,什么是HAL,接下来会详细介绍)。

• BP SoftWare在BP上运行,主要负责实际的无线通信能力处理,不在本书讨论的范围。

1.3.1 系统运行库层的HAL

HAL(Hardware Abstraction Layer,硬件抽象层)在Linux和Windows操作系统平台下有不同的实现方式。

Windows下的HAL位于操作系统的最底层,它直接操作物理硬件设备,用来隔离与不同硬件相关的信息,为上层的操作系统和设备驱动程序提供一个统一接口,起到对硬件的抽象作用。这样更换硬件后编写硬件的驱动时,只要实现符合HAL定义的标准接口即可,而上层应用并不会受到影响,也不必关心具体实现的是什么硬件。

Linux下的HAL与Windows下的HAL不太一样,HAL并不是位于操作系统的最底层,直接操作硬件;相反,它位于操作系统核心层和驱动程序之上,是一个运行在用户空间中的服务程序。

1.3.2 简析HAL结构

通过前面的学习,我们知道Android是基于Linux Kernel的开源智能手机操作系统,所以这里重点介绍基于Linux下的HAL结构,就不再单独介绍Windows下的HAL结构。

要想知道HAL结构,先看看来源于HAL 0.4.0 Specification的框图,如图1-4所示。

图1-4 HAL 0.4.0 Specification

HAL是一个位于操作系统和驱动程序之上,运行在用户空间中的服务程序。其目的是对上层应用提供一个统一的查询硬件设备的接口。我们都知道,抽象就是为了隔离变化,那么这里的HAL可以带给我们什么?首先,有了HAL接口,可以提前开始应用的开发,而不必关心具体实现的是什么硬件;其次,硬件厂家需要更改硬件设备,只要按照HAL接口规范和标准提供对应的硬件驱动,而不需要改变应用;最后,HAL简化了应用程序查询硬件的逻辑,把这一部分的复杂性转移到由HAL统一处理,这样当一些应用程序使用HAL的时候,可以把对不同硬件的实际操作的复杂性也交给不同硬件厂家提供的库函数来处理。

总之,HAL所谓的抽象并不提供对硬件的实际操作,对硬件的操作仍然由具体的驱动程序来完成。

1.3.3 Android为什么引入HAL

HAL的一些优势在前面已经提到,这里回顾一下。Android引入HAL不仅看重其自身的优势,而且还有一个非常重要的因素,为了保障在Android平台基于Linux开发的硬件驱动和应用程序,不必遵循GPL(General Public License)许可而保持封闭,以保障更多厂家的利益。我们都知道,Linux Kernel开源而且遵循GPL许可证,根据GPL许可证规定,对代码的任何修改都必须向社会开源。

那么Android是如何做到的呢?Linux Kernel和Android的许可证不一样,Linux Kernel是GPL许可证,Android是ASL(Apache Software License)许可证。ASL许可证规定,可以随意使用源码,但不必开源,所以构筑在Android之上的硬件驱动和应用程序都可以保持封闭。也就是说,只要把关键的与驱动处理相关的主要逻辑转移到Android平台内,在Linux Kernel中仅保留基础的通信功能,即使开源一部分代码,对厂家来讲也不会有什么损失。

谷歌选择了这样做,并且特意修改了Kernel,原本应该包括在Linux Kernel中的某些驱动关键处理逻辑,被转移到了HAL层中,从而达到了不必开源的目的。

注意

本书不再对GPL、ASL或其他的开源许可证做深入探讨,有兴趣的读者可以上网搜索详细资料。

1.3.4 Android中HAL的运行结构

由图1-2中可以知道Android源码中已经实现了一部分HAL,包括Wi-Fi、GPS、RIL、Sensor等,这些代码主要存储于以下目录:

• Android_src/hardware/libhardware_legacy

老式HAL结构,采用直接调用so动态链接库方式。

• Android_src/hardware/libhardware

新式HAL结构,采用Stub代理方式调用。

• Android_src/hardware/ril

RIL(Radio Interface Layer,无线通信接口层)作为本书重点关注和学习的内容,后面会采用单独章节详细讲解。

在Android中,HAL的运行机制是什么样的呢?它有两种运行机制,老式HAL和新式HAL,如图1-5所示。

图1-5 Android中HAL两种运行结构

从图中不难看出,左边是老式HAL结构。如图中所示,应用或框架通过so动态链接库调用从而达到对硬件驱动的访问。在so动态链接库里,实现了对驱动的访问逻辑处理。我们重点学习和理解HAL Stub方式,RIL也采用了此方式的设计思想。

HAL Stub是一种代理概念,虽然Stub仍是以*.so的形式存在,但HAL已经将*.so的具体实现隐藏了起来。Stub向HAL提供operations方法,Runtime通过Stub提供的so获取它的operations方法,并告知Runtime的callback方法。这样Runtime和Stub都有对方调用的方法,一个应用的请求通过Runtime调用Stub的operations方法,而Stub响应operations方法并完成后,再调用Runtime的callback方法返回。根据前面的描述再结合图1-6会更容易理解。

图1-6 HAL Stub结构

上层调用底层,通过底层HAL提供的函数,而底层在处理完上层请求后或硬件状态发生变化时回调上层,则通过Runtime提供的callback接口完成。

HAL Stub有一种包含关系,即HAL里包含了很多的Stub。Runtime只要说明请求类型,就可以取得并操作Stub对应的operations方法。其实现主要在hardware.c和hardware.h文件中。实质也是通过dlopen方法加载.so动态链接库,从而调用*.so里的符号(symbol)实现。