第一章:Android 系统启动流程
1.1 启动阶段概述
Android 系统从按下电源键到 Launcher 显示,共经历六个阶段:
- Bootloader
- Linux Kernel 初始化
- Init 进程启动
- init.rc 解析与守护进程启动
- Zygote 与 SystemServer 启动
- Launcher 启动
【补充】此六阶段模型是理解 Android 系统架构的基础。
1.2 Bootloader 阶段
当设备通电后,CPU 会从芯片中固化的一个地址开始执行代码,这个地址通常指向 Boot ROM。Boot ROM 中的代码会加载 Bootloader 到 RAM 中,并跳转执行。Bootloader 负责初始化硬件(如时钟、内存控制器等),然后加载 Linux 内核镜像(通常是 boot.img)到内存,并跳转到内核入口开始执行。
1.3 Linux 内核初始化阶段
Linux 内核启动后,首先会创建两个特殊的进程:
- swapper 进程(pid=0):也称 idle 进程,是内核的空闲进程;
- kthreadd 进程(pid=2):内核线程管理器,负责创建和管理其他内核线程。
内核完成中断、调度器、内存管理等子系统的初始化后,会加载必要的驱动模块(如显示、存储、输入设备驱动),挂载 tmpfs、proc、sysfs 等虚拟文件系统,最后执行用户空间的第一个程序:/init。
1.4 Init 进程启动(PID=1)
init 是用户空间的第一个进程(PID=1),也是所有用户进程的祖先。它主要完成以下工作:
- 挂载 /system、/vendor、/data 等系统分区;
- 创建 /dev、/mnt、/acct 等关键目录;
- 启用 SELinux 安全策略;
- 启动属性服务(Property Service),该服务提供全局配置的读写接口,例如 ro.build.version 等系统属性。
【补充】SELinux 在此阶段激活,后续所有进程的行为都将受到其安全策略约束。
📚 更多关于 init 进程的深度解析,可参考:init进程
1.5 解析 init.rc 并启动系统守护进程
init 进程会读取 /init.rc 文件以及它所 include 的其他 .rc 文件(例如 zygote.rc),按照其中的声明顺序启动一系列关键的系统服务,包括:
- servicemanager:Binder 驱动的服务注册中心,所有 Binder 服务都必须向它注册;
- hwservicemanager:用于 Treble 架构,管理 HIDL HAL 服务的注册;
- adbd:Android Debug Bridge 守护进程,提供调试接口;
- logd:日志系统后台服务;
- zygote:Java 应用进程的孵化器,这是 Android 系统中最重要的进程之一。
【重要说明】这些服务并非由 init 主动创建,而是通过 init.rc 脚本中的 service 块被动触发,init 通过 fork + exec 方式启动它们。


