【Android FrameWork】延伸阅读:ActivityManagerService启动Activity

AMS 启动 Activity

在 Android 系统中,用户点击应用图标或调用startActivity()时,看似简单的 "界面跳转",实则是 AMS(运行于 SystemServer 进程)与应用进程、Zygote 进程、WMS(窗口管理服务)等多角色协同的复杂过程。

整个流程以 "跨进程通信(Binder)" 为纽带,围绕 "组件校验→栈管理→进程准备→Activity 创建→窗口显示" 展开。

本文将按时序拆解每个关键环节,还原 Activity 从 "启动请求" 到 "用户可见" 的全链路。

启动流程的核心角色与数据结构

在深入流程前,需明确参与方及关键数据结构(部分已在前文提及,此处聚焦启动场景):

角色 / 结构 归属进程 核心作用
AMS(ActivityManagerService) SystemServer 进程 统筹启动流程:校验权限、管理任务栈、调度进程、通知应用创建 Activity
ActivityManager 应用进程 AMS 的客户端代理,应用通过它发起startActivity()请求(封装 Binder 调用)
ApplicationThread 应用进程 应用进程的 Binder 服务端,接收 AMS 的指令(如 "创建 Activity""触发生命周期")
ActivityThread 应用进程 应用的主线程调度器,负责执行 Activity 生命周期、创建 Activity 实例
ActivityRecord SystemServer 进程 单 Activity 的状态载体:记录组件信息(如ComponentName)、生命周期状态、所属任务栈
TaskRecord SystemServer 进程 任务栈载体:管理同一任务下的所有 ActivityRecord,保证 "返回栈" 逻辑
ActivityStackSupervisor SystemServer 进程 任务栈的顶层管理者:决定 Activity 入哪个栈、是否创建新栈、调整栈内 Activity 顺序
Zygote 进程 独立进程 孵化器:接收 AMS 请求,创建新的应用进程(若目标进程未启动)
WMS(WindowManagerService) SystemServer 进程 窗口管理者:在 Activity resume 阶段,接收 AMS 指令,添加 Activity 窗口并显示

startActivity到 AMS 调用

应用进程(如当前运行的 Activity 所在进程)发起启动请求时,并非直接操作 Activity,而是通过 "代理→Binder 通信" 将请求传递给 AMS。

具体步骤如下:

1. 应用层调用:startActivity()的上层封装

无论是用户点击按钮调用startActivity(new Intent(this, TargetActivity.class)),还是系统发起的启动(如启动桌面 Launcher),最终都会进入ContextImpl的实现(应用的Context实际是ContextImpl实例),核心调用链为:

java 复制代码
// 应用层调用

Activity.startActivity(Intent);

→ ContextImpl.startActivity(Intent);

→ ActivityManager.startActivity(Intent) // 应用进程的AMS代理(ActivityManager)

此处的ActivityManager是应用进程的 "客户端代理",它不直接处理逻辑,而是将请求通过 Binder 发送给 SystemServer 进程的 AMS。

2. Instrumentation 拦截:启动前的应用层校验

ContextImpl.startActivity()中,会先经过Instrumentation(应用的 "工具类",负责监控组件生命周期)的拦截,执行基础校验:

  • 检查Intent是否为空、是否设置了目标组件(ComponentName);

  • 若为 "隐式 Intent",则通过PackageManager(PMS 的客户端代理)查询匹配的 Activity(避免无匹配组件导致启动失败)。

3. Binder 跨进程:请求传递至 AMS

Instrumentation校验通过后,会调用ActivityManager.getService().startActivityAsUser(...)------ 这里的getService()获取的是 AMS 的 Binder 代理(IActivityManager),通过 Binder 驱动,将启动请求从应用进程 "跨进程传递" 到 SystemServer 进程的 AMS。

AMS 校验、栈管理与进程判断

AMS 收到启动请求后,需完成 "合法性校验→任务栈调度→目标进程状态判断" 三大核心操作,这是决定启动能否继续的关键环节。

1. 合法性校验:权限与组件双重检查

AMS 首先执行严格校验,避免非法启动(若校验失败,直接抛出异常,如ActivityNotFoundException):

  • 组件校验 :通过 PMS 查询目标 Activity 是否在AndroidManifest.xml中注册(PMS 存储了所有应用的组件信息,AMS 与 PMS 同属 SystemServer 进程,可直接内存调用,无需 IPC);

  • 权限校验 :检查发起进程是否拥有启动目标 Activity 的权限(如目标 Activity 声明了android:permission,则需发起进程在 Manifest 中声明对应权限);

  • Intent 校验 :检查Intentflags是否合法(如FLAG_ACTIVITY_NEW_TASK是否符合栈管理规则)、目标 Activity 是否为 "导出状态"(android:exported="true",非本应用组件需导出才能被启动)。

