Android源码体积很是庞大,由Dalvik虚拟机、Linux内核、编译系统、框架代码、Android定制C库、测试套件、系统应用程序等部分组成,在编译Android源码以前,必需要先掌握Android源码的组成。linux
在Android源码中,按照不一样功能代码被放在不一样的目录下:android
目录web |
描述sql |
bionicshell |
针对Android系统定制的仿生标准C库、连接器等所在目录,Android系统并无使用Linux的glibc库,bioinc C库针对嵌入式系统作了优化,添加了一些Android特定的函数API同时大大减小库的体积,也避免了LGPL版权的问题。数据库 |
bootableapache |
Android系统引导启动代码,用来引导系统、更新系统、恢复系统。windows |
build浏览器 |
Android的编译系统目录,里面包含大量的Makefile,用来编译目标系统、Host主机开发环境等。bash |
cts |
兼容性测试工具目录。 |
dalvik |
Dalvik虚拟机,Android系统得以运行的虚拟执行环境。 |
development |
程序开发所须要的模板和工具。 |
external |
Android系统使用的其它开源代码目录,如jpeg图片解码开源库、opencore开源代码等。 |
frameworks |
框架层代码,frameworks/base目录下存放目标系统的框架库,frameworks/policies/base下存放应用程序框架代码。 |
hardware |
HAL(Hardware Abstraction Layer)硬件抽象层代码。 |
kernel |
Linux内核目录,默认下载的Android源码里没有,需单独下载。 |
packages
|
Android系统级应用程序源码目录,如摄像应用、电话应用等。 |
prebuilt |
主机编译工具目录,如arm-linux-gcc交叉系统工具链等。 |
sdk |
SDK及模拟器。 |
system |
init进程、蓝牙、无线WIFI工具、uevent进程目录。 |
devices |
厂商设备配置目录,针对不一样设备,由不一样的子目录来分别管理,用来裁剪实现不一样设备上Android目标系统。 |
在external目录下存放着大量的外部开源代码:
外部开源项目 |
描述 |
外部开源项目 |
描述 |
aes |
AES加密 |
libxml2 |
xml解析库 |
apache-http |
网页服务器 |
make |
|
asm |
|
netbeans-visual |
|
bluez |
蓝牙相关、协议栈 |
netcat |
simple Unix utility which reads and writes dataacross network connections |
ccache |
|
netperf |
网络性能测量工具 |
clearsilver |
|
neven |
看代码和JNI相关 |
dbus |
低延时、低开销、高可用性的IPC机制 |
opencore |
多媒体框架 |
dhcpcd |
DHCP服务 |
openssl |
SSL加密相关 |
dropbear |
SSH2的server |
oprofile |
OProfile是Linux内核支持的一种性能分析机制 |
eclipse |
|
ppp |
pppd拨号命令,好像尚未chat |
elfcopy |
复制ELF的工具 |
protobuf |
a flexible, efficient, automated mechanism for serializing structured data |
elfutils |
ELF工具 |
qemu |
arm模拟器 |
embunit |
Embedded Unit Project |
safe-iop |
functions for performing safe integer operations |
emma |
Java代码覆盖率统计工具 |
sdl |
|
esd |
Enlightened Sound Daemon,将多种音频流混合在一个设备上播放 |
skia |
skia图形引擎 |
expat |
Expat is a stream-oriented XML parser |
sonivox |
sole MIDI solution for Google Android Mobile Phone Platform |
fdlibm |
FDLIBM (Freely Distributable LIBM) |
sqlite |
数据库 |
Flex |
|
srec |
Nuance 公司提供的开源连续非特定人语音识别 |
freetype |
字体库 |
strace |
trace工具 |
gdata |
google的无线数据相关 |
swing-worker |
|
diflib |
|
swt |
|
googleclient |
google用户库 |
tagsoup |
TagSoup是一个Java开发符合SAX的HTML解析器 |
icu4c |
ICU(International Component for Unicode)在C/C++下的版本 |
tcpdump |
抓TCP包的软件 |
iptables |
防火墙 |
tinyxml |
TinyXml is a simple, small, C++ XML parser |
Jdiff |
generate a report describing the difference between two public Java APIs |
toolchain |
|
jfreechart |
|
tremor |
I stream and file decoder provides an embeddable,integer-only library |
jpeg |
jpeg库 |
webkit |
浏览器核心 |
kxml2 |
|
wpa_supplicant |
无线网卡管理 |
libffi |
libffi is a foreign function interface library. |
yaffs2 |
yaffs文件系统 |
libpcap |
网络数据包捕获函数 |
zlib |
a general purpose data compression library |
在packages/app目录下存放着大量系统级应用程序,咱们能够拿到这些应用程序代码分析、理解,编写出效率更高,性能更好的应用:
系统应用程序 |
描述 |
AlarmClock |
闹钟 |
Browser |
浏览器 |
Calculator |
计算器 |
Calendar |
日历 |
Camera |
摄像头 |
Contacts |
联系人 |
|
邮件 |
GoogleSearch |
Google搜索 |
HTML Viewer |
浏览器附属界面,被浏览器应用调用,同时提供存储记录功能 |
IM |
即时通信,为手机提供信号发送、接收、通讯的服务 |
Launcher |
Android的桌面 |
Mms |
彩信业务 |
Music |
音乐播放器 |
PackageInstaller |
应用程序安装、卸载器 |
Phone |
电话应用 |
Settings |
系统设置 |
SoundRecorder |
录音机 |
Stk |
短信接收和发送 |
Sync |
同步数据 |
Updater |
更新 |
VoiceDialer |
语音识别通话 |
在package/providers目录下存放的是系统级内容提供器(Content Provider):
系统内容提供器 |
描述 |
CalendarProvider |
日历提供器 |
ContactsProvider |
联系人提供器 |
DownloadProvider |
下载管理提供器 |
DrmProvider |
DRM受保护数据存储服务,建立和更新数据库时调用 |
GoogleContactsProvider |
谷歌联系人提供器 |
GoogleSubscribedFeedsProvider |
Google同步功能 |
ImProvider |
即时通信提供器 |
MediaProvider |
媒体提供器、提供存储数据 |
SettingsProvider |
系统设置提供器 |
SubscribedFeedsProvider |
|
TelephonyProvider |
彩信提供器 |
按照Android官方网站给出的步骤,编译Android源码过程以下:
Ø 初始化编译环境
在编译Android以前,编译系统须要加载一些编译脚本命令到环境变量中,经过下面的指令来初始化编译环境:
在执行完上述命令后,能够经过执行help命令来查看全部加载的命令。
经常使用脚本命令:
脚本命令 |
描述 |
Help |
帮助信息,打印全部命令 |
add_lunch_combo |
添加新目标编译项 |
print_lunch_menu |
打印全部目标编译项 |
lunch |
选择目标编译项 |
m |
从源码树顶级目录向下编译源码,至关于执行make |
mm |
从当前目录向下编译源码 |
mmm |
从指定目录向下编译源码,一般用来编译某个模块 |
cgrep |
从全部的C,C++文件里查找指定字符串 |
jgrep |
从全部的Java文件里查找指定字符串 |
Ø 选择编译选项
因为Android源码是一个开源的系统,然要匹配不少设备产品,也就是说一个版本的Android源码,能够编译出针对不一样产品的系统。经过选择一个目标编译项,来决定编译出针对哪一个产品的系统,咱们能够经过执行下面的命令来选择要编译的目标系统:
经过lunch命令可知,让用户输入目标编译项,咱们能够选择编译项前的数字,也能够直接输入编译项的名字。
…接前面终端输出信息
由上面结果可知,当用户输入:1或generic-eng时,会打印出上面的信息,这些信息是Android的编译系统必须依赖的环境变量,只有设置了这些变量,才能决定Android系统如何编译,编译成什么平台,编译成什么版本。
目标编译项格式:产品名-版本变量名,目标编译项能够由用户添加(见xxx章节),产品名是目标设备的产品名,由厂商本身定义,generic产品是通用产品,它是Android默认设备的产品名,它包含了经常使用的手机的全部功能,本身定义的产品能够继承generic,并重写它的功能,达到定制产品的目的(见xxx章节)。
版本变量名由如下几个组成:
其中,eng版本产品其实就是手机行业的工程机,它不是最终销售的产品,而是产品在定型下线以前放出的一些测试用机器,用于检测和标准的认证,这些工程机上安装的系统为eng版本,user是最终用户机发行版本,userdebug是调试版本,它比用户机添加了一些调试功能,如adb调试默认打开等,tests测试版本,该版本会安装一些测试程序,用于测试系统。
上述四种版本的分类做用,其一:用于区分目标系统里的全部的应用程序、库、测试程序等,将它们打上对应的Tags,当选择一个版本编译时,拥有对应Tags及低级别的Tags的程序会被编译安装到目标设备上,应用程序Tags的包含关系以下图:。其二:根据不一样的版本,系统会有不一样的设置,如adbd在用户版本里是关闭的,在其它版本中是默认打开的,ro.secure属性用户版本值为1,其它版本为0。
Ø 编译源码
执行完前面的命令后,咱们能够输入make指令开始编译目标系统:
编译的时长与机器的硬件配置有关系,当第一次编译时通常须要数小时以上。后续编译,相对快多了,编译完的效果以下图所示:
经过上面的输出信息可知,Android系统编译完后,在out/target/product/generic/目录下产出了三个文件:system.img、ramdisk.img、userdata.img。
其实,Android手机的ROM包(一般为update.zip文件),就是主要由上述三个映像文件构成的:
ROM包文件 |
说明 |
android-info.txt |
ROM版本及刷写配置信息 |
boot.img |
Linux内核zImage、ramdisk.img |
system.img |
Android系统映像 |
userdata.img |
用户数据映像 |
… |
其它映像 |
只要咱们拿到手机的源码,就能够本身编译出本身的ROM,不过,通常手机厂商不会开源本身产品源码,都是第三方爱好者本身下载,修改编译的,如:业界著名的CM团队:http://www.cyanogenmod.com/。
因为彻底编译Android系统耗时很长,而且Android源码由不少模块组成,咱们能够经过下面一些编译命令来减小编译时间:
编译命令 |
说明 |
make snod |
打包生成system.img,不检查依赖关系 |
make bootimage |
打包生成ramdisk.img |
mmm |
指定编译某个目录下的模块 |
上述三个命令常常在咱们源码开发时使用,但愿你们记住。
Android使用Linux内核,在源码级开发过程当中,有时要修改内核代码,一般内核代码是和目标设备相关的,咱们使用的是模拟器的内核,即便没有硬件设备也能够完成实验。
编译Android的内核,须要用到交叉编译器,咱们能够直接使用Android源码里自带的arm-eabi-gcc编译器,为了编译出针对模拟器的内核(模拟器的CPU为Goldfish),还要配置内核(若是不知道如何配置内核,请读者阅读内核裁剪相关资料),为了方便咱们编译Goldfish内核,咱们编写了以下脚本,方便编译。
添加以下内容:
@ /home/linux/android/android_source/kernel/goldfish/build_kernel.sh
注:当Andorid源码目录发生改变时,要修改PATH的路径,让它指向对应的交叉编译器。
给脚本加上可执行权限,而后执行该脚本:
内核编译完成如图x-x所示:
图 内核编译结果