App 启动流程

66 阅读6分钟

原文:blog.csdn.net/u010257931/…


App 启动流程(一):从点击到请求 Zygote 笔记

一、 核心重点提炼 (Key Takeaways)

  1. 四大核心进程:App 启动至少涉及四个进程的协作:

    • Launcher 进程:用户交互的起点,本质是一个 App,负责显示桌面图标并监听点击事件。
    • SystemServer 进程:Android 系统的核心服务中枢,ActivityTaskManagerService (ATMS, 在旧版中是 AMS) 在此运行,是启动流程的“总指挥”。
    • Zygote 进程:所有 App 进程的“孵化器”,负责 fork() 创建新的 App 进程。
    • App 进程:最终运行我们应用代码的目标进程。
  2. 两种通信机制:整个流程依赖两种不同的 IPC (进程间通信) 方式:

    • Binder:用于 Launcher -> SystemServer 以及 SystemServer <-> App 进程之间。这是 Android 中最主要、功能最丰富的 IPC 机制,适用于复杂的业务通信。
    • Socket:仅用于 SystemServer -> Zygote 之间。这是一种更底层、更简单的通信方式,非常适合 system_serverZygote 发送创建进程的简单指令。
  3. 启动的责任链:请求的传递是一个清晰的责任链条。

    • 用户点击,LauncherActivity 响应。
    • ActivitystartActivity() 调用并非直接执行,而是通过 Instrumentation 类作为“中间人”。
    • Instrumentation 将请求通过 Binder 发送给 SystemServer 进程中的 ActivityTaskManagerService (ATMS)。
    • ATMS 内部经过 ActivityStartController -> ActivityStarter 等一系列的检查和准备。
    • 最终发现需要创建新进程时,通过 Process.start() 调用,切换到 Socket 通信,向 Zygote 发出指令。
  4. 最终目标:第一阶段所有工作的最终目标,是向 Zygote 进程成功发送一条创建新进程的 Socket 消息,并明确告知新进程的入口点是 android.app.ActivityThread

二、 详细流程图

sequenceDiagram
    participant Launcher Process
    participant System Server Process (ATMS)
    participant Zygote Process

    Note over Launcher Process: 用户点击桌面 App 图标
    Launcher Process->>Launcher Process: onListItemClick() -> startActivity()
    Launcher Process->>Launcher Process: startActivityForResult() -> mInstrumentation.execStartActivity()

    Note over Launcher Process, System Server Process (ATMS): --- Binder IPC ---
    Launcher Process->>System Server Process (ATMS): ActivityTaskManager.getService().startActivity()

    System Server Process (ATMS)->>System Server Process (ATMS): startActivityAsUser()
    System Server Process (ATMS)->>System Server Process (ATMS): ActivityStartController.obtainStarter().execute()
    System Server Process (ATMS)->>System Server Process (ATMS): ActivityStarter.startActivityInner()
    System Server Process (ATMS)->>System Server Process (ATMS): RootWindowContainer.resumeFocusedTasksTopActivities()
    System Server Process (ATMS)->>System Server Process (ATMS): ActivityTaskSupervisor.startSpecificActivity()

    Note over System Server Process (ATMS): 发现目标进程不存在, 准备创建...
    System Server Process (ATMS)->>System Server Process (ATMS): Process.startProcessLocked()
    System Server Process (ATMS)->>System Server Process (ATMS): Process.start()

    Note over System Server Process (ATMS), Zygote Process: --- Socket Communication ---
    System Server Process (ATMS)->>Zygote Process: ZygoteProcess.startViaZygote()<br/>(发送包含 "android.app.ActivityThread" 等参数的 Socket 消息)

    Zygote Process->>Zygote Process: fork() a new App Process
    Note left of Zygote Process: (后续流程进入第二篇)

三、 详细流程笔记梳理

阶段一:Launcher 进程 - 发起启动请求

  1. 起点:用户点击桌面图标。这个桌面是由 LauncherActivity 构成的,图标点击事件被 onListItemClick 捕获。
  2. 意图创建:通过 intentForPosition() 方法创建一个包含目标 App 包名和类名的 Intent
  3. 调用 startActivity:
    • LauncherActivity 调用 startActivity(),这会层层深入到 Activity#startActivityForResult()
    • 关键点Activity 本身不具备与系统服务直接通信的能力。它委托其成员变量 mInstrumentation (一个 Instrumentation 实例) 来完成这个任务。
  4. Instrumentation.execStartActivity():
    • 这是 App 框架层到系统服务层的桥梁
    • 它内部通过 ActivityTaskManager.getService() 获取到 ActivityTaskManagerService (ATMS) 的 Binder 代理对象。
    • 调用 ATMS 的 startActivity() 方法,请求正式通过 Binder IPC 从 Launcher 进程发送到 SystemServer 进程

阶段二:SystemServer 进程 - 处理请求与决策

  1. ATMS 接收请求ActivityTaskManagerServicestartActivity() 方法被调用。
  2. ActivityStarter 的介入
    • ATMS 不会立即处理,而是通过 ActivityStartController 创建一个 ActivityStarter 对象来专门负责这次启动。
    • 设计思想:将复杂的启动逻辑(如权限检查、任务栈管理、参数解析等)封装在 ActivityStarter 类中,使 ATMS 的职责更清晰。
  3. 执行启动ActivityStarter.execute() 被调用,经过一系列内部方法如 startActivityUnchecked() -> startActivityInner()
  4. 窗口与任务栈处理
    • 启动流程与窗口管理(WMS)紧密相关。代码会深入到 RootWindowContainer (窗口容器的根)、Task (任务栈) 等类。
    • resumeFocusedTasksTopActivities() 方法被调用,目的是将要启动的 Activity 所在的任务栈恢复到前台并获取焦点。
  5. 检查进程是否存在:在 ActivityTaskSupervisor.startSpecificActivity() 中,系统会检查要启动的 ActivityRecordr)所对应的 ProcessRecordproc)是否存在。如果 procnull 或已死亡,就需要创建新进程。
  6. 创建进程的决策:通过 mService.startProcessAsync() -> startProcessLocked(),系统最终决定需要启动一个新进程。

阶段三:SystemServer 到 Zygote - 发送创建指令

  1. 准备参数:在 startProcessLocked 系列方法中,系统会准备好创建新进程所需的所有参数,其中最关键的是 入口类 entryPoint = "android.app.ActivityThread"
  2. 获取 Zygote 通信句柄:在 Process.start() 方法中,系统判断这是一个普通应用启动,会通过 appZygote.getProcess().start() 来执行。
  3. 切换到 Socket 通信ZygoteProcess.startViaZygote() 是核心方法。
    • 它将所有参数(包括入口类、uid、gid、seInfo 等)格式化成一个字符串列表。
    • 通过 openZygoteSocketIfNeeded() 方法,与 Zygote 进程建立一个 Unix Domain Socket 连接。
  4. 发送指令并等待结果
    • zygoteSendArgsAndGetResult() 将参数列表拼接成一个字符串,通过 Socket 的输出流写入。
    • 写入后,它会阻塞并等待 Zygote 从输入流返回结果,结果中包含了新进程的 pid
    • system_server 进程拿到 pid 后,这个阶段的任务就完成了。后续将等待 App 进程反向连接(attach)。

四、 核心面试问题与答案

问题 1:请简述一下从点击桌面图标到 App 进程开始创建的完整流程。

答:

  1. Launcher 进程:用户点击图标,LauncherApp 的 Activity 响应点击事件,通过 startActivity() 调用到 Instrumentation 类。
  2. Binder IPC 到 SystemServerInstrumentation 类通过 Binder IPC,向 SystemServer 进程中的 ActivityTaskManagerService (ATMS) 发起 startActivity 请求。
  3. SystemServer 处理:ATMS 接收请求后,交由 ActivityStarter 进行处理,包括权限检查、任务栈管理等。在 ActivityTaskSupervisor 中,系统发现目标 Activity 所在的进程不存在。
  4. Socket IPC 到 ZygoteSystemServer 决定创建新进程,于是通过 Process.start() 方法,切换到 Socket 通信,向 Zygote 进程发起 fork 进程的请求,并传递了新进程的入口类 android.app.ActivityThread 等参数。
  5. Zygote 创建进程:Zygote 进程接收到 Socket 消息后,执行 fork() 操作,创建出新的 App 进程。

问题 2:为什么 Launcher 和 SystemServer 之间用 Binder 通信,而 SystemServer 和 Zygote 之间用 Socket?

答: 这是由它们各自的职责和技术限制决定的。

  • Binder:功能强大但复杂,支持面向对象的接口调用,非常适合 LauncherSystemServer 之间复杂的业务通信。但 Binder 的实现是多线程的,而 Zygote 的核心是 fork()。如果 Zygote 使用 Binder,fork() 出的子进程无法正确继承父进程的多线程状态(如锁),会导致死锁等严重问题。
  • Socket:是一种非常基础、简单的 Linux IPC 机制。SystemServerZygote 的请求非常单一,就是“给我创建一个进程”。使用 Socket 可以让 Zygote 的实现非常简洁、稳定、可靠,并且完美避开了 fork 和多线程的冲突问题。

问题 3:在 App 启动流程中,Instrumentation 类扮演了什么角色?

答: Instrumentation 类扮演着 “桥梁”“监控者” 的角色。

  1. 桥梁:它是应用程序代码和系统服务(ATMS)之间的桥梁。ActivitystartActivity 等请求都是委托给 Instrumentation 实例,由它来真正地通过 Binder IPC 与系统服务进行通信。
  2. 监控者:它的设计初衷是为了监控应用与系统的交互,这也是为什么所有 Activity 的生命周期回调(如 onCreate, onResume)实际上都是由 Instrumentation 来间接调用的。这使得 Android 的测试框架可以通过替换 Instrumentation 实现对应用生命周期的完全控制和模拟。

问题 4:当 ATMS 收到 startActivity 请求后,它会立即开始创建进程吗?中间经过了哪些重要环节?

答: 不会立即创建。中间会经过一系列复杂的检查和准备工作,主要由 ActivityStarter 类负责,包括:

  1. 权限检查:检查调用者是否有权限启动目标 Activity
  2. Intent 解析:解析 Intent,找到最匹配的 ActivityInfo
  3. 任务栈(Task)处理:决定这个 Activity 应该放在哪个任务栈中,是新建任务栈还是复用现有任务栈,并根据 launchModeIntent Flags 对栈内 Activity 进行相应处理(如 CLEAR_TOP 等)。
  4. 进程检查:在确定了所有信息后,才会检查目标 Activity 所在的进程是否存在。只有在进程不存在时,才会触发后续的创建流程。