📚 关于 init 进程如何管理子进程生命周期,详见:init进程
1.6 Zygote 与 SystemServer 启动
Zygote 进程在启动时会预加载 Android Framework 中常用的 Java 类(如 Activity、View、Intent 等)以及公共资源(如 R 文件)。这样,当需要启动一个新的应用进程时,只需通过 fork() 系统调用复制 Zygote 的进程镜像,即可直接复用这些已加载的类和资源,从而大幅缩短应用启动时间。
SystemServer 进程是由 Zygote 通过 fork() 创建的,它会执行 com.android.server.SystemServer 类的 main 方法。SystemServer 负责启动 Android 系统中超过 90 个核心服务,这些服务被分为三类依次启动:
- 引导服务(Bootstrap Services):包括 ActivityManagerService (AMS)、PackageManagerService (PMS)、WindowManagerService (WMS) 等;
- 核心服务(Core Services):包括 BatteryService、UsageStatsService、WebViewUpdateService 等;
- 其他服务(Other Services):包括 BluetoothService、WifiService、UsbService 等。
【补充】Zygote 与 AMS 之间的通信使用的是 LocalSocket,而不是 Binder。这是因为 AMS 向 Zygote 发送的 fork 请求数据量非常小(只包含包名、uid、gids 等),使用 Socket 的开销更低,且无需经过 Binder 的权限校验流程。
📚 Zygote 的双进程模型(zygote64 / zygote_secondary)详解:zygote进程
1.7 Launcher 启动
当 SystemServer 成功启动并完成所有核心服务的初始化后,ActivityManagerService (AMS) 会发送一个 Intent,其 action 为 ACTION_MAIN,category 为 CATEGORY_HOME。这个 Intent 会被 Launcher 应用接收。Zygote 接收到 AMS 的请求后,会 fork 出一个新的进程来运行 Launcher。至此,系统完成了从硬件上电到用户可见界面的全过程。
【补充】此后,所有普通应用的进程都是通过同样的方式——由 Zygote fork 生成。
第二章:PackageManagerService (PMS) —— APK 扫描与解析机制
2.1 PMS 的初始化时机与职责
PackageManagerService(简称 PMS)是在 SystemServer 启动过程中,作为引导服务(Bootstrap Services) 之一被创建的。它的核心职责是:
- 扫描设备上所有预置和用户安装的 APK 文件;
- 解析每个 APK 的 AndroidManifest.xml;
- 提取并注册四大组件(Activity、Service、BroadcastReceiver、ContentProvider)信息;
- 为系统其他模块(如 AMS)提供组件查询与权限校验能力。
2.2 APK 扫描路径与优先级
PMS 会按以下顺序和优先级扫描多个目录中的 APK:
/system/framework
存放系统核心库(如 android.jar、framework-res.apk),具有最高优先级。/system/app
系统内置应用(如 Settings、SystemUI),优先级次之。/vendor/app
厂商定制应用。/data/app
用户通过应用商店或 adb 安装的应用,优先级最低。
【补充】扫描顺序决定了同名包的覆盖规则:高优先级目录中的 APK 会覆盖低优先级目录中的同名包。
2.3 扫描与解析过程细节
PMS 对每个 APK 执行以下操作:
- 使用
PackageParser读取 APK 文件; - 解压并解析
AndroidManifest.xml; - 提取 package name、version、permissions、uses-sdk 等元数据;
- 遍历四大组件声明,为每个组件创建对应的对象(如 ActivityInfo、ServiceInfo);
- 将所有信息封装到一个
PackageParser.Package对象中,并存入内部集合。
【关键细节】每个 APK 对应一个 Package 对象,其内部的组件(如 Activity)以
ArrayList<ActivityInfo>形式存储。
2.4 异常处理机制
PMS 在扫描过程中会对不同类型的 APK 采取不同的容错策略:
- 系统 APK(/system/app 等):即使解析失败,也不会删除文件,但会记录严重错误日志;
- 非系统 APK(/data/app):若解析失败(如 Manifest 格式错误、签名无效),PMS 会直接删除该 APK 文件,防止无效应用残留。
【补充】这一设计确保了系统启动后,所有已知组件都是合法且可调度的。
第三章:WindowManager 体系架构与窗口管理机制
3.1 WindowManager 的三层抽象模型
Android 的窗口管理系统采用清晰的三层架构,将应用层、客户端与系统服务解耦:
-
Window(应用层)
- 是一个抽象类,代表一个窗口容器;
- 在 Activity 中的实际实现类为
PhoneWindow; - 负责持有 DecorView(根视图)并管理窗口属性(如标题栏、背景等)。
-
WindowManager(客户端接口)
- 是一个接口,提供给应用程序使用的窗口操作 API;
- 实现类为
WindowManagerImpl; - 应用通过它调用
addView()、updateViewLayout()、removeView()等方法。
-
WindowManagerService(WMS,系统服务)
- 运行在 SystemServer 进程中;
- 是窗口管理的真实执行者;
- 负责窗口的创建、布局计算、Z-order 排序、动画驱动、Surface 分配及与 SurfaceFlinger 的交互。
【补充】这种分层设计使得应用无需关心底层图形合成细节,同时保证系统对窗口的统一管控。
📚 完整窗口机制解析:Android Window 机制
3.2 WMS 中的关键对象
WindowState
- 每个窗口在 WMS 内部都有一个对应的
WindowState对象; - 它记录了窗口的尺寸、位置、类型(TYPE_APPLICATION / TYPE_STATUS_BAR)、可见性、Token 引用等状态信息;
- 是 WMS 进行布局计算和绘制调度的基本单位。
WindowToken
-
WindowToken是一组窗口的逻辑容器; - 例如,一个 Activity 的所有窗口(Activity Window + Dialogs + PopupWindows)共享同一个 WindowToken;
- Token 由 AMS 在启动 Activity 时创建,并传递给 WMS;
- WMS 通过 Token 确保同一任务内的窗口具有相同的生命周期和层级归属。


