一个startActivity请求是如何穿越进程边界
整个过程涉及两次Binder IPC调用和三次进程的协作。下图清晰地展示了整个过程的核心流程与交互:
第一步:从你的App进程到system_server(第一次Binder IPC)
当你在App中调用 startActivity()
时,旅程开始了
- 应用层调用:
// 在你的App进程内 startActivity(new Intent(this, TargetActivity.class));
这个调用会进入
Activity
类,最终通过Instrumentation.execStartActivity()
Binder代理封装:
Instrumentation
会通过ActivityTaskManager.getService()
获取一个IActivityTaskManager
对象。这个对象看起来像是一个本地对象,但它实际上是一个 Binder代理(Proxy)
○ 你的App进程:持有IActivityTaskManager
的 Proxy 对象
○ system_server进程:有一个对应的IActivityTaskManager
的 Stub 对象(具体实现是ActivityTaskManagerService
)数据打包与传输:
○ Proxy 对象会将方法名(startActivity
)、你的应用身份(ApplicationThread
,后面会讲)、Intent、参数等信息打包成一个Parcel
对象
○ 通过Binder驱动
,这个请求被发送到system_server
进程system_server端处理:
○Binder驱动
将请求传递给system_server
进程中的目标Binder对象
○ActivityTaskManagerService(ATMS)
(AMS的一部分)的onTransact
方法被调用,它从Parcel
中解包数据,并执行真正的startActivity
逻辑
至此,第一次Binder调用完成。控制权从你的App进程转移到了system_server进程的AMS/ATMS中
第二步:AMS在system_server中的决策与处理
现在,AMS/ATMS掌握了主动权,它会做一系列繁重的工作:
- 权限检查:检查你的App是否有权限启动这个Activity
- Activity解析:如果Intent是隐式的,会通过
PackageManagerService
解析出具体的目标Activity - 栈管理:决定目标Activity应该放在哪个任务栈(Task)的什么位置
- 进程检查:检查目标Activity所属的应用进程是否已经启动
○ 如果目标进程已存在:直接进入下一步
○ 如果目标进程不存在:AMS会请求Zygote
进程通过fork()
创建一个新的应用进程
第三步:从system_server到目标App进程(第二次Binder IPC)
现在AMS需要通知目标App进程去创建并运行对应的Activity。这需要另一个Binder调用,但方向反了过来
- Binder桥梁:IApplicationThread
为了与应用进程通信,AMS需要每个应用进程在启动时都向AMS“注册”一个回调接口。这个接口就是IApplicationThread
○ 目标App进程:有一个IApplicationThread
的 Stub 对象(具体实现是ActivityThread
内部的ApplicationThread
类)
○ system_server进程:持有目标进程的IApplicationThread
的 Proxy 对象 - AMS发起调用:
AMS通过它持有的那个IApplicationThread
Proxy 对象,调用其scheduleLaunchActivity()
方法 - 第二次Binder传输:
○ 同样,方法名和参数(Activity信息、Intent、配置等)被打包成Parcel
○ 通过Binder驱动
,这个请求被发送到 目标App进程
第四步:目标App进程中的Activity创建
- 目标进程接收请求:
○ 目标进程中的ApplicationThread
(Stub)的scheduleLaunchActivity
方法被调用
○ 但请注意:Binder调用是运行在Binder线程池中的,不能直接操作UI - 线程切换:Handler机制:
ApplicationThread
不会直接创建Activity,而是会向主线程的Handler
(即H
,在ActivityThread
中)发送一个LAUNCH_ACTIVITY
消息。这样就把控制权从Binder线程交还给了主线程 - 主线程处理:
主线程的Handler
收到消息后,调用ActivityThread
的handleLaunchActivity()
方法。在这里,目标App进程会执行经典的Activity创建流程:
○ 创建Activity
对象(通过反射)
○ 调用Activity.attach()
方法,建立上下文、创建PhoneWindow
○ 调用onCreate()
、onStart()
,最终调用onResume()
,使Activity进入运行状态
总结与核心角色回顾
步骤 | 发起者 | 接收者 | 核心Binder接口 | 目的 |
---|---|---|---|---|
1 | 你的App进程 | system_server | IActivityTaskManager | 请求AMS启动一个Activity |
2 | system_server (AMS) | 目标App进程 | IApplicationThread | 指示目标进程创建并运行指定的Activity |
关键点:
- 两次Binder:整个过程是两次方向相反的Binder IPC
- 三个进程:你的App进程 -> system_server -> 目标App进程。system_server是中枢指挥系统
- 代理与桩:Binder的Proxy-Stub模式是跨进程通信的基石
- 线程切换:在应用进程内,通过Handler将Binder线程的请求转发到主线程执行UI操作