Android 应用启动流程

Posted by boredream on November 17, 2017

启动应用前准备

启动电源后,先做一系列处理,主要是init进程的启动。init进程作为空户空间的第一进程,需要做很多重要工作,主要是创建zygote孵化器服务等。 Android系统中,Dalvik虚拟机、应用程序进程、系统各种关键服务进程都是由Zygote进程通过folk复制的形式来创建的,所以称之为孵化器。

Zygote会fork孵化出一个System Server,它会启动所有系统核心服务,比如ActivityManagerService、PackageManagerService等。最后Zygote还会启动第一个App,也就是Laucher应用。

手机的桌面就是这个Laucher了,它会通过PackageManager获取手机里面已经安装的各种软件,然后将图标显示出来。然后我们就可以通过点击这些图标去启动某个应用。

启动应用流程

图片来自网络
appstart1

  1. 点击桌面App图标,Launcher进程采用Binder IPC向ActivityManger发起startActivity请求;(AMS在system_server进程中,这个进程是zygote孵化的第一个重要系统进程)
  2. AMS接收到请求后,向zygote进程发送创建进程的请求;
  3. Zygote进程fork出新的子进程,即App进程;
  4. App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
  7. 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

调用链详细版流程:
appstart2

  1. 用户点击桌面图标的时候,会通过BinderIPC调用System Server中ActivityManagerService的startAcitivityLocked方法。
    (Laucher和System Server都是Zygote孵化出来的不同进程,进程间无法直接通讯,所以用Binder进行IPC)
  2. AMS再经过一系列处理(解析Intent里的信息,封装信息,判断是否有目标页面,是否有权限可以打开灯等)最后会调用Process.start方法。
  3. 然后Process会再调用Zygote,让其fork复制孵化出来一个新的目标应用进程。
  4. Zygote在孵化出应用进程后,会再实例化ActivityThread对象并调用其main方法,同时返回新进程的pid保存下来。

流程图继续下接应用启动后的初始化: 其中ActivityThread的main方法是程序启动入口
appstart3 入口代码中会新建一个线程,然后prepareMainThread将其处理为安卓中的UI主线程,主要是给这个线程绑定一个MainLooper,这个就是Handle机制的那套了,最后调用Looper.loop方法开始轮询启动主线程消息队列。
main方法中还会再做一个Application绑定处理,将进程和指定的Application绑定起来,绑定完成后,就会在App进程里保存一个Application对象了。

绑定好Application后,就可以直接startActivity启动目标进程页面了。
这里是由AMS调用realStartActivity方法开始
appstart4 ActivityThread中会发送一个LAUNCHER_ACTIVITY消息到队列中,队列消息执行,然后ActivityThread将事件交于Instrumentation具体实施,比如newActivity然后调用onCreate方法,Instrumentation 最终调用目标页面的onCreate回调方法,完成~

启动流程理解

可以把手机看做一个公司。

  1. 公司开始的时候,有个发起人(init进程)
  2. 他会起好公司名,办手续等等各种基本东西整好~
  3. 然后定下一个模式(Zygote进程),领导说我准备按照这个模式去挨个组建公司具体团队(Zygote用于Fork复制孵化进程)
  4. 公司初始,会先打造一个核心管理团队(System Server)负责统筹以后所有的业务部(App进程),核心团队包括财务啊、战略啊、CEO啊啥的,最重要的是CEO(ActivityServiceManager)
  5. 最后公司还要再整个办公地点作为门面(Laucher进程)方便CEO进行安排任务

准备好了,下面是具体做事了(打开应用某个页面等)

  1. CEO在办公室说我想做个啥啥啥事儿(从Laucher打开一个App)~
  2. 先要判断下我们有没有这个业务部门(判断应用是否存在,还会判断其他东西,这里略过)
  3. 如果不存在的话先创建一个,用上头定好的团队模式组建新业务部(Zygote孵化新App进程)
  4. 新业务部建立好后,业务部内部自己找个老大(ActivityThread),
  5. 然后自己一通整合下(ActivityThread.main方法,初始化UI线程等操作),
  6. 完了再去CEO那报备下,说我们组好啦,现在我们这个团队就是xxx业务部了(向AMS调用attachApplication)

最后就可以执行CEO下发的任务了(AMS打开某个App页面)

  1. 然后业务部老大收到消息(App的ActivityThread接收到打开页面消息请求)
  2. 业务部老大再命令干活的小弟去实施~(ActivityThread让Instrumentation处理页面相关命令)

希望最后的例子能帮你更好的理解~