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

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui