2. Android系统架构与启动流程

理解 Android 的性能与稳定性问题,必须先理解系统从上电到桌面可交互之间发生了什么。Android 的启动不是“内核启动完就结束”,而是一条由 init → Zygote → SystemServer → 核心系统服务 → Launcher 组成的链式过程。链上任意一环变慢,都会直接体现为开机时间变长、首屏卡顿甚至开机失败。本章聚焦这条链的结构、启动顺序与性能关键路径。

一、核心原理:分层架构与启动链

Android 系统架构自下而上可分为:Linux 内核层、硬件抽象层(HAL)、原生库与运行时(含 ART)、Java API 框架层、应用层。启动流程正是自下而上逐层“点亮”的过程:内核启动后挂载根文件系统并执行 init,init 解析 init.rc 启动各类 native 服务,其中最关键的是 servicemanager、zygote 与 surfaceflinger。

Zygote 是 Android 应用进程的“母体”。它在启动时预加载大量常用类与资源,并初始化 ART 虚拟机,随后进入 socket 循环等待孵化请求。当需要启动新应用进程时,AMS 通过 socket 通知 Zygote,Zygote 以 fork() 方式复制自身,子进程再执行 RuntimeInit 与 ActivityThread.main()。这种“预加载 + fork”的设计大幅缩短了应用启动时间,也是 Android 区别于传统 Linux 进程模型的关键。

SystemServer 是 Java 框架层的起点,由 Zygote fork 出的第一个 Java 进程。它按严格顺序启动上百个系统服务,其中 AMS(ActivityManagerService)、PMS(PackageManagerService)、WMS(WindowManagerService)是三大核心。AMS 负责进程与四大组件调度,PMS 负责包解析与权限,WMS 负责窗口与输入分发。它们之间存在强依赖:AMS 启动时需要 PMS 提供包信息,WMS 又依赖 AMS 的进程管理能力。

Android 启动链与核心服务启动顺序 内核 / init Zygote SystemServer 应用层 Linux Kernel init 进程 servicemanager surfaceflinger Zygote 进程 预加载类/资源 + ART 初始化 fork() 子进程 ActivityThread.main() SystemServer 进程 启动引导服务 / 核心服务 AMS ActivityManager PMS PackageManager WMS WindowManager Launcher / 应用进程 首屏可交互 性能关键路径 Zygote 预加载耗时 PMS 扫描 APK / AMS 服务初始化 WMS 窗口就绪 → 首帧绘制

二、方法流程:核心服务启动顺序

SystemServer 的启动顺序经过精心设计,遵循“先底层后上层、先基础后业务”的原则。其 run() 方法中依次调用 startBootstrapServices()、startCoreServices()、startOtherServices()。关键顺序如下:

  1. 引导服务:ActivityManagerService、PowerManagerService、PackageManagerService、DisplayManagerService 等。AMS 与 PMS 在此阶段创建,PMS 会扫描 /system/framework、/data/app 等目录下的 APK,解析 AndroidManifest,构建包信息数据库。
  2. 核心服务:BatteryService、UsageStatsService、WebViewUpdateService 等。
  3. 其他服务:WindowManagerService、InputManagerService、NetworkManagementService、MountService 等。WMS 在此时完成窗口层级与输入通道的建立。
  4. 系统就绪:所有服务启动完毕后,AMS 调用 systemReady(),通知各服务进入运行态,随后启动 Launcher。

可以用以下命令观察启动各阶段耗时:

# 查看启动阶段时间戳
adb shell dmesg | grep -i "init\|zygote\|system_server"

# 查看 SystemServer 各服务启动耗时
adb logcat -b events | grep "system_server"

# 查看开机时间统计
adb shell "cat /proc/boottime" 2>/dev/null
adb shell dumpsys activity | grep -i "boot"

三、案例/场景:首屏卡顿的定位

某项目反馈“开机后桌面出现慢、点击图标无响应”。排查思路如下:

  • 用 adb shell dumpsys activity activities 查看 Launcher 是否已处于 RESUMED 状态,若长时间停留在 STARTING,说明 AMS 调度或进程创建受阻。
  • 用 adb shell dumpsys window 检查 WMS 是否已完成窗口添加,若 mCurrentFocus 为空,说明窗口尚未就绪。
  • 用 adb shell dumpsys package 观察 PMS 扫描耗时,若 APK 数量多或存在损坏包,PMS 会阻塞后续服务。
  • 用 adb shell top -H 观察 system_server 线程 CPU 占用,定位是否在 PackageManagerService 或 ActivityManagerService 初始化中空转。

最终定位为 PMS 扫描某个第三方预装 APK 时解析异常,导致启动链在引导服务阶段被拉长。移除该 APK 后开机时间从 28s 降至 19s。

四、误区与复盘

常见误区一:认为“开机慢就是内核慢”。实际上内核阶段通常只占 2~4 秒,大部分时间消耗在 Zygote 预加载、PMS 扫描与 SystemServer 服务初始化上。

常见误区二:把 AMS、PMS、WMS 当作完全独立模块。它们存在启动依赖:AMS 需要 PMS 提供包信息,WMS 需要 AMS 提供进程与 Activity 记录,修改任一服务的初始化逻辑都可能影响整条链。

常见误区三:只优化应用启动而不关注系统服务。若 SystemServer 尚未完成 systemReady(),应用进程即使被创建也无法正常显示。

阶段 关键对象 典型耗时 性能关注点
内核 / init Kernel、init.rc 2~4s 驱动加载、分区挂载
Zygote 预加载类、ART 1~3s 预加载类数量、GC 策略
SystemServer 引导 AMS、PMS 3~8s APK 扫描、权限解析
SystemServer 其他 WMS、InputManager 2~5s 窗口层级、输入通道
应用层 Launcher、首帧 1~3s 首帧绘制、进程创建

优化启动链的核心思路:缩短关键路径上的串行耗时。例如减少 Zygote 预加载类、延迟非必要服务初始化、并行化 PMS 扫描、避免在 SystemServer 主线程做耗时 IO。任何在 systemReady() 之前执行的阻塞操作,都会直接转化为开机时间。