Activity启动流程

原文链接:https://mp.weixin.qq.com/s/aEadJQUQLL_DsbkRZw80lQ

问:Activity启动流程中,大部分都是用Binder通讯,为啥跟Zygote通信的时候要用socket呢?

答:
1、 zygote 比 service manager 先启动;从这个意义上,他没有 service manager 可以注册,所以没法用 binder
2、 因为他们两个都是 init 进程启动的,就算先启动 service manager,也不能保证zygote 起来的时候 service manger 就已经初始化好了(这就需要额外的同步,太麻烦)
3、 这个 socket 的所有者是 root,group 是 system,只有系统权限的用户才能读写,这又多了一个安全保障(注意,这个 socket 是 Unix 域 socket,不是 internet 域 socket)
4、Zygote是通过fork生成进程的,而多线程是不允许使用fork,可能造成死锁,同时Binder又是多线程的,所以就干脆不用Binder转而使用socket了

Activity启动流程分两种,一种是启动正在运行的app的Activity,即启动子Activity。如无特殊声明默认和启动该activity的activity处于同一进程。如果有声明在一个新的进程中,则处于两个进程。另一种是打开新的app,即为Launcher启动新的Activity。后面启动Activity的流程是一样的,区别就是前面判断进程是否存在的那部分。
Activity启动的前提是已经开机,各项进程和AMS等服务已经初始化完成。

Activity启动之前

init进程:init是所有linux程序的起点,是Zygote的父进程。解析init.rc孵化出Zygote进程。

Zygote进程:Zygote是所有Java进程的父进程,所有的App进程都是由Zygote进程fork生成的。

SystemServer进程:System Server是Zygote孵化的第一个进程。SystemServer负责启动和管理整个Java framework,包含AMS,PMS等服务。

Launcher:Zygote进程孵化的第一个App进程是Launcher。

1.init进程是什么?

Android是基于linux系统的,手机开机之后,linux内核进行加载。加载完成之后会启动init进程。
init进程会启动ServiceManager,孵化一些守护进程,并解析init.rc孵化Zygote进程。

2.Zygote进程是什么?

所有的App进程都是由Zygote进程fork生成的,包括SystemServer进程。Zygote初始化后,会注册一个等待接受消息的socket,OS层会采用socket进行IPC通信。

3.为什么是Zygote来孵化进程,而不是新建进程呢?

每个应用程序都是运行在各自的Dalvik虚拟机中,应用程序每次运行都要重新初始化和启动虚拟机,这个过程会耗费很长时间。Zygote会把已经运行的虚拟机的代码和内存信息共享,起到一个预加载资源和类的作用,从而缩短启动时间。

Activity启动阶段

涉及到的概念

进程:Android系统为每个APP分配至少一个进程

IPC:跨进程通信,Android中采用Binder机制。
涉及到的类

ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ActivitySupervisor:管理 activity 任务栈

ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。

ApplicationThread:用来实现AMS和ActivityThread之间的交互。

ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理与ActivityThread进行通信的。

IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能

AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。

AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。

AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。

Instrumentation:仪表盘,负责调用Activity和Application生命周期。测试用到这个类比较多。

涉及到的进程

Launcher所在的进程

AMS所在的SystemServer进程

要启动的Activity所在的app进程

如果是启动根Activity,就涉及上述三个进程。
如果是启动子Activity,那么就只涉及AMS进程和app所在进程。

具体流程

  1. Launcher:Launcher通知AMS要启动activity。

    startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity

  2. AMS:PMS的resoveIntent验证要启动activity是否匹配。如果匹配,通过ApplicationThread发消息给Launcher所在的主线程,暂停当前Activity(即Launcher)。

  3. 暂停完,在该activity还不可见时,通知AMS,根据要启动的Activity配置ActivityStack。然后判断要启动的Activity进程是否存在?

    存在:发送消息LAUNCH_ACTIVITY给需要启动的Activity主线程,执行handleLaunchActivity

    不存在:通过socket向zygote请求创建进程。进程启动后,ActivityThread.attach

  4. 判断Application是否存在,若不存在,通过LoadApk.makeApplication创建一个。在主线程中通过thread.attach方法来关联ApplicationThread。

  5. 在通过ActivityStackSupervisor来获取当前需要显示的ActivityStack。

  6. 继续通过ApplicationThread来发送消息给主线程的Handler来启动Activity (handleLaunchActivity)。

  7. handleLauchActivity:调用了performLauchActivity,里边Instrumentation生成了新的activity对象,继续调用activity生命周期。

IPC过程:

双方都是通过对方的代理对象来进行通信。
1.app和AMS通信:app通过本进程的AMP和AMS进行Binder通信
2.AMS和新app通信:通过ApplicationThreadProxy来通信,并不直接和ActivityThread通信

参考函数流程

Activity启动流程(从Launcher开始):

第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

Launcher.startActivitySafely //首先Launcher发起启动Activity的请求

Activity.startActivity

Activity.startActivityForResult

Instrumentation.execStartActivity //交由Instrumentation代为发起请求

ActivityManager.getService().startActivity //通过IActivityManagerSingleton.get()得到一个AMP代理对象

ActivityManagerProxy.startActivity //通过AMP代理通知AMS启动activity

第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

ActivityManagerService.startActivity

ActivityManagerService.startActivityAsUser

ActivityStackSupervisor.startActivityMayWait

ActivityStackSupervisor.startActivityLocked :检查有没有在AndroidManifest中注册

ActivityStackSupervisor.startActivityUncheckedLocked

ActivityStack.startActivityLocked :判断是否需要创建一个新的任务来启动Activity。

ActivityStack.resumeTopActivityLocked :获取栈顶的activity,并通知Launcher应该pause掉这个Activity以便启动新的activity。

ActivityStack.startPausingLocked

ApplicationThreadProxy.schedulePauseActivity

第三阶段: pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

ApplicationThread.schedulePauseActivity

ActivityThread.queueOrSendMessage

H.handleMessage

ActivityThread.handlePauseActivity

ActivityManagerProxy.activityPaused

第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程)

ActivityManagerService.activityPaused

ActivityStack.activityPaused

ActivityStack.completePauseLocked

ActivityStack.resumeTopActivityLocked

ActivityStack.startSpecificActivityLocked

ActivityManagerService.startProcessLocked

Process.start //在这里创建了新进程,新的进程会导入ActivityThread类,并执行它的main函数

第五阶段: 创建ActivityThread实例,执行一些初始化操作,并绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

ActivityThread.main

ActivityThread.attach(false) //声明不是系统进程

ActivityManagerProxy.attachApplication

第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

ActivityManagerService.attachApplication //AMS绑定本地ApplicationThread对象,后续通过ApplicationThreadProxy来通信。

ActivityManagerService.attachApplicationLocked

ActivityStack.realStartActivityLocked //真正要启动Activity了!

ApplicationThreadProxy.scheduleLaunchActivity //AMS通过ATP通知app进程启动Activity

第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

ApplicationThread.scheduleLaunchActivity //ApplicationThread发消息给AT

ActivityThread.queueOrSendMessage

H.handleMessage //AT的Handler来处理接收到的LAUNCH_ACTIVITY的消息

ActivityThread.handleLaunchActivity

ActivityThread.performLaunchActivity

Instrumentation.newActivity //调用Instrumentation类来新建一个Activity对象

Instrumentation.callActivityOnCreate

MainActivity.onCreate

ActivityThread.handleResumeActivity

AMP.activityResumed

AMS.activityResumed(AMS进程)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值