1:前言
之前两篇我们简单的描述了Android智能手机的生产过程以及一个APK的生成过程,这里我们将对从按下电源键一直到启动Home应用这个过程做一个详细的描述,文章将分为两个章节;该章节描述Android系统结构;
2:Android架构
在Android的架构里提出了HAL的概念,这个HAL其实就是硬件独立的意思,Android系统不依赖于某一个具体的硬件驱动,而是依赖于HAL代码,这是因为为了避免Android源码开源性质从而公开了各厂家的源代码,这样,第三方厂商可以将自己不开源的代码封装在HAL层,仅提供二进制代码;
2.1:Android架构之应用层
内置核心应用,如Home,Setting
2.2:Android Framework层
2.2.1:其主要作用有两个:
1)为应用层提供API,那提供API的jar在哪里?在第三层的ANDROID RunTIME Core Libraries中;它叫android.jar,在这个jar中并不包含那些设置为hide的API
2)为应用层提供组件支持,这也是框架层最重要的作用;如listview,textview等;
2.2.2:Android Framework层中重要模块
1)View System: 提供组件如listview
2)Content Providers: App共享数据的数据库
3)Activity Manager: 管理应用程序生命周期并提供常用的导航回退功能
2.3: Androidy运行环境和系统运行库
系统运行库主要包括各种系统库和第三方库;Android运行环境主要是C++或者C实现的,如DVM;
2.3.1: Androidy运行环境中重要模块
在开发Android App过程中,引入的不同的Android版本,都会引入android.jar;这个jar文件就是存在Android运行环境中;
1)Core Librares是对标准java api进行了裁剪,并加入了Android特有的API,如android.jar
2)Dalvik Virtual Machine:Google并没有采用JVM,而是针对引移动设备在内存,供电,处理速度有限的情况下自己设计的Dalvik虚拟机;在Android5.0中,DVM正式推出历史舞台,取而代之的是ART
2.3.2:Android系统运行库重要模块
1)WebKit: 上层浏览器的实现
2)SurfaceManager:显示系统核心,负责绘图合成
2.3.3: DVM JVM和ART
此时我们接触到三种虚拟机,这里做个简单的介绍
1)JVM
java 虚拟机,基于栈编写,需要去栈中读写数据,所需的指令会更多,读写速度慢
Java类会被编译成一个或多个.class文件,打包成jar文件,而后JVM会通过相应的.class文件和jar文件获取相应的字节码。执行顺序为: .java文件 -> .class文件 -> .jar文件
2)DVM
2.1)Dalvik虚拟机,基于寄存器的,读写速度快;
2.2)Dalvik虚拟机由Zygote进程创建和初始化
Zygote它是一个DVM进程,同时它也用来创建和初始化DVM实例。每当系统需要创建一个应用程序时,Zygote就会fock自身,快速的创建和初始化一个DVM实例,用于应用程序的运行。
什么是fock: 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都
复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
这样做的好处就是可以共享framework层的资源,库等
2.3)DVM允许在有限的内存中同时运行多个进程
DVM经过优化,允许在有限的内存中同时运行多个进程。在Android中的每一个应用都运行在一个DVM实例中,每一个DVM实例都运行在一个独立的进程空间。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
DVM会用dx工具将所有的.class文件转换为一个.dex文件,然后DVM会从该.dex文件读取指令和数据。执行顺序为:
.java文件 –>.class文件-> .dex文件 ;
3)ART(Android Runtime)
ART与DVM的区别
DVM中的应用每次运行时,字节码都需要通过即时编译器(JIT,just in time)转换为机器码,这会使得应用的运行效率降低。而在ART中,系统在安装应用时会进行一次预编译(AOT,ahead of time),将字节码预先编译成机器码并存储在本地,这样应用每次运行时就不需要执行编译了,运行效率也大大提升。
用安装时间换运行时间的代表
后续将开设专门的文章讲解ART
2.4 : Android kernal层
遵循linux标准蒙,并增加了适用于移动设备的进程间通信,低内存killer,电源管理以及日志系统(Logger)等标准
3: Android源码下载
因为google被墙的原因,下载源码推荐通过
清华大学源码镜像 进行下载
推荐一个下载源码的链接
基本上结合清华大学的教程和推荐的链接就可以完成源码下载;
3.1)每次执行repo sync都会更新android源码,目前最新的是7.1.2
3.2)git branch -a,查看有哪些分支,方便你下载对应分支的源码
下图是我下载的7.1.2的源码结构图,是从vmware中拷贝到windows主机的
在从从vmware中拷贝到windows主机的过程中,你会发现有些文件夹是拷贝不到主机的,这是因为linux中有些系统符号不兼容windows,这里没做过多纠结。
我的虚拟机配置,硬盘务必超过120G,安装软件和下载的源码比较大
4:Android源码编译
4.1)Android源码编译会在out/target/product/generic下生成的三个镜像文件:ramdisk.img,system.img,userdata.img以及它们对应的目录树root,system,data。ramdisk.img是根文件系统,system.img包括了主要的包、库等文件,userdata.img包括了一些用户数据,android加载这3个映像文件后,会把 system和 userdata分别加载到 ramdisk文件系统中的system和 data目录下。
刷机的时候三个镜像文件及其三个目录树就是我们刷机的关键
编译指定模块
4.2)make 模块名
这种方法适合第一次编译,会把依赖的模块一并编译;
如编译电话模块
我们可以根据模块中Android.mk文件查找模块名,LOCAL_PACKAGE_NAME:=Phone
进入到源码跟目录 执行make Phone即可
4.3)mmm命令
在源码根目录编译指定模块,参数为模块的相对路径,只能在第一次编译后使用
如:mmm packgae/apps/phone
4.4) mm命令
用于在模块跟目录编译这个模块,只能在第一次编译后使用
如cd ~/package/apps/phone $ mm
编译Android上层系统源码
a:进入到源码跟目录,执行 . build/ envsetup.sh 导入预设基本
. 是shell命令,作用是从后面的文件中读取指令并执行,注意 . 后面有空格
b : 指定产品名和编译变量 执行 lunch命令
c : 编译全部源码 执行 make -j8(开启8线程开始编译)