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 消息调度。

相关推荐
执明wa1 天前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio
404_coder1 天前
源码视角下的 Android 开机流程:从 Zygote、SystemServer 到 Launcher
android
二流小码农1 天前
鸿蒙开发:以登录案例了解代码架构MVVM
android·ios·harmonyos
用户69371750013841 天前
从代码生产者到 AI 协作者:软件工程师的角色重构
android·前端·后端
GitLqr1 天前
别在 Flutter 的 main() 里乱锁屏幕方向,小心 iPad 分屏功能被你搞没了
android·flutter·ios
sg_knight1 天前
MySQL 存储过程详解:从入门到实战
android·数据库·mysql·database·dba·关系型数据库·db
爱笑鱼1 天前
Binder(四):ioctl(BINDER_WRITE_READ) 之后,事务怎样到达目标进程?
android
AFinalStone1 天前
Android 7系统休眠唤醒(二)开机全链路—BootROM到Launcher
android·电源管理·休眠唤醒
Mr YiRan1 天前
Android NDK开发之统计到未被回收的图片
android