3.3 添加 View 的完整流程
当应用调用 WindowManager.addView(decorView, params) 时,系统执行以下步骤:
-
创建 ViewRootImpl
- WindowManagerImpl 会为该 View 创建一个
ViewRootImpl实例; - ViewRootImpl 是 View 树与 WMS 之间的桥梁。
- WindowManagerImpl 会为该 View 创建一个
-
绑定 DecorView
- 将传入的 DecorView 与 ViewRootImpl 绑定;
- 设置 LayoutParams。
-
触发首次绘制流程
- 调用
requestLayout(),触发measure → layout → draw; - 但此时尚未真正显示,因为未与 WMS 建立连接。
- 调用
-
通过 Binder 调用 WMS 的 addWindow()
- ViewRootImpl 通过 Binder IPC 调用 WMS 的
addWindow()方法; - 传入参数包括:View 的 LayoutParams、InputChannel、Display ID 等。
- ViewRootImpl 通过 Binder IPC 调用 WMS 的
-
WMS 分配 Surface 并注册到 SurfaceFlinger
- WMS 验证权限和 Token 合法性;
- 创建
WindowState和WindowSurfaceController; - 向 SurfaceFlinger 申请一个
Surface; - 将 Surface 的生产端(Producer)通过 Binder 返回给 App 进程。
-
App 端开始绘制
- App 拿到 Surface 后,通过
Canvas或OpenGL向其写入图形数据; - SurfaceFlinger 在 VSync 信号到来时合成所有 Surface 并输出到屏幕。
- App 拿到 Surface 后,通过


【补充】整个过程依赖
Choreographer监听 VSync 信号,在doFrame()回调中驱动绘制流水线,确保画面流畅。
3.4 Surface 的管理机制
-
WMS 创建真实 Surface:App 进程中的
Surface对象只是一个空壳,真正的图形缓冲区由 WMS 通过SurfaceFlinger创建; - App 仅持有引用:App 通过 Binder 获取 Surface 的“生产端”(IGraphicBufferProducer),用于提交帧数据;
- 线程安全:Surface 的写入操作需在 UI 线程或 GL 线程进行,避免并发冲突。
3.5 输入事件通道
- 每个窗口在添加时,WMS 会为其创建一对
InputChannel(基于 Socket FD); - 一端留在 WMS,用于接收 InputDispatcher 的事件;
- 另一端通过 Binder 传回 App 进程,由
ViewRootImpl的InputEventReceiver监听; - 事件在 App 主线程中分发给对应 View。

