Android系统源代码情景分析(第三版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-30 02:56:15

点击下载

作者:罗升阳

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Android系统源代码情景分析(第三版)

Android系统源代码情景分析(第三版)试读:

前言

Android系统自2008年9月发布第一个版本1.0以来,截至2016年8月发布最新版本7.0,一共存在十多个版本。本书在2012年10月出版第一版时,选择了Android 2.3的源代码来分析Android系统的实现,主要是因为就当时而言,它的基础架构是最稳定的,而且也是使用最广泛的。

本书有两个特点。一是通过使用情景来分析Android源代码。这种方式不仅能使读者带着目标去阅读源代码,还能把系统各个模块有机地联系在一起来理解。二是分析的内容都是Android系统的核心基础架构。这些内容在后来的版本中,都是灵魂般地稳定存在的。例如,智能指针、硬件抽象层(HAL)、匿名共享内存(Ashmem)、Binder IPC和四大组件管理等。

因此,读者阅读了本书之后,能够自行去阅读和分析其他的Android源代码。这种“授人以鱼,不如授人以渔”的效果,正是本书所追求的目标。因为技术发展日新月异,只有掌握了本质和宗旨,才能以不变应万变。

笔者记得2010年学习Linux内核时,一开始就从当时的最新版本(2.6.32)入手,结果犹如跌入茫茫大海之中。高版本的源代码,为了解决和优化一些问题,往往会引进一些复杂的概念,以及增加一些难以理解的代码。对于初学者来说,这些复杂的概念和难以理解的代码,会阻碍他们理解代码的核心思想。后来笔者改为从0.11版本(Linux的第一个基本可以正常运行的内核版本,于1991年发布)入手,才逐渐进入状态。《Linux内核完全注释》这本书,就是以0.11版本为蓝本,对Linux内核进行分析的。

本书自第一版发布以来,经历了6次重印,得到了读者的热烈反馈和建议。基于这些反馈和建议,本书在2015年12月进行了相应的修订。在不到两年的时间内,修订版又经历了4次重印,这充分说明了读者对本书的厚爱。本次修订仍以Android 2.3版本的源代码为蓝本,并且根据读者持续的反馈和建议(http://blog.csdn.net/luoshengyang/article/details/8116866)进行。由于读者提供的反馈和建议众多,这里就不一一列出,具体可以参考上述链接。

同时,本次修订还根据最新的官方文档,优化了Android源代码编译环境搭建的内容,使读者可以简单、快速、准确地初始化好Android源代码编译环境。另外,本次修订还增加了一节内容,介绍如何为真机编译ROM。让自己编译的Android源代码运行在真机上,是一件令人兴奋的事情,一方面,可以加深对Android系统的理解;另一方面,可以随心所欲地定制系统的行为,这不仅可以满足特殊的手机使用需求,还能辅助日常的开发工作。

为了更好地帮助读者理解本书的内容,笔者创建了一个网站(http://0xcc0xcd.com)。该网站会陆续提供一些免费视频,讲解Android系统相关的知识。最后,希望本书能够继续为有志于深入研究Android的读者服务。同时也非常感谢读者的反馈和建议,你们的支持是笔者持续研究和分享Android系统技术的动力所在。本书内容

全书分为初识Android系统篇、Android专用驱动系统篇和Android应用程序框架篇三个部分。

初识Android系统篇包含三个章节的内容,主要介绍Android系统的基础知识。第1章介绍与Android系统有关的参考书籍、Android源代码工程环境的搭建方法,以及为真机编译ROM的过程;第2章介绍Android系统的硬件抽象层;第3章介绍Android系统的智能指针。读者可能会觉得奇怪,为什么一开始就介绍Android系统的硬件抽象层呢?因为涉及硬件,它似乎是一个深奥的知识点。其实不然,Android系统的硬件抽象层无论是从实现上,还是从使用上,它的层次都是非常清晰的;而且从下到上涵盖了整个Android系统,包括Android系统在用户空间和内核空间的实现。内核空间主要涉及硬件驱动程序的编写方法,而用户空间涉及运行时库层、应用程序框架层及应用程序层。因此,尽早学习Android系统的硬件抽象层,有助于我们从整体上去认识Android系统,以便后面可以更好地分析它的源代码。在分析Android系统源代码的过程中,经常会碰到智能指针,第3章我们就重点分析Android系统智能指针的实现原理,也是为了后面可以更好地分析Android系统源代码。

Android专用驱动系统篇包含三个章节的内容。我们知道,Android系统是基于Linux内核来开发的,但是由于移动设备的CPU和内存配置都要比PC低,因此,Android系统并不是完全在Linux内核上开发的,而是在Linux内核里面添加了一些专用的驱动模块来使它更适合于移动设备。这些专用的驱动模块同时也形成了Android系统的坚实基础,尤其是Logger日志驱动程序、Binder进程间通信驱动程序,以及Ashmem匿名共享内存驱动程序,它们在Android系统中被广泛地使用。在此篇中,我们分别在第4章、第5章和第6章分析Logger日志系统、Binder进程间通信系统和Ashmem共享内存系统的实现原理,为后面深入分析Android应用程序的框架打下良好的基础。

Android应用程序框架篇包含十个章节的内容。我们知道,在移动平台中,Android系统和iOS系统比的是谁的应用程序更丰富、质量更高、用户体验更好,谁就能取得最终的胜利。因此,每个平台都在尽最大努力吸引第三方开发者来为其开发应用程序。这就要求平台必须提供良好的应用程序架构,以便第三方开发者可以将更多的精力集中在应用程序的业务逻辑上,从而开发出数量更多、质量更高和用户体验更好的应用程序。在此篇中,我们将从组件、进程、消息和安装四个维度来分析Android应用程序的实现框架。第7章到第10章分析Android应用程序四大组件Activity、Service、Broadcast Receiver和Content Provider的实现原理;第11章和第12章分析Android应用程序进程的启动过程;第13章到第15章分析Android应用程序的消息处理机制;第16章分析Android应用程序的安装和显示过程。学习了这些知识之后,我们就可以掌握Android系统的精髓了。本书特点

本书从初学者的角度出发,结合具体的使用情景,在纵向和横向上对Android系统的源代码进行了全面、深入、细致的分析。在纵向上,采用从下到上的方式,分析的源代码涉及Android系统的内核层(Linux Kernel)、硬件抽象层(HAL)、运行时库层(Runtime)、应用程序框架层(Application Framework)以及应用程序层(Application),这有利于读者从整体上掌握Android系统的架构。在横向上,从Android应用程序的组件、进程、消息和安装四个维度出发,全面地剖析Android系统的应用程序框架层,这有利于读者深入理解Android应用程序的架构及运行原理。第1篇 初识Android系统

Linux内核的鼻祖Linus在回答一个Minix系统[1]的问题时,第一句话便是“Read The Fucking Source Code”。这句话虽然颇有调侃的味道,但是它道出了阅读源代码的重要性。由于Android系统的源代码是开放的,因此,认识Android系统的最好方法莫过于阅读它的源代码。

我们知道,Android系统是基于Linux内核来开发的,因此,在阅读它的源代码之前,需要掌握Linux内核的基础知识。有了Linux内核的基础知识之后,就可以下载Android源代码来阅读。阅读Android源代码时,宜采用动静结合的方法。所谓静,就是研究和思考源代码的实现;而所谓动,就是通过运行系统来证实自己对源代码的研究和思考。运行系统并不是单纯地将系统运行起来就可以了,还需要亲自动手编写一些应用程序来验证系统的行为。因此,在第1章中,我们首先介绍几本Linux内核的经典参考书籍,然后介绍如何搭建Android源代码工程环境,最后介绍如何在Android源代码工程环境中开发应用程序。

在阅读Android源代码之前,首先需要从整体上了解Android系统的架构。Android系统大致可以划分为五个层次,它们分别是Linux内核层、硬件抽象层、运行时库层、应用程序框架层和应用程序层。其中,硬件抽象层从实现到使用上涉及这五个层次,因此,在第2章中,我们通过具体的实例来介绍Android系统的硬件抽象层,以便对Android系统的实现层次有一个感性的认识。

虽然Android应用程序是使用Java语言来开发的,但是在Android应用程序框架层中,有相当多的一部分代码使用C++语言来编写,在阅读这些C++代码时,经常会碰到智能指针。Android系统的智能指针对于C++开发者来说,是比较容易理解的;但是对于Java开发者来说,就比较苦涩了。因此,在第3章中,我们继续通过具体的实例来分析Android系统的智能指针实现原理。

[1] Minix是一个类UNIX的操作系统,见http://en.wikipedia.org/wiki/MINIX。第1章 准备知识

Android系统的源代码非常庞大和复杂,我们不能贸然进入,否则很容易在里面迷失方向,进而失去研究它的信心。为了有条不紊地对Android系统的源代码进行全面、深入、细致的分析,我们需要准备一些参考书籍,搭建好Android系统源代码工程环境,以及对Android系统有一个感性认识。1.1 Linux内核参考书籍

在阅读分析Android系统的源代码时,经常会碰到诸如管道(pipe)、套接字(socket)和虚拟文件系统(VFS)等知识。此外,Android系统通过模块的形式在Linux内核中增加了一些专用的驱动程序,如Logger日志驱动程序、Binder进程间通信驱动程序,以及Ashmem匿名共享内存驱动程序等,这些都是Linux内核的基础知识,涉及进程、内存管理等内容。由于本书的重点是分析Android系统的源代码,因此,下面推荐四本介绍Linux内核基础知识的经典书籍。

(1)Linux Kernel Development

这本书的作者是Robert Love,目前最新的版本是第3版。它对Linux内核的设计原理和实现思路提供了一个总览视图,并且对Linux内核的各个子系统的设计目标进行了清晰的描述,非常适合初学者阅读。从软件工程的角度来看,这本书相当于Linux内核的概要设计文档。

(2)Understanding the Linux Kernel

这本书的作者是Daniel P.Bovet和Marco Cesati,目前最新的版本是第3版。它对Linux内核的实现提供了更多的细节,详细地描述了内核开发中用到的各种重要数据结构、算法以及编程技巧等,非常适合中、高级读者阅读。从软件工程的角度来看,这本书相当于Linux内核的详细设计文档。

(3)Linux Device Drivers

这本书的作者是Jonathan Corbet,Alessandro Rubini和Greg Kroah-Hartman,目前最新的版本是第3版。它更加注重于实际操作,详细地讲解了Linux内核驱动程序的实现原理,对分析Android系统的专用驱动模块有非常大的帮助。(4)《Linux内核源代码情景分析》

这本书的作者是毛德操和胡希明,是中国人自己编写的一本经典的Linux内核书籍。它最大的特点是从使用情景出发,对Linux内核作了详细的分析,为读者在Linux内核源代码的汪洋大海中指明方向。1.2 Android应用程序参考书籍

分析Android系统的源代码时,应该带着问题或者目标。要把问题或者目标挖掘出来,最好的方法就是在Android系统中编写应用程序。通过编写Android应用程序,我们可以知道系统提供了哪些功能,并且如何去使用这些功能,进而激发我们去了解这些功能是如何实现的。这样我们就可以获得分析Android系统源代码所需要的问题或者目标。下面推荐两本介绍Android应用程序开发的书籍。

(1)Professional Android 2 Application Development(2)《Google Android SDK开发范例大全》

这两本书的特点是都使用了大量的例子来描述如何使用Android SDK来开发Android应用程序。我们可以根据实际情况来熟悉Android应用程序的开发方法,主要掌握Android应用程序四大组件(Activity、Service、Broadcast Receiver和Content Provider)的用法。在学习的过程中,如果遇到其他问题,还可以参考官方API文档,其网址为:

http://developer.android.com/index.html1.3 下载、编译和运行Android源代码

目前,官方支持Android源代码在Ubuntu和Mac系统上编译。本书推荐使用Ubuntu系统。Ubuntu系统是一个广受称道的Linux发行版本,它具有强大的软件包管理系统,并且简单易用,官方下载地址为:http://www.ubuntu.com/。

不同版本的Android源代码对Ubuntu系统版本的要求不一样,具体如下。

● Android 6.0 (Marshmallow)~AOSP master:Ubuntu 14.04 (Trusty)

● Android 2.3.x (Gingerbread)~Android 5.x (Lollipop):Ubuntu 12.04 (Precise)

● Android 1.5 (Cupcake)~Android 2.2.x (Froyo):Ubuntu 10.04 (Lucid)

本书分析的Android源代码版本为2.3.x,因此推荐安装Ubuntu 12.04。另外,如果要安装Ubuntu 14.04,则需要安装64位版本。

如果读者习惯使用Windows系统,就可以考虑先在Windows上安装虚拟机,然后在虚拟机上安装Ubuntu系统。虚拟机推荐使用VMware,官方网站为:http://www.vmware.com/。

安装VMware时,最好选择6.0以上的版本,因为较旧版本的VMware在网络连接支持上比较差,而我们在下载Android源代码时,是必须要联网的。

安装好Ubuntu系统之后,还需要安装JDK及其他的依赖包,然后才可以正常下载、编译和运行Android源代码。接下来我们就介绍它们的安装方法[1]。

1.JDK

不同版本的Android源代码对JDK版本的要求也不一样,具体如下。

● AOSP master:OpenJDK 8

● Android 5.x (Lollipop)~Android 6.0 (Marshmallow):OpenJDK 7

● Android 2.3.x (Gingerbread)~Android 4.4.x (KitKat):Java JDK 6

● Android 1.5 (Cupcake)~Android 2.2.x (Froyo):Java JDK 5

Java JDK 5和6的官方网站为:http://www.oracle.com。

该网站为Linux提供的JDK有bin和rpm.bin两种包,推荐下载bin包。以JDK 6为例,假设下载文件为jdk-6u45-linux-x64.bin,保存在~/Downloads目录下,执行以下命令进行安装。

安装完成后,可以通过update-alternatives工具管理JDK,如下所示。

如果电脑上也安装了其他版本的JDK,则可以通过以下命令选择所需要的版本。

输入数字“1”,就可以将系统的java命令指向JDK 6安装目录下的Java文件。

输入数字“1”,就可以将系统的javac命令指向JDK 6安装目录下的javac文件。

OpenJDK 7和8的下载地址分别如下:

http://archive.ubuntu.com/ubuntu/pool/universe/o/openjdk-7/

http://archive.ubuntu.com/ubuntu/pool/universe/o/openjdk-8/

下载得到一个deb文件,可以使用dpkg命令进行安装。例如,假设下载OpenJDK 8,文件名为openjdk-8-dbg_8u45-b14-1_amd64.deb,保存在~/Downloads目录下,执行以下命令进行安装。

在安装过程中如果提示依赖缺失,则可以执行以下命令进行修复安装。

2.其他依赖包

Ubuntu 14.04的依赖包可以执行以下命令进行安装。

Ubuntu 12.04的依赖包可以执行以下命令进行安装。

Ubuntu 10.04的依赖包可以执行以下命令进行安装。

在上述依赖包中,包含了Git工具。Git是一种分布式的源代码管理工具,它可以有效、高速地对项目源代码进行版本管理[2]。Android源代码就是采用它来管理的。1.3.1 下载Android源代码

为了方便开发者下载Android源代码,Google提供了一个repo工具。这个工具实际上是一个脚本文件,里面封装了用来下载Android源代码所需要的git命令。它的下载和安装方法如下:

安装好repo工具之后,我们就可以创建一个空目录,然后进入到这个目录中执行repo命令来下载Android源代码了。

下载的过程可能会比较漫长,这取决于网络连接速度,期间还可能会碰到网络中断的现象,这时候只需要重复执行repo sync命令就可以继续下载了。

上述命令下载的是主线上的Android源代码,即最新版本的Android源代码。一般来说,主线上的源代码是正在开发的版本,它是不稳定的,编译和运行时都可能会遇到问题。如果想下载稳定的版本,就需要选择某一个支线上的代码。例如,如果我们想下载Android 2.3.1版本的代码,就可以在执行repo init命令时指定-b选项。

在本书接下来的内容中,如果没有特别声明,我们所分析的Android源代码都是基于Android 2.3版本的,并且位于~/Android目录中。1.3.2 编译Android源代码

要编译Android源代码,只需在Android源代码目录下执行make命令就可以了。

第一次编译Android源代码时,花费的时间会比较长,同时也可能会遇到各种各样的问题,这时候一般都可以通过搜索引擎来找到解决方案。例如,如果我们是在32位机器上编译主线上的Android源代码,则会碰到下面这个错误提示。

这时候可以使用关键词“You are attempting to build on a 32-bit system”在搜索引擎上找到解决方案。原来,主线上的Android源代码默认只能在64位的机器上编译,如果在32位的机器上编译,就会出现上述错误提示。如果我们仍然想在32位的机器上编译Android源代码,就可以按照下面方法来修改编译脚本。(1)打开build/core/main.mk文件,并且找到下面内容。

将第3行修改为(2)打开external/clearsilver/cgi/Android.mk、external/clearsilver/cs/Android.mk、external/clearsilver/java-jni/Android.mk和external/clearsilver/util/Android.mk这四个文件,并且找到下面内容:

将后面两行修改为

经过这样的修改之后,在32位的机器上编译Android源代码产生的问题就可以解决了。

编译成功后,可以看到下面的输出。

编译结果输出目录为out/target/product/$(TARGET_PRODUCT),其中,TARGET_PRODUCT是一个环境变量,它的默认值为generic。

Android源代码编译成功之后,可以执行以下命令将它打包成SDK。

打包成功后,可以看到下面的输出。

其中,$USER$表示当前登录到系统中的用户名。有了这个SDK包之后,我们就可以在IDE环境中开发Android应用程序了。1.3.3 运行Android模拟器

Android源代码编译成功之后,我们就可以运行它。为了方便起见,我们使用Android模拟器emulator来运行编译出来的Android源代码。执行以下命令来启动Android模拟器。

Android模拟器位于源代码根目录下的子目录out/host/linux-x86/bin中,因此,为了方便使用,我们把这个目录添加到环境变量PATH中。

启动Android模拟器需要四个文件,它们分别是zImage、system.img、userdata.img和ramdisk.img,其中,前面一个是Linux内核镜像文件,而后面三个是Android系统镜像文件。如果不带任何参数来运行emulator命令,那么Android模拟器默认使用的zImage文件是位于源代码根目录下的子目录out/host/linux-x86/bin中的kernel-qemu文件,而默认使用的system.img、userdata.img和ramdisk.img文件则位于ANDROID_PRODUCT_OUT目录中。ANDROID_PRODUCT_OUT是一个环境变量,我们将它的值设置为Android源代码编译结果输出目录;如果不设置ANDROID_PRODUCT_OUT环境变量,就需要指定上述四个文件来启动Android模拟器,如下所示。

在本书接下来的内容中,当我们运行不带参数的emulator命令时,如果没有特别声明,都是假设已经设置好PATH和ANDROID_PRODUCT_OUT两个环境变量,其中PATH环境变量包含了~/Android/out/host/linux-x86/bin目录,而ANDROID_PRODUCT_OUT环境变量指向~/Android/out/target/product/generic目录。

Android模拟器emulator启动起来后,它的界面如图1-1所示。图1-1 Android模拟器界面1.4 下载、编译和运行Android内核源代码

Android源代码工程默认是不包含它所使用的Linux内核的源代码的,因此,如果我们需要运行定制的Linux内核,就要下载它的源代码,并且对它进行编译。接下来,我们就详细介绍如何为Android模拟器下载、编译和运行Linux内核源代码。1.4.1 下载Android内核源代码

Android模拟器所使用的Linux内核源代码也是通过Git工具来管理的,不过它不像Android源代码有一个repo脚本工具来支持下载,我们需要手动执行git命令来下载。

首先在Android源代码根目录下创建一个用来保存Linux内核源代码的子目录kernel,然后调用git clone命令来下载Linux内核源代码。取决于网络连接速度,整个下载过程可能需要较长时间的等待。

下载完成之后,在kernel目录下就会看到一个空的goldfish子目录,这时候需要执行git checkout命令来指定所需要的支线代码。

在执行git checkout命令之前,可以先执行git branch命令来查看有哪些支线代码。由于我们使用Android模拟器来运行Android系统,因此,我们选择android-goldfish-2.6.29支线代码来作为Android系统的内核源代码。

执行完成git checkout命令之后,我们就可以在goldfish目录中看到Linux内核源代码了。在本书接下来的内容中,如果没有特别声明,我们分析的Android内核源代码都是基于android-goldfish-2.6.29版本的,并且位于~/Android/kernel/goldfish目录中。1.4.2 编译Android内核源代码

在编译Android内核源代码之前,我们首先要修改它的Makefile文件。Android模拟器所使用的CPU体系结构是arm的,因此,我们需要将Makefile文件中ARCH变量的值设置为arm。又由于我们是在PC上为Android模拟器编译内核的,因此,还需要在Makefile文件中指定交叉编译工具,即修改里面的CROSS_COMPILE变量的值。

打开Android内核源代码目录下的Makefile文件,并且找到下面的内容。

将后面两行修改为

Android源代码目录为我们准备了一个适用于编译Android模拟器内核的交叉编译工具,它位于Android源代码目录下的prebuilt/linux-x86/toolchain子目录中。在Makefile文件中,我们将ARCH变量的值设置为arm,表示编译的Linux内核是适用于arm体系结构的;而将CROSS_COMPILE变量的值设置为arm-eabi-,表示所使用的交叉编译工具名称是以“arm-eabi-”来作为前缀的。

为Android模拟器编译内核分为三个步骤。其中,第一步是将交叉编译工具所在的目录添加到环境变量PATH中;第二步是修改硬件配置文件goldfish_defconfig[3];第三步是执行make命令。

编译成功后,可以看到下面两行输出。

这表明编译好的Android内核镜像文件zImage位于Android内核源代码目录下的arch/arm/boot子目录中。1.4.3 运行Android模拟器

在前面1.3.3小节提到,在执行不带参数的emulator命令来启动Android模拟器时,使用的内核镜像文件zImage是位于Android源代码根目录下的out/host/linux-x86/bin子目录中的kernel-qemu文件,现在既然已经编译了自己的内核镜像文件zImage,我们就需要通过-kernel选项来启动Android模拟器,以便可以指定Android模拟器所使用的内核镜像文件。

在命令后面加一个符号“&”,表示要在后台启动Android模拟器。这样做的目的是为了能够在同一个终端运行adb[4]工具来连接Android模拟器,以便验证Android模拟器是否使用了我们自己编译的

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载