首先对Android的系统启动流程进行一个介绍,这个启动流程是贯穿Android四层架构的过程:
一、启动电源以及系统启动:引导芯片代码从固化在ROM上的预定义地方开始执行,加载引导程序BootLoader到RAM然后执行
二、引导程序BootLoader:是在Android系统启动前的程序,其主要作用是把系统OS拉起来并运行
三、Linux内核启动:在启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,会首先寻找init.rc文件并启动init进程
四、init进程启动:初始化和启动属性服务,并且启动Zygote进程
(1)创建和挂载启动所需的文件目录,
(2)解析init.rc配置文件并启动Zygote进程
(3)初始化和启动属性服务
五、Zygote进程启动:创建java虚拟机并为java虚拟机注册JNI方法,创建服务端Socket启动SystemServer进程
(1)创建AppRuntime并调用start方法,启动Zygote进程
(2)创建java虚拟机并为其注册JNI方法
(3)通过JNI调用ZygoteInit的main函数进入Zygote的java框架
(4)通过registerZygoteSocket方法创建服务器端Socket通过runSelectLoop方法等待AMS的请求来创建新的应用程序进程
(5)启动SystemServer
六、SystemServer进程启动:启动Binder线程池和SystemServerManager,并启动各种服务。
(1)创建Binder线程池,与其他进程通信
(2)创建SystemServiceManger对系统服务进行创建,启动和管理
(3)启动3种系统服务
七、Launcher启动:被SystemServer进程启动的AMS会启动Launcher,启动后会将以安装应用的快捷图标显示到界面上
一、启动电源
当启动电源键的时候硬件电路会产生一个确定的复位时序,保证CPU是最后一个被复位的器件,如果CPU第一个被复位,则当CPU复位后开始运行时,其他硬件内部的寄存器状态可能还没有准备好比如磁盘或者内存,那么久可能出现外围硬件初始化错误。当正确完成复位后,CPU开始执行第一条指令,引导芯片代码从预定义的地方开始执行。
二、引导程序BootLoader
这时加载引导程序BootLoader到RAM中然后执行,该引导程序BootLoader是在Android操作系统运行前的一个小程序主要作用是把系统来起来运行。该指令所在的内存地址是固定的,这由CPU的制造者指定。不同的CPU可能会从不同的地址获取指令,但这个地址必须是固定的,这个固定地址所保存的程序往往被称为引导程序(BootLoader)。
对于Android而言,最常用的bootloader还是U-boot,其作用就是初始化硬件设备,比如网口、SDRAM、RS232等,并提供一些调试功能,比如像NAND Flash写入新的数据,这可用于开发过程中的内核烧写、等级等。U-boot的启动过程大致上可以分为两个阶段:
第一阶段汇编代码:U-boot的第一条指令从cpu/armXXX/start.S文件开始
第二阶段C代码:从文件/lib_arm/board.c的start_armboot()函数开始。
三、启动Linux内核层
Linux启动分为3个步骤分别是:
1.自解压过程
2.设置ARM处理器的工作模式
3.C代码进行Android的初始化全部工作。
Linux内核启动的第一个阶段是从start_kernel函数开始的。start_kernel是所有Linux平台进入系统内核初始化后的入口函数,它主要完成剩余与硬件平台的相关初始化工作,当内核启动的时候:设置环境、开启MMU建立列表、初始化串口、加载驱动、挂载根目录系统。
挂载根目录的原因是启动第一个init进程时必须以根目录系统为载体,在内核完成系统设置后,会首先在根文件系统中寻找init.rc并启动init进程,当Linux找到init服务后会让init负责后续初始化系统使用的工作。
严格上讲,Android系统实际上是运行于Linux内核之上的一系列"服务进程",并不算一个完成意义上的"操作系统";而这一系列进程是维持Android设备正常工作的关键,所以它们肯定有一个"根进程",这个"根进程"衍生出了这一系列进程。这个"根进程"就是init进程。
四、启动init进程
init进程是Android系统启动的第一个进程,进程号为1,作为第一个进程需要创建Zygote(孵化器)和属性服务等。Android系统启动流程的前几步,以引入init进程为主。它通过解析init.rc脚本来构建出系统的初始形态。其他的"一系列"Android系统进程大部分也是通过"init.rc"来启动的。init进程主要用来初始化和启动属性服务,也用来启动Zygote进程。
1.init开始负责初始化。
在init进程的入口函数内创建和挂载启动所需的文件目录,其中挂载了五种文件系统:tmpfs、devps、proc、sysfs和selinuxfs。
(1)property_init():对属性服务进行初始化
(2)singl_handler_init():设置子进程信号处理函数,当Zygote进程异常退出时会发出一个信号,init进程就会调用该函数接收信号并处理,处理过程是调用handler_singal找到Zygote进程移除信息并重启Zygote服务带有onestart选项的服务。
(3)start_property_service():启动属性服务
2.解析init.rc配置文件。
Android8.0对init.rc进行了拆分,使每个服务对应一个rc文件,init.rc文件是一个重要的文件由Android初始化语言编写的脚本,包含五种类型语句Action、Command、Service、Option、Import。
Zygote在init.zygoteXX.rc中定义。通过Service来通知init进程创建Zygote进程,Service类型语句采用ServiceParser来进行解析。
ServiceParser会通过两个函数对Service语句进行解析:
(1)ParseSection():解析Service的rc文件用来搭建Service的架子
(2)ParseLineSection():用于解析子项
在ServiceParser中会根据参数构造出一个Service对象,在解析完所有数据之后会通过ServiceManager的AddService(),将Service对象加入Vector类型的Service链表。
3.init启动Zygote的Service。
在init.rc中有一个命令class_start,对应的函数为do_class_start(),在init.rc中会通过该命令启动classname为main的Service,Zygote的classname就是main。在do_class_start()中通过ForEachServiceInClass()来遍历Service链表找到Zygote,并执行StrartIfNotDisabled函数对该Service执行Start()进行启动。
在Start函数里会判断Service是否已经运行,如果已经运行则不启动。还需要判断需要启动的Service对应的执行文件是否存在,如果不存在就不启动。如果子进程没有启动就会调用fork函数创建子进程,调用execve(),Zygote的Service子进程就会被启动。就会进入该Service的main函数里,也就是Zygote的执行路径下的文件app_main里的main(),在这个函数里会调用runtime.start(“com.android.internal.os.ZygoteInit”,args,zygote),就会启动Zygote。
4.init启动属性服务。
同时init还会进行属性服务的初始化以及启动,当init进程启动的时候就会启动属性服务,属性服务的主要功能是即使系统或者软件重启还能够根据之前的注册表中的记录进行相应的初始化工作,在启动时就会分配内存用来存储属性。
通过property_init()、start_property_service()进行初始化以及启动属性服务。在内部创建非阻塞的Socket将引用赋给property_set_fd并通过listen()对property_set_fd进行监听,这样创建的Socket就成为了Server也就是属性服务,将property_set_fd发入epoll中,用epoll来监听property_set_fd,当有数据到来时init进程将调用handle_property_set_fd()进行处理。
系统属性分为两种类型:一种是普通属性,还有一种是控制属性,所以handle_property_set函数分为两个处理分支进行处理。property_set主要对普通属性进行修改,首先判断属性是否合法,如果合法就从属性控件上查找该属性,如果属性存在就更新属性值否则就添加该属性。
五、Zygote进程启动
在Android系统中DVM,ART,应用程序进程以及运行系统的关键服务SystemServer都是由Zygote创建的,Zygote通过fork的形式来创建应用程序进程和SystemServer进程,Zygote进程在启动时会创建DVM或者ART,因此通过fork而创建的应用程序和SystemServer可以在内部获取一个DVM或者ART的实例。
在init.rc里使用了Import类型语句引入Zygote启动脚本,但是不会直接引入一个固定的文件而是根据属性ro.zygote的内容来引入不同的文件比如32位文件和64位文件。
-(main)-> app_main -(start)->AndroidRuntime -(main)-> ZygoteInit -(registerServerSocket)->ZygoteServer
init文件启动Zygote是在app_main内通过AndroidRuntime的start()实现的。因为Zygote是通过fock自身来创建进程,所以它的子进程都可以进入app_main的main(),为了可以区分main()运行在哪一个进程,需要判断参数arg是否包含了--zygote,如果包含就说明是运行在Zygote进程中。
当在Zygote进程中就会调用AndroidRuntime实现的start(),在该函数内会通过startVm()来创建虚拟机,startReg()为java虚拟机注册JNI方法,通过JNI方法调用ZygoteInit的main(),因为当前运行在Native层,但是ZygoteInit的main()是java编写的所以需要通过JNI来调用java,JNI调用ZygoteInit的main方法使Zygote进入java框架层。
ZygoteInit主要做了:
1.通过registerServerSocket()创建一个Server端的Socket,这个socket用于等待ActivityManagerService请求Zygote来创建新的应用程序进程,当Zygote进程将SystemServer进程启动之后就会在这个服务端上的Scoket等待AMS请求Zygote进程来创建新的应用程序。
2.通过preload()预加载类和资源
3.通过startSystemServer()启动SystemServer进程,该进程会启动系统的服务
4.通过zygoteServer.runSelectLoop()等待AMS请求创建新的应用进程
在ZygoteInit中有startSystemServer(),它会创建一个args数组来保存启动Systemserver的启动参数,然后将args封装成Arguments对象供forkSystemServer()调用,在forkSystemServer()内部会通过一个本地方法fork当前进程创建一个子进程,也就是SystemServer进程,会通过pid的值是否为0来判断当前代码是否运行在新创建的子进程中。
启动SytemServer之后会执行ZygoteServer的runSelectLoop(),在该函数内会获得之前创建的Socket的fd字段,然后无限循环等待AMS请求Zygote进程创建新的进程,当AMS向Zygote进程发送了一个创建应用进程的请求,ZygoteConnection.runOnce()会创建一个新的应用进程,并在创建之后将这个连接从socket连接列表peers和fd列表fds中删除。
1.peers列表是存储通过acceptCommandPeer得到的ZygoteConnection类。
2.fds列表是存储通过mServerSocket.getFileDescriptor()获得的socket的fd字段
六、SystemServer进程
ZygoteInit -(onZygoteInit)->AndroidRuntime
ZygoteInit -(applicationInit)-> RuntimeInit
ZygoteInit -(run)->MethodAndroidCaller -(main)->SystemServer
SytemServer进程主要创建系统服务,SystemServer进程复制了Zygote进程的地址空间,在ZygoteInit中会调用handleSystemServerProcess()来启动SystemServer进程,还调用本地方法启动了Binder线程池,让SystemServer可以用Binder与其他进程进行通信。这个本地方法对应的就是AndroidRuntime的子类AppRuntime,在app_main中定义的onZygoteInit()。
在ZygoteInit中调用了RuntimeInit的applicationInit(),这个方法通过反射取得SystemServer的main()返回给ZygoteInit。在ZygoteInit进程中会捕获MethodAndroidCaller异常并调用caller.run()让SystemServer的进程进入SystemServer的main()。
在SystemServer的main()中会new一个SystemServer对象启动run方法,在run方法内会创建Looper、加载动态库、创建系统的Context、创建SystemServiceManger、并启动引导服务,核心服务,其他服务。SystemServerManger会对系统服务进行创建、启动、生命周期管理。
七、Launcher启动
-(startOtherService)->SystemServer -(systemReady)->AMS -(resumeFocusedStack)-> ActivityStackSupervisor-(resumeTopActivity)->ActivityStack
系统的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序就是Launcher,在Launcher的启动过程中会请求,PackageManagerService返会系统中已经安装的应用程序的信息,并封装成一个快捷图标显示在系统屏幕上。Launcher代表系统的桌面,作为系统的启动器用于启动相应的应用程序,显示和管理应用程序的图标和组件。Launcher是用工作区的形式来显示系统安装的应用程序的快捷图标,每个工作区都是用来描述一个抽象桌面,由n个屏幕组成,每个屏幕又分为n个单元格,每个单元格用来显示一个应用程序的快捷图标,Launcher完成启动后,作为桌面会显示应用程序图标,与应用程序开发有所关联,应用程序图标是用户进入应用程序的入口。
SystemServer进程在启动的时候会启动PackageManagerService,启动后会将系统中的应用程序安装完成。AMS会将Launcher启动起来。AMS的systemReady()作为Launcher的入口,判断mFactoryTest的模式是否为低级工厂模式,如果是则返回false,如果否就创建Launcher所需的Intent并交给startHomeActivityLocked(),该方法会启动该应用程序即Launcher。因为Launcher的AndroidManifest文件中的intent-filter设置的category为HOME,使Launcher为主Activity。
在launcher的onCreate()方法里:
1.通过LauncherAppState.setLauncher()将Launcher对象传入,并在方法内部通过initialize()将传入的Launcher对象封装成一个弱引用对象。
2.会调用startLoad(),该方法在LauncherModel里创建具有消息循环的线程HandlerThread对象、同时将创建的Handler对象以及LoaderTask对象,并将Handler和LoaderTask传入HandlerThread的Looper,这里Handler的作用就是向HandlerThread发出消息而LoaderTask则是作为消息被发送。
LoaderTask类实现了Runnable接口,当其描述的消息被处理的时候就会调用它实现的run方法:加载工作区信息,绑定工作区信息,加载系统已经安装的应用程序信息等。
在Luncher里调用setApps()将包含信息列表的apps传进去。并在AllAppsContainerView中将包含应用信息的列表设置给mApps,会有一个onFinishInflate()用来显示App列表通过向AllAppsRecyclerView()传入mApps和Adapter就可以显示应用程序快捷图标的列表。