📚 深入 WMS 实现:无处不在的WMS|WindowManager体系
第四章:Activity 生命周期
4.1 Activity 启动初始化流程
当 AMS 决定启动一个 Activity 时,会通过 Binder IPC 通知目标应用进程的 ActivityThread。ActivityThread 执行以下关键步骤:
▶ attach()
- 创建
PhoneWindow对象; - 将当前 Activity 设置为
PhoneWindow的 Callback; - 调用
window.setWindowManager(),将 Activity 与 WindowManager 关联; - 此时 Window 已创建,但尚未添加到 WMS,因此没有有效的 WindowToken。
▶ setContentView()
- 调用
PhoneWindow.setContentView(); - inflate 用户指定的布局文件;
- 创建
DecorView(整个 View 树的根容器); - 将用户布局添加到
DecorView的 content 区域(ID 为android.R.id.content); - 此时 View 树已构建完成,但仍未调用
WindowManager.addView(),因此不会触发 measure/layout/draw,也不会显示在屏幕上。
【关键说明】只有在 Activity 的生命周期推进到
onResume()阶段后,AMS 才会通知 WMS 添加窗口。
4.2 完整生命周期方法详解
以下为原文中对每个生命周期方法的完整描述,未做任何删减
onCreate(Bundle savedInstanceState)
- 开发者在此方法中进行初始化操作,如调用
setContentView()、findViewById、绑定数据等; - 系统会传入
savedInstanceState参数,用于恢复因异常销毁前的状态; - 此时 Activity 的 Window 尚未注册到 WMS,WindowToken 为 null;
- 不能在此弹出 Dialog 或 PopupWindow,否则会抛出 “Unable to add window – token null is not valid” 异常。
onStart()
- Activity 对用户可见,但尚未获得焦点;
- WMS 已接收到 AMS 的请求,开始为该 Activity 分配 WindowToken;
- Surface 尚未创建,View 树不可交互;
- 可在此执行轻量级的可见性相关逻辑(如启动动画预加载)。
onResume()
- Activity 进入前台,获得焦点,可与用户交互;
- Input 事件通道已建立,触摸、按键事件可正常分发;
-
注意:尽管此时 Activity 已“resume”,但在某些机型或系统版本上,首次在
onResume()中立即弹出 PopupWindow 仍可能失败,原因在于 WMS 的 Token 注册与 Surface 分配存在微小延迟; -
推荐做法:将弹窗操作延迟到
onWindowFocusChanged(true)回调中,或通过View.post()发送到消息队列尾部执行。
onNewIntent(Intent intent)
-
触发条件:当 Activity 的启动模式为
singleTop或singleTask,且该 Activity 实例已存在时,再次启动它不会创建新实例,而是复用现有实例,并调用onNewIntent(); - 作用:用于接收新的 Intent 数据;
-
注意事项:
- 在
onNewIntent()中,应调用setIntent(intent)更新当前 Activity 的 Intent,否则后续调用getIntent()仍返回旧的 Intent; - 此方法可能在任意生命周期状态后被调用(如 Activity 在后台时被启动),因此不应假设 UI 已可见或已 resume;
- 常见使用场景:推送通知点击、Deep Link 跳转、跨应用数据传递。
- 在
【示例】
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); // 必须调用,否则 getIntent() 返回旧值 handleNewIntent(intent); }
onPause()
- Activity 失去焦点(例如:启动新 Activity、弹出 Dialog、来电界面覆盖);
- 必须快速返回,不能执行耗时操作,否则会导致 ANR(Application Not Responding);
- 系统可能在此之后杀死进程,因此不应依赖此方法保存持久化数据;
- 通常用于暂停动画、释放传感器、注销广播接收器等轻量级清理。
onStop()
- Activity 完全不可见(被其他 Activity 完全覆盖或进入后台);
- 可在此释放重量级资源,如停止网络请求、关闭数据库连接、注销位置监听;
- 若因配置变更(如屏幕旋转)导致重建,系统会在
onStop()之后调用onDestroy()。
onDestroy()
- Activity 被销毁;
- 所有资源应在此彻底释放;
- 若由
finish()触发,则isFinishing()返回 true; - 若因系统内存不足被回收,则此方法可能不会被调用。
4.3 onSaveInstanceState() 的调用时机(版本差异)
原文明确指出以下版本行为差异,完整保留:
在 Android API 级别 28(Android 9.0)之前:
onSaveInstanceState()在onPause()之后、onStop()之前调用。从 Android API 级别 28(Android 9.0)开始:
onSaveInstanceState()被移至onStop()之后调用。
【原因说明】Google 作出此调整是为了避免开发者在
onStop()中释放的资源(如 Bitmap、数据库连接)被onSaveInstanceState()误用,从而引发空指针或状态不一致问题。
【建议】不要在
onSaveInstanceState()中访问可能已在onStop()中释放的对象。
4.4 AMS 与 Activity 的协作机制
- AMS 作为系统服务,维护所有 Activity 的状态机;
- 当需要切换 Activity 状态时,AMS 通过 Binder 向目标进程的
ApplicationThread发送指令; -
ActivityThread的H(Handler)接收到消息后,反射调用对应 Activity 的生命周期方法; - Activity 本身不具备主动控制权,其生命周期完全由 AMS 驱动;
- 因此,Activity 是 AMS 管理的一个被动状态机,应用代码只是状态变更的响应者。
📚 完整生命周期详解:Activity生命周期

