Android随笔-APP首次启动流程

从用户点击应用图标到 Activity 执行 onCreate() 的完整流程,涉及 Launcher 进程 → SystemServer 进程 → Zygote 进程 → 应用进程 之间的多轮跨进程通信。以下是详细拆解:

一、核心通信方式概览

通信双方 IPC 方式 作用
Launcher → AMS/ATMS Binder IPC 发送启动 Activity 的请求
AMS → Zygote Socket 请求 fork 创建新应用进程
AMS → 应用进程 Binder IPC 通过 ApplicationThread 代理回调应用进程
应用进程 → AMS Binder IPC 应用进程向 AMS 注册自身

:Android 10+ 中 AMS 的 Activity 管理职责已拆分至 ActivityTaskManagerService (ATMS),但核心逻辑不变。以下以 AMS 代指系统侧服务 。

二、详细流程

阶段 1:Launcher 发起启动请求(Binder IPC)

用户点击桌面图标时,Launcher 进程(本质也是一个普通应用)执行以下调用链:

java 复制代码
// Launcher 点击图标
Launcher.onClick() 
    → startActivity(intent) 
    → Instrumentation.execStartActivity()
    → ActivityManager.getService().startActivity()  // 跨进程 Binder 调用
  • ActivityManager.getService() 返回的是 AMS 的 Binder 代理对象(IActivityManager 接口的代理)
  • 通过 Binder 驱动 将请求发送到 SystemServer 进程中的 AMS
  • 传递的 Intent 包含目标组件信息:component = com.example.app/.MainActivity

阶段 2:AMS 处理启动请求(SystemServer 进程)

AMS 收到请求后,执行以下关键步骤:

  1. 权限校验 --- 检查调用方是否有启动权限
  2. 创建 ActivityRecord --- 在 AMS 内部为本次启动创建对应的 ActivityRecord 对象,记录 Activity 状态
  3. 检查进程状态 --- 通过 ProcessRecord 查询目标应用进程是否存在
    • 若进程已存在 → 直接走 realStartActivityLocked() 启动 Activity
    • 若进程不存在 → 进入进程创建流程

阶段 3:AMS 请求 Zygote 创建新进程(Socket)

当 AMS 发现目标进程不存在时:

java 复制代码
AMS.startProcessLocked() 
    → Process.start() 
    → ZygoteProcess.startViaZygote()
    → 通过 Socket 连接 Zygote 进程,发送 fork 参数
  • 为什么用 Socket 而非 Binder?
    • Zygote 进程在启动时初始化并预加载了大量类和资源,需要保持"干净"状态
    • 如果使用 Binder,Zygote 需注册到 ServiceManager,会引入额外依赖
    • Socket 通信更简单、开销更小,且 fork 后子进程无需继承 Binder 线程池的复杂状态
  • Zygote 收到请求后,调用 fork() 创建子进程,子进程继承了预加载的环境,然后反射调用 ActivityThread.main() 作为应用进程入口

阶段 4:应用进程初始化(ActivityThread.main)

新创建的应用进程执行 ActivityThread.main():

java 复制代码
public static void main(String[] args) {
    // 1. 初始化主线程 Looper
    Looper.prepareMainLooper();
    
    // 2. 创建 ActivityThread 实例
    ActivityThread thread = new ActivityThread();
    thread.attach(false);  // 关键:向 AMS 注册
    
    // 3. 创建 ApplicationThread(Binder 服务端)
    // 4. 进入消息循环,等待 AMS 指令
    Looper.loop();
}
  • ActivityThread 是应用进程的主线程管理类,每个应用进程只有一个实例
  • ApplicationThread 是 ActivityThread 的内部类,继承 IApplicationThread.Stub,作为应用进程向 AMS 暴露的 Binder 服务端接口
  • thread.attach(false) 通过 Binder 调用 AMS 的 attachApplication() 方法,将ApplicationThread 的 Binder 代理注册到 AMS 下

阶段 5:AMS 回调应用进程创建 Application(Binder IPC)

AMS 收到 attachApplication() 后,通过 ApplicationThread 的代理回调应用进程:

java 复制代码
AMS.attachApplicationLocked()
    → ApplicationThreadProxy.bindApplication()  // Binder 跨进程调用
    → 应用进程 ApplicationThread.bindApplication()
    → sendMessage(H.BIND_APPLICATION, data)     // 向主线程 Handler 发消息
    → ActivityThread.handleBindApplication()

handleBindApplication() 的核心逻辑:

java 复制代码
private void handleBindApplication(AppBindData data) {
    // 1. 创建 LoadedApk(代表已加载的 APK)
    // 2. 创建 ContextImpl(应用级 Context)
    // 3. 反射创建 Instrumentation
    // 4. 创建 Application 实例
    Application app = data.info.makeApplication(false, mInstrumentation);
    
    // 5. 调用 Application.attachBaseContext() --- 最早的应用入口
    app.attach(context);  // 内部调用 attachBaseContext()
    
    // 6. 安装 ContentProviders(比 onCreate 更早)
    installContentProviders(app, data.providers);
    
    // 7. 调用 Application.onCreate()
    mInstrumentation.callApplicationOnCreate(app);
}

关键顺序:

attachBaseContext() → ContentProvider.onCreate() → Application.onCreate()

阶段 6:AMS 请求启动 Activity(Binder IPC)

Application 初始化完成后,AMS 再次通过 ApplicationThread 代理发送启动 Activity 的请求:

java 复制代码
AMS.realStartActivityLocked()
    → ClientTransaction.schedule()
    → ApplicationThreadProxy.scheduleLaunchActivity()  // Binder 跨进程
    → 应用进程 ApplicationThread.scheduleLaunchActivity()
    → sendMessage(H.LAUNCH_ACTIVITY, r)               // 向主线程发消息
    → ActivityThread.handleLaunchActivity()

阶段 7:应用进程创建 Activity 并执行 onCreate()

handleLaunchActivity() 调用 performLaunchActivity() 完成 Activity 创建:

java 复制代码
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 1. 创建 Activity 的 Context
    ContextImpl appContext = createBaseContextForActivity(r);
    
    // 2. 反射创建 Activity 实例
    Activity activity = mInstrumentation.newActivity(
        cl, component.getClassName(), r.intent);
    
    // 3. 获取 Application 实例
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
    // 4. 调用 Activity.attach() --- 创建 PhoneWindow、绑定 WindowManager
    activity.attach(appContext, this, getInstrumentation(), r.token, 
        r.ident, app, r.intent, r.activityInfo, title, r.parent, ...);
    
    // 5. 调用 Activity.onCreate()
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    // 6. 设置 Activity 状态为 ON_CREATE
    r.setState(ON_CREATE);
}

Activity.attach() 内部关键操作:

  • 调用 attachBaseContext(context) --- 绑定 Context
  • 创建 PhoneWindow --- 这是 Activity 的窗口实现
  • 创建 WindowManager --- 与系统窗口管理服务绑定
  • 初始化 FragmentController 等内部组件

Instrumentation.callActivityOnCreate() 最终调用:

java 复制代码
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    activity.performCreate(icicle);  // 内部调用 activity.onCreate(icicle)
}

三、关键类与角色总结

类/组件 所属进程 角色
Launcher Launcher 进程 桌面应用,接收点击事件,发起启动请求
ActivityManagerService (AMS) SystemServer 管理系统所有 Activity 的生命周期和进程
ActivityTaskManagerService (ATMS) SystemServer Android 10+ 负责 Activity 栈管理(从 AMS 拆分)
Zygote Zygote 进程 所有应用进程的父进程,通过 fork 快速创建新进程
ActivityThread 应用进程 应用主线程管理类,入口为 main()
ApplicationThread 应用进程 应用进程暴露给 AMS 的 Binder 服务端
IApplicationThread 接口定义 AMS 调用应用进程的 Binder 接口
Instrumentation 应用进程 应用进程的"管家",封装 Activity/Application 的创建和生命周期调用
ActivityRecord AMS 内部 AMS 中代表一个 Activity 实例的管理对象
ProcessRecord AMS 内部 AMS 中记录进程状态信息的对象

四、总结

点击图标后,Launcher 通过 Binder 请求 AMS → AMS 通过 Socket 让 Zygote fork 进程 →新进程通过 Binder 向 AMS 注册 → AMS 通过 Binder 回调应用进程创建 Application → 再回调创建Activity 并执行 onCreate()。整个过程经历了 2 次 Binder 往返 + 1 次 Socket 通信 + 多次 Handler 消息调度。

相关推荐
阿pin1 小时前
Android随笔-SELinux是什么?
android·selinux
红糖奶茶1 小时前
设备管理器中Android出现黄色感叹号怎么办? 如何修复?
android
取个名字太难了~1 小时前
从通用到专用:影像 SDK 的场景化封装与垂直行业落地实践
android·数码相机·美颜·相机连接·demu
zakariyaa331 小时前
Android 绘制调度机制
android·gitee
安卓修改大师2 小时前
安卓修改大师Smali语法实战:从零掌握数据类型、判断循环、自定义方法与Toast插桩
android
私人珍藏库2 小时前
[Android] 多开空间-一机多账号+应用一键克隆双开
android·人工智能·智能手机·软件
海兰2 小时前
【SpringBoot 】AOP企业级权限控制方案(二)
android·java·spring boot
阿pin2 小时前
Android随笔-启动Zygote的rc文件是什么?
android·zygote·rc
帅次12 小时前
Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题
android·java·面试