Android 随想录之 Android 系统架构

应用层(Application)

Android 的应用层由运行在 Android 设备上的全部应用程序共同构成(系统预装程序以及第三方应用程序)。java

系统预装应用程序包含拨号软件、短信、联系人、邮件客户端、日历、地图以及浏览器等提供基础功能的应用程序构成。第三方应用程序则是基于 Android SDK(Android Software Development Kit)进行开发,并受到框架层 SDK 接口约束的应用程序。二者的区别在于,系统预装应用比第三方应用拥有更高的系统使用权限:系统预装应用可使用 SDK 中隐藏的、不对第三方应用开放的系统 API。android

一般状况下,Android 应用程序是使用 Java 做为主要开发语言的。若是需求中涉及到性能要求较高的运算、图形处理或者须要使用已经存在的 C/C++类库,经过 Java 实现的话,则可能带来运行效率低下、C/C++类库移植成本太高等问题。所以,在开发过程当中,咱们可使用 C/C++实现底层模块,并经过 JNI(Java Native Interface)接口实现底层模块与 Java 层的互相调用。数据库

Android 提供的 NDK(Native Development Kit)中包含的交叉编译工具用来支持 Java 与 C/C++的相互调用。经过 NDK 甚至能够绕过框架层 SDK 接口的约束,直接使用 C++调用特定的系统功能。自 Android 2.3 (Api Level 9)以后,新增android.app.NativeActivity 类(经过调用预约义的 JNI 接口实现),这就意味着可使用 C/C++完成整个应用程序的开发。编程

因为 Android 中大多数的控件并无提供 Native 的实现,若是须要进行大量的 UI 开发工做(使用游戏引擎开发游戏除外),则大大下降了开发效率。浏览器

一种理想状况下的设计思想是,使用 Java 做为上层 UI 的实现,使用 C/C++做为业务层面的实现,经过 Android 的交叉编译工具完成整个应用程序的开发。安全

由此带来的好处是,执行效率的提高以及对核心业务的保护。效率的提高是由 C/C++ 自己的执行效率决定的,而对核心业务的保护则是由 C/C++ 反编译的难度较高、反编译后文件难于阅读的特性决定的。网络

可是由此带来的开发效率下降、维护和调试难度增大,甚至会形成兼容性降低等因素也是不得不考虑的。数据结构

框架层 (Application Framework)

框架层是 Android 系统中最为核心的部分,也是 Android 系统设计思想集中体现的部分。架构

框架层提供了大量的 API 供开发者调用,而弄清楚这些 API 的具体功能和用法则是 Android 应用程序开发过程当中最为重要的环节。app

框架层不仅是应用程序开发的基础,也是软件复用的重要手段,任何一个应用程序均可以发布它的功能模块——只要发布时遵照了框架层的约定,那么其余的应用程序也可使用这个模块。

框架层由多个系统服务(System Service)组成,包括组件管理服务、窗口管理服务、地理信息服务、电源管理服务、通话管理服务等。全部的系统服务都寄宿在系统核心进程(System Core Process)中,在运行时,每一个服务都占据一个独立的进程,彼此之间经过进程间通讯机制(IPC,Inter-Process Communication)发送消息以及传输数据。

对于开发者而言,最为直观的框架层体现就是 Android SDK,它经过一系列的 Java 功能模块来实现应用所须要的可复用的组件,提供了应用开发的规范,屏蔽了应用层与底层交互的复杂性。

框架层的设计决定了上层应用程序的开发模式、开发效率以及可以实现的功能范畴。

从系统运行的角度来看,Android 指望框架层是全部应用程序运行的核心,参与到应用层的每一次操做中,并进行全局统筹。Android 应用的最大特征是基于组件的设计方式,每一个应用程序都由若干个组件构成,组件与组件之间经过框架层的系统服务集中的调度和传递信息。

框架层主要是使用 Java 和 JNI 实现的,位于该层的主要组件以下:

  • 视图系统(View System) 提供了可扩展的用于构建应用程序 UI 的控件,包括ListViewGridViewTextViewButtonWebView 等。
  • 内容提供器(Content Provider) 提供应用程序之间数据共享的接口。
  • 资源管理器(Resource Manager) 提供非代码资源的访问接口,如字符串、布局文件等。
  • 通知管理器(Notification Manager) 用来在状态栏显示自定义的 提示信息。
  • 活动管理器(Activity Manager) 用来管理应用程序生命周期并提供通用的导航回退功能。
  • 窗口管理器(Window Manager) 管理全部的窗口程序。
  • 包管理器(Package Manager) 提供 Android 系统内的程序管理。

框架层是基于 Android 核心类库实现的 Android 系统框架层的 API,也就是应用开发人员所使用的 Android 开发包。Android 开发包以 android.开头,其实现位于framework\base\目录中,其中framework \base\core\java包含了大部分 API,还有另一部分 API 属于Android 系统库中的扩展库部分,分别位于:

  • framework\base\graphics\java\
  • framework\base\media\java\
  • framework\base\opengl\java\
  • framework\base\wifi\java\
  • framework\base\location\java\

Android 运行时(Android Runtime)

Android 运行时有两部分组成:Android 核心类库和 Dalvik 虚拟机。其中核心类库提供了 Java 语言核心库所能使用的绝大部分功能,包括Java 对象库、文件管理库、网络通讯等。 Dalvik 虚拟机则提供了 Android 应用程序的运行环境,负责动态解析执行应用、分配空间、管理对象生命周期等工做。

Android 运行时使得 Android 设备从本质上与一个移动 Linux 实现区分开来。

Dalvik 虚拟机