📚 更多 AMS 与 WMS 协作细节:WMS/AMS 窗口层级结构解析
第五章:其他关键技术机制
5.1 Zygote 与 AMS 的通信机制
- AMS 在需要启动新应用进程时,不会直接 fork 进程,而是通过 LocalSocket 向 Zygote 发送请求;
- 请求内容包括:目标 APK 的包名、用户 ID(uid)、组 ID(gids)、调试标志等;
- Zygote 接收到请求后,执行
fork()创建子进程,并在子进程中调用RuntimeInit.zygoteInit(),最终启动目标 ActivityThread; -
为何使用 Socket 而非 Binder?
- 因为 fork 请求数据量极小(通常 < 1KB);
- Socket 在小数据量下延迟更低、开销更小;
- Binder 需要跨进程权限校验和上下文切换,不适用于高频、轻量的进程孵化场景。
📚 Zygote 的双进程模型(zygote64 / zygote_secondary)详解:zygote进程
5.2 Input 事件通道机制
- 每个窗口在通过
WMS.addWindow()注册时,WMS 会为其创建一对InputChannel; -
InputChannel基于 Unix Domain Socket 的文件描述符(FD) 实现; - 一端保留在 WMS,用于接收
InputDispatcher分发的触摸、按键事件; - 另一端通过 Binder 传递给 App 进程,由
ViewRootImpl中的InputEventReceiver监听; -
关键特性:
- 单线程读取:事件必须在主线程中处理,保证顺序性;
- 线程安全:底层 FD 读写加锁,避免并发冲突;
- 低延迟:直接通过内核 socket 传递,绕过 binder transaction 开销。

5.3 Choreographer 与动画驱动机制
- Android 的 UI 绘制与动画依赖 VSync(垂直同步)信号;
-
Choreographer是系统提供的协调器,用于监听 VSync 信号; - 当应用调用
invalidate()或启动动画时,会向Choreographer注册回调; - 在下一个 VSync 到来时,
Choreographer执行doFrame()方法,依次触发:- Input 处理(分发触摸事件);
- Animation 更新(计算属性动画新值);
- Traversal(measure → layout → draw);
- Surface 提交(将帧数据提交给 SurfaceFlinger);
- 此机制确保所有 UI 操作以 60fps(或设备刷新率) 同步执行,避免画面撕裂和卡顿。
【补充】若主线程阻塞导致
doFrame无法及时完成,就会出现掉帧(jank)。
5.4 Surface 管理细节
-
App 端的
Surface对象是空的:它只是一个壳,不包含真实的图形缓冲区; -
真实 Surface 由 WMS 创建:WMS 调用
SurfaceFlinger的createSurface()方法申请一个Layer; -
生产者-消费者模型:
- App 进程持有 生产者端(IGraphicBufferProducer),用于填充像素数据;
- SurfaceFlinger 持有 消费者端(IGraphicBufferConsumer),用于合成并输出;
- 生命周期绑定窗口:当窗口被移除(如 Activity finish),WMS 会销毁对应的 Surface,释放 GPU 内存。
📚 深入 WMS 实现:无处不在的WMS|WindowManager体系