2. 任务栈管理:创建 ActivityRecord 与调度 TaskRecord

校验通过后,AMS 会通过ActivityStackSupervisor(栈管理者)完成 "Activity 入栈" 逻辑,核心是创建ActivityRecord并分配到对应的TaskRecord

  1. 创建 ActivityRecord :AMS 为目标 Activity 创建ActivityRecord实例,记录关键信息(如发起进程 ID、目标组件名、生命周期状态初始化为INITIALIZING);

  2. 确定目标 TaskRecordActivityStackSupervisor根据Intentflags(如FLAG_ACTIVITY_NEW_TASK)和 "任务栈亲和性"(android:taskAffinity),决定 Activity 进入哪个栈:

  • IntentFLAG_ACTIVITY_NEW_TASK且无匹配亲和性的栈,则创建新的TaskRecord

  • 若有匹配的现有栈(如同应用的默认栈),则将ActivityRecord加入该栈的栈顶;

  1. 调整栈内顺序 :若存在 "栈内复用" 场景(如FLAG_ACTIVITY_SINGLE_TOP),则将目标ActivityRecord移至栈顶,同时销毁其上方的ActivityRecord(触发对应 Activity 的onDestroy())。

3. 进程判断:目标进程是否已启动

AMS 通过ActivityRecord关联的 "目标进程包名",查询系统中的ProcessRecord列表(记录所有进程状态),判断目标进程(即目标 Activity 所在的应用进程)是否已启动:

  • 情况 1:目标进程已启动:直接进入 "阶段 3",通知应用进程创建 Activity;

  • 情况 2:目标进程未启动:先触发 "进程创建流程",再进入后续步骤(这是冷启动与热启动的核心区别)。

AMS 请求 Zygote 创建进程

若目标进程未启动(如首次点击应用图标),AMS 需先请求 Zygote 创建新进程,流程如下:

  1. AMS 发起进程创建请求 :AMS 调用Process.start(),封装进程创建参数(如目标应用包名、进程名、uid/gid,这些信息从 PMS 获取),通过 Socket 通信(Zygote 监听特定 Socket 端口)将请求发送给 Zygote 进程;

  2. Zygote 创建进程 :Zygote 收到请求后,通过fork()系统调用复制自身进程(利用 Linux 写时复制机制,复用预加载的框架类和资源,加速进程创建),生成新的应用进程;

  3. 初始化应用进程 :新进程启动后,会执行ActivityThread.main()方法(应用进程的入口):

  • 创建ActivityThread实例(应用主线程管理器);

  • 初始化Looper(为主线程开启消息循环,处理 UI 和生命周期消息);

  • 创建ApplicationThread实例(应用的 Binder 服务端,用于接收 AMS 指令),并通过ActivityManager.getService().attachApplication(mAppThread)将其注册到 AMS;

  1. AMS 绑定进程与 ActivityRecord :AMS 收到attachApplication()请求后,将新进程的ProcessRecord与目标 Activity 的ActivityRecord关联,标记 "进程已就绪",进入下一步。

AMS 通过 Binder 触发 Activity 创建

无论目标进程是已启动还是新创建,AMS 最终都会通过ApplicationThread(应用的 Binder 服务端)向应用进程发送 "创建 Activity" 的指令,流程如下:

1. AMS 发起创建指令:scheduleLaunchActivity()

AMS 调用ApplicationThread.scheduleLaunchActivity(ActivityClientRecord)------ 此处的ActivityClientRecordActivityRecord的 "客户端副本",包含创建 Activity 所需的所有信息(如ActivityRecord引用、Intent、组件名),通过 Binder 传递到应用进程。

2. 应用进程接收指令:从 Binder 线程到主线程

应用进程的 Binder 线程池(负责接收 AMS 的 Binder 请求)收到scheduleLaunchActivity()后,会将任务封装为Message,通过Handler发送到应用主线程(ActivityThreadmH Handler)------ 因为 Android 要求 UI 操作和生命周期执行在主线程,Binder 线程不能直接操作。

3. 主线程处理:ActivityThread.handleLaunchActivity()

主线程的Looper处理Message时,调用ActivityThread.handleLaunchActivity(),这是应用进程创建 Activity 的核心入口,具体分两步:

  1. 创建 Activity 实例 :通过Instrumentation.newActivity(ClassLoader, className, intent)创建目标 Activity 实例(ClassLoader加载 Activity 类,避免类加载冲突);

  2. 初始化 Application(首次启动时) :若应用的Application未创建,会先通过Instrumentation.callApplicationOnCreate(app)创建Application并执行onCreate()(整个应用生命周期仅执行一次)。