与传统的 Java 虚拟机不一样的是,一方面,Dalvik 虚拟机使用新的二进制码格式文件.dex,而再也不使用传统虚拟机的二进制码做为其编译的中间文件(.class)。在 Android 应用程序的编译过程当中,Android 会对部分.class文件中的指令作转义处理,使用 Dalvik 虚拟机特有的指令集 OpCodes 替换,并将全部的.class文件统一转换成.dex文件。.dex文件会整合.class文件中的重复信息,并对冗余部分作全局的优化,合并重复的常量定义,节约常量池的资源开销,另外一方面,Dalvik虚拟机放弃了传统虚拟机基于栈的指令架构,采用基于寄存器的指令架构设计,以确保更为高效的执行效率和硬件能力。

基于堆栈的指令架构相对于基于寄存器的架构,其指令更为紧凑。Java 虚拟机使用的指令只占据一个字节,于是被称做字节码。基于寄存器的指令架构因为须要指定源地址和目标地址,于是须要更多的指令空间(Dalvik 虚拟机的某些指令只要占据两个字节码)。通常来讲,执行一样的代码,前者须要更多的指令,然后者则须要更多的指令空间。须要更多的指令意味着须要占用更多的 CPU 时间,而须要更大的指令空间则意味着数据缓冲(d-cache)更容易失效。

此外,基于寄存器的设计则更有利于进行 AOT(AHead-Of-Time)优化。AOT 优化就是在解释型语言运行以前,就先将它编译成本地机器语言。

每一个 Android 应用都运行在单独的 Dalvik 虚拟机中(每一个 Android 进程对应一个虚拟机进程),每一个 Dalvik 虚拟机则运行在独立的 Linux 进程空间中。每一个 Android 进程之间经过进程间通讯机制(IPC,Binder 的实现机制)进行通讯,而虚拟机的线程管理、内存管理则是依赖于 Linux 内核实现的。

不一样的应用程序最后在不一样的 Linux 进程空间中运行,即便其中一个虚拟机进程意外关闭或终止,不会对其余的虚拟机进程形成影响,从而最大限度的保证了应用程序的独立运行和隔离。

Android 核心类库(Core Libraries)

一般状况下,Android 应用程序使用 Java 语言编写,其大部分 Java 语言基础功能都由 Android 核心库提供,好比基础数据结构、数学、I/O、工具、数据库、网络等库。其中大部分实现来源于 ApacheHarmony 项目,核心库的具体实现位于libcore目录中,Java 部分最终会被打包为core.jar包,通过安装,最终将被放置在目标文件系统的system\framework\目录中,当桌面启动时首先加载,做为 Java 程序的一个基础包。

libcore中的 C/C++ 代码被编译为libjavacore.a静态库,是 Java 核心库的本地代码。

另外,libcore目录中还包括部分测试用例,用来测试 Java 核心库的基本接口功能实现,在移植 Android 或者其虚拟机时,也可使用它们来测试 Java 核心库的功能。

核心库主要实现了如下 Java 基础包:

  • Java 标准API(java.*
  • Java 扩展 API(javax.*
  • 企业和组织提供的 Java 类库(org.*

以及如下 Android 的核心 API:

  • android.os
  • android.net
  • android.media

类库(Libraries)

核心类库有一系列的二进制动态连接库组成,一般使用 C/C++进行开发。与框架层服务相比,核心类库不能独立运行于线程中,而是经过系统服务将其加载到其所在的进程空间中,并经过类库提供的 JNI 接口进行调用。

下面是常见的系统类库:

  • Surface Manager 执行多个应用程序的时候,负责管理显示与存取操做间的互动,另外也负责2D 与3D 图层的无缝整合。
  • Media Framework 多媒体支持库,基于 PacketVideo 的 OpenCore,支持多种常见的音视频格式的录制和播放,支持的编码格式包括 MPEG四、MP三、H.24六、AAC、ARM。
  • SQLite 轻量级的关系型数据库。
  • OpenGL ES 基于OpenGL ES 的3D 绘图函数库。
  • Free Type 位图与向量字体的显示。
  • WebKit 网页浏览器的解析引擎。
  • SGL底层的2D图形渲染引擎。
  • SSL 在 Android 通讯过程当中实现握手。
  • Libc 从 BSD 派生出来的标准 C 函数库。

硬件抽象层(HAL)

硬件抽象层(HAL,Hardware Abstraction Layer)是介于内核和 Libraries 层中间的,抽象出来的一层结构。Android 的硬件抽象层能够以闭源源码的形式提供硬件驱动模块。HAL 存在的目的是为了把 Framework 层与 Linux 内核隔离开,使得 Android 不会过分依赖 Linux 内核,以达到“内核独立”的目的。它是对 Linux 驱动的封装,对上层服务提供统一的接口,屏蔽了底层的实现细节。

台湾著名架构师高焕堂老师对 HAL 的的理解则是“为了一些硬件提供商提出的‘专利保护’的硬件驱动程序而产生的,简而言之,就是为了避开 Linux内核的 GPL 协议的束缚”。

关于 Android 增长 HAL 层的更多内容请参考 Android ,在争议中逃离 Linux 内核的 GPL 约束

Linux 内核

Android 最先的版本是基于 Linux2.6 内核提供核心系统系统服务的,例如安全、内存管理、进程管理、网络堆栈、驱动模型等。Linux 内核做为硬件和软件之间的抽象层,屏蔽掉硬件的差别性并为上层提供统一服务。

参考文献

《疯狂 Android 讲义》
《Android 开发精要》
《Android 的设计与实现》
《Android 4高级编程(第三版)》

麦子学院 Android 架构之 HAL 的商业意义(高焕堂)

RednaxelaFX 的 虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩

罗升阳的 Dalvik虚拟机简要介绍和学习计划