1.手机通电
首先,手机通上电,手机设备会在BootLoader分区进行一些硬件的初始化,硬件的一些自检,类似pc电脑的bios自检。
2.BootLoader分区
自检成功了,硬件输入没有问题了,你的输入输出系统没有问题了, 你会接收用户的按键。你会接收一些组合按键,不同的组合按键会进入不同的模式。
3.进入不同模式
BootLoader模式
这个模式下可以进行线刷,通过镜像包可以直接烧写分区,通过fastboot这种工具。
recovery分区
这种模式进行系统的更新,用户数据的擦写,他会把recovery这个分区加载进来,recovery也是一个小型的Linux操作系统,他里面包含Linux内核,内核加载成功以后他会有一个init程序,init程序就是Linux系统的第一个用户进程。init也会去读取一个叫init.rc的配置文件。
这个我们要看一下源码了,recovery分区里面的init程序,他所读的init.rc
他也会去挂载一些分区,有一个分区系统,因为你要操作那些分区,进行镜像烧写,首先要知道那些分区在哪。
还有,他会去启动一个recovery程序。这也是个二进制程序,把她启动起来我们才叫进入了recovery模式。
在recovery模式我们可以进行系统更新和用户数据擦除。recovery也是定制的,有些公司也会把recovery做得非常炫。
recovery模式也可以重启,又走一遍操作,什么都不做,什么按键都没去按,就会通过正常模式加载进入到boot分区。
正常模式(boot分区)
boot分区跟recovery分区差不多,也有一个Linux内核,也有一个init程序,他这里就不是启动recovery程序进入recovery模式了,他这里启动的是zygote程序进入到android系统当中,这个init程序也去读一个init.rc,这个inint.rc是一个初始化配置文件。
4.init程序做了什么?
1.读取init.rc并执行
2.根据fstab分区表挂载分区
3.启动Zygote等/system/bin/app_process…
zygote在什么时候启动起来呢?
zygote启动起来之前我们还要说一下这个分区的问题,分区会通过一个分区表去挂载,我们可以去看一下,这边有一些很复杂的操作,但是我们只找关键字,不去纠结他们都是干嘛的。
首先文件系统他会去读取一个分区表,分区表叫fstab,fstab也是一个文件,这个文件我们也可以看一下。android源码当中,找一个文件
他列出来很多,很多都是在device下,device是设备,像华为(huawei),华硕(asus),LG(lge),每一个设备有每一个设置的分区表。这些是厂商进行定制的,这一般都是硬件工程师把这些定出来,分区表里面会去定义怎么去挂载system分区,cache分区。我们通过华为的看一眼。
左边是block,右边是目录,还有就是格式和分区的配置。目录对应的就是分区表。
分区表挂载成功就进入zygote的启动。
zygote是在哪启动的呢?
以前zygote就是直接在init.rc里面,现在把她导到另外一个配置文件里面了,因为现在很多设备也分cpu64位的,32位的,所以就不能单纯启动某一种zygote。
他会根据根据你当前的配置分四种。
我们就看32位的。32位的就是启动的bin下的app_process这个程序。
也就是我们init程序启动起来以后,看一下模拟器
切换到系统目录下
ps显示所有进程
init程序启动起来以后,他会去启动zygote,zygote调用的是system目录下bin/app_process
我们看到process有32位的和普通的app_process。
就是这个bin,init会去调用这个bin,调用app_process这个程序,然后后边还会跟一些参数。这个参数是后续一些逻辑需要用到的参数。那这个参数是在哪定义的呢?我们回到这个里边。
zygote里面有个–zygote,然后是–start-system-server,我们记住这两个参数,这两个参数就是app_process这个程序后面跟的参数。他是怎么使用者两个参数的呢?
app_process对应的源码是app_main.cpp,c语言也是看程序入口,main函数
5.Zygote进程:App_main_cpp.main()
main函数里边,首先做了几件事情,
1.解析app_process的参数,参数就是–zygote,–start-system-server
2.解析完参数,设置当前进程为zygote进程,通过设置进程名
3.然后调用AndroidRuntime.start
我们把这每一步对应源码去找一下
首先解析参数
这里边有一个while循环,循环里面好像在解析上面参数,–zygote通过strcmp对比,有没有这个参数,有的话,zygote = true,nicename = …,nicename其实就是我们的进程名字。
下面就是解析–start-system-server,解析完就把startSystemServer变为true
zygote和startSystemServer好像是两个比较重要的参数,那我们看他在哪用了。
把startSystemServer对象放到了args对象里面,args看起来跟集合似的
在做if(zygote)操作之前,设置进程名称为zygote
对应到真实设备里边就是zygote进程。
走完这一步,他开始调用AndroidRuntime.start,又跳到另外一个类当中。
第一个参数看起来像一个包名,看起来像一个java的文件,args是刚刚的集合,zygote就是true。
我们跳到AndoridRuntime.cpp的start方法
6.AndroidRuntime.cpp.start()
首先看一下AndroidRuntime.cpp.start()他做了些什么:
1.启动虚拟机startVm:因为后边要去加载java的类,虚拟机首先要启起来
2.注册JNI方法startReg:因为虚拟机里面要涉及到一些native的方法,首先要把JNI的环境搭建起来。
3.反射调用ZygoteInit.main:最后又跳出去了,最后又回到了ZygoteInit.main里边
先看看虚拟机怎么启起来的
startVm返回不等于0就是启动失败,直接退出,成功后startReg,注册JNI环境。
然后下面就是反射调用传过来的ZygoteInit的main函数。
然后进入到ZygoteInit当中
到这就是java代码了。
7.ZygoteInit.java.main()
ZygoteInit.java.main()又做了哪些事情呢?
1.启动预加载preload()
2.startSystemServer会fork并配置子进程system_server:之前都是在zygote进程里面,这里把system_server进程弄出来了。
3.通过RuntimeInit反射调用启动SystemServer.main
首先预加载,加载了什么?
预加载类,预加载资源,预加载openGl,预加载共享库,预加载文字资源,与加载webview。
安卓系统在启动过程中,可以多做一些工作,后续应用调用资源的时候就不用去加载字节码了,他可以直接用了,这些预加载就是在zygoteinit的时候加载进来的。
如果公司做一些系统启动的优化,让系统启动快一些,后续应用启动可以慢一些,那就可以在这里做工作。
再看startSystemServer,zygote通过fork又创建了一个进程system_server,他把system_server启动起来放到这个子进程里面。
8.来到SystemServer.java.main()
先看他做了什么
1.初始化Looper:Looper.prepareMainLooper()
2.加载服务的JNI库:System.loadLibrary(“android_servers”)
3.创建SystemServiceManager
4.启动Android服务
startBootstartServices
startCoreServices
startOtherServices(会执行ActivityManagerService.systemReady)
跳到run,进行一些设置以后,从这一步正式进入安卓系统服务。
到这一步,这个方法大家很熟悉,初始化一个MainLooper
只要跟android相关了,handler这个机制就不可避免要用到,handler你要去发送一些延时消息,你系统需要不断地去监测别人给你发过来的一些请求,SystemServer很忙的,SystemServer需要一直等在这。不断地等待其他的应用,api去访问一些请求,请求了我就处理。所有应用调用api的时候到要找到他,他是系统服务嘛,他是安卓系统framework层的基石,首先要有一个MainLooper不断地在这里loop。
他是systemserver的这个进程的主线程的mainlooper,先初始化出来。然后去加载安卓server的so库。这个也是需要调用他的jni的。我们普通应用调用的时候有jni,我们系统服务server调用的时候也有一些jni,他有些东西不可能自己完全用java代码实现。他需要本地代码去实现。
这个就是android_servers这个so。加载的时候不需要加libandroid和so,他是一种命名规范,他会自动去找。
然后初始化系统的context,创建一个系统服务的管理器。系统有非常多的服务,他需要有一个管理者,管理进行查找。
管理者先初始化出来,然后start services
简简单单三个方法,每个方法都对服务进行了分类。
Bootstrap里面就有:activitymanagerService、powermanagerService、LightService…
Core:核心的services,电源电池…
Other:很多android调用的service都在这里实现,WindowmanagerService、inputmanagerservice…
9.ActivityManagerService.java.systemReady()
一直到我们关注的出口ActivityManagerService.java.systemReady()
每个服务都会systemReady(),我们找的就是最后一个systemReady(),这是一个出口
出到哪了呢?我们找到ActivityManagerServer中systemReady()的实现
我们先看一下systemReady()里面做了些什么,再去找,加深印象
1.系统准备工作systemReady(),后续启动应用的准备工作
2.发送开机广播finishBooting(),关键性操作,开机广播是在ActivityManagerService.java.systemReady()发送的
3.启动桌面应用startHomeActivityLocked()
我们先去找找系统准备工作,准备工作有很多,前面可以说都是一些准备工作,一直到
准备工作完了,我们去找开机广播的操作。
启动初始化的activity,下面一行是启动桌面应用,发送开机广播是通过finishBooting(),我们找一下这个方法,到这里的时候mBooting为true
他会初始化一个intent,然后发送开机广播。
开机广播做完以后就是startHomeActivityLocked(),startHomeActivityLocked()这个里面还有非常复杂的逻辑,我们只要知道他调完startHomeActivityLocked()以后,会把launcher启起来。他肯定会去遍历当期安装的apk里面哪些是桌面属性的。