Activity 生命周期执行与窗口显示

Activity实例创建后,ActivityThread会按顺序触发其生命周期方法,同时与 WMS 协同完成窗口显示,这是 Activity 从 "内存对象" 变为 "用户可见界面" 的关键环节。

1. 触发早期生命周期:onCreate()onStart()onPause()(当前栈顶 Activity)

  • onCreate()执行ActivityThread调用Instrumentation.callActivityOnCreate(activity, bundle),触发Activity.onCreate(savedInstanceState)------ 此时 Activity 完成布局加载(setContentView()),但窗口尚未显示;

  • onStart()执行 :紧接着调用callActivityOnStart(activity),触发onStart()------Activity 进入 "可见但不可交互" 状态;

  • 当前栈顶 Activity 暂停 :若启动新 Activity 前,已有 Activity 在栈顶(如从 A 启动 B),AMS 会先通知原 Activity 所在进程执行onPause()(通过ApplicationThread.schedulePauseActivity()),确保 "先暂停旧界面,再启动新界面"(避免界面重叠)。

2. AMS 与 WMS 协同:为新 Activity 准备窗口

在新 Activity 执行onStart()后,AMS 会向 WMS 发送 "添加窗口" 的请求:

  1. AMS 通知 WMS :AMS 调用WMS.addWindow(),传递ActivityRecord关联的窗口信息(如窗口大小、类型、所属进程);

  2. WMS 创建窗口对象 :WMS 为 Activity 创建WindowState实例(记录窗口状态),并分配窗口 Z 序(确保新 Activity 窗口在最上层);

  3. 应用进程创建 Window :应用进程的Activity通过PhoneWindowWindow的实现类)创建DecorView(窗口的根视图),并将setContentView()加载的布局添加到DecorView

3. 触发onResume():Activity 进入 "可交互" 状态

  • AMS 发起 resume 指令 :当 WMS 窗口准备就绪,AMS 调用ApplicationThread.scheduleResumeActivity(),通知应用进程触发onResume()

  • onResume()执行ActivityThread调用Instrumentation.callActivityOnResume(activity),触发Activity.onResume()------ 此时 Activity 的DecorView被添加到 WMS 的窗口体系中;

  • WMS 显示窗口 :WMS 通过SurfaceFlinger(图形渲染服务)将DecorView的内容渲染到屏幕,Activity 正式 "用户可见且可交互"。

总结

整个启动流程可概括为 "三进程协同、两重校验、一次窗口渲染"

  1. 三进程协同:应用进程(发起请求、创建 Activity)→ SystemServer 进程(AMS 统筹、WMS 管窗口)→ Zygote 进程(冷启动时创建应用进程);

  2. 两重校验 :应用层Instrumentation基础校验 → AMS 层权限 + 组件 + Intent 合法性校验;

  3. 一次窗口渲染 :从onCreate()加载布局到 WMS+SurfaceFlinger 渲染,完成 "内存对象→屏幕显示" 的转化。

关键设计思路:

  • 跨进程通信依赖 Binder :AMS 与应用进程的交互全靠IActivityManager(AMS 代理)和ApplicationThread(应用 Binder 服务端),确保指令高效传递;

  • 任务栈管理保证用户体验 :通过TaskRecordActivityStackSupervisor维护 "返回逻辑",让用户点击返回时能按启动顺序退出;

  • 多服务协同实现功能闭环:AMS 主导流程,PMS 提供组件信息,WMS 管理窗口,Zygote 负责进程创建,缺任一环节均无法完成启动。

相关推荐
COSMOS_*2 小时前
2025最新版 Android Studio安装及组件配置(SDK、JDK、Gradle)
android·ide·jdk·gitee·android studio
jian110582 小时前
android studio Profiler性能优化,查看内存泄漏
android·性能优化·android studio
建群新人小猿5 小时前
陀螺匠企业助手——组织框架图
android·java·大数据·开发语言·容器
TheNextByte15 小时前
如何将文件从Android无线传输到 iPad
android·ios·ipad
赫萝的红苹果5 小时前
实验探究并验证MySQL innoDB中的各种锁机制及作用范围
android·数据库·mysql
叶落无痕526 小时前
Android Studio 2024.3.1 连接夜神模拟器
android·ide·android studio
玲子的猫6 小时前
安卓原生开发实现图片双指放大预览功能
android
2501_915106327 小时前
如何在iPad上高效管理本地文件的完整指南
android·ios·小程序·uni-app·iphone·webview·ipad
似霰7 小时前
AIDL Hal 开发笔记5----实现AIDL HAL
android·framework·hal
2501_915106328 小时前
iOS 成品包加固,在只有 IPA 的情况下,能做那些操作
android·ios·小程序·https·uni-app·iphone·webview