Android 16(API Level 36)Activity 启动流程源码级解析

本文基于 Android 16(API Level 36)AOSP 源码,全文 8000+ 字,建议收藏。

startActivity()Activity.onResume(),再到首帧显示,完整追踪一次 Activity 启动链路。

一、前言

Activity 启动流程是 Android Framework 中最经典、也最容易被追问的链路之一。

常见问题包括:

  • startActivity() 到底经历了什么?

  • Instrumentation 为什么能 Hook Activity 启动?

  • AMSATMS 分别负责什么?

  • ActivityThread 是什么?

  • Application.onCreate()Activity.onCreate() 谁先执行?

  • LaunchMode 在哪里生效?

  • onResume() 执行后界面是否已经显示?

  • Android 16 对 Activity 启动有什么影响?

本文基于 Android 16(API Level 36)的 Framework 源码结构来分析。

先给结论:

Android 16 中,Activity 启动主链路并没有被重写。核心仍然是:应用进程通过 Instrumentation 发起请求,System Server 中的 ActivityTaskManagerServiceActivityStarter 负责启动决策,目标进程中的 ActivityThread 负责创建 Activity 并执行生命周期。

整体链路如下:

复制代码
Activity.startActivity()
  ↓
Instrumentation.execStartActivity()
  ↓ Binder
ActivityTaskManagerService
  ↓
ActivityStarter
  ↓
Task / RootWindowContainer
  ↓
ClientTransaction
  ↓ Binder
ActivityThread
  ↓
LaunchActivityItem
  ↓
performLaunchActivity()
  ↓
Activity.attach()
  ↓
Activity.onCreate()
  ↓
Activity.onStart()
  ↓
Activity.onResume()
  ↓
WindowManagerGlobal.addView()
  ↓
ViewRootImpl.setView()
  ↓ Binder
WindowManagerService.addWindow()
  ↓
ViewRootImpl.performTraversals()
  ↓
首帧显示

二、整体架构

一次 Activity 启动可以分成四个阶段:

复制代码
阶段一:App 进程发起启动请求
阶段二:System Server 解析 Intent、校验权限、处理 Task 和启动模式
阶段三:目标 App 进程接收生命周期事务,创建 Activity
阶段四:执行 onCreate / onStart / onResume,并进入窗口显示流程

对应进程关系:

复制代码
┌────────────────────┐
│    App Process      │
│ startActivity()     │
└─────────┬──────────┘
          │ Binder
          ▼
┌────────────────────┐
│   System Server     │
│ ATMS / ActivityStarter
└─────────┬──────────┘
          │ Binder
          ▼
┌────────────────────┐
│ Target App Process  │
│ ActivityThread      │
└─────────┬──────────┘
          ▼
onCreate → onStart → onResume
          ▼
WindowManager / ViewRootImpl
          ▼
WMS / SurfaceFlinger
          ▼
首帧显示

重点:

App 进程负责发起请求,System Server 负责决策,目标 App 进程负责真正创建 Activity 和执行生命周期。


三、startActivity 与 Instrumentation

开发者通常这样启动页面:

java 复制代码
Intent intent = new Intent(this, DetailActivity.class);
startActivity(intent);

进入 Activity 后,大致链路是:

java 复制代码
Activity.startActivity()
  ↓
Activity.startActivityForResult()
  ↓
Instrumentation.execStartActivity()

Activity 自己并不会直接完成启动,它会把启动请求交给 Instrumentation

Instrumentation 是应用进程内非常关键的代理类。它参与:

  • 发起 Activity 启动:execStartActivity()

  • 创建 Activity 实例:newActivity()

  • 回调 Activity 生命周期:callActivityOnCreate()

  • 回调 Application 生命周期:callApplicationOnCreate()

🔍 源码印证:Instrumentation.execStartActivity()

java 复制代码
// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // ...
    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        int result = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(),
                        intent, intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        // 关键:检查启动结果,失败会抛异常(ActivityNotFoundException 等)
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

在启动阶段,关键动作是:

复制代码
Instrumentation.execStartActivity()
  ↓
ActivityTaskManager.getService().startActivity()

ActivityTaskManager.getService() 返回的是 System Server 中 ActivityTaskManagerService 的 Binder 代理。

所以从进程角度看:

复制代码
App 进程
  ↓ Binder
System Server

重点:

Instrumentation.execStartActivity() 是应用进程侧启动 Activity 的关键入口,所以插件化框架、自动化测试框架经常会从这里 Hook。checkStartActivityResult() 会在启动失败时抛出明确的异常(如 ActivityNotFoundException),这是开发者经常遇到的运行时异常来源。


四、ATMS 与 ActivityStarter

Android 10 之后,Activity 和 Task 管理从早期 ActivityManagerService 中拆分出来,主要由:

复制代码
ActivityTaskManagerService

负责,简称 ATMS

AMSATMS 大致分工是:

复制代码
AMS:进程、Service、Broadcast、Provider 等管理
ATMS:Activity、Task、窗口层级、Activity 生命周期调度

但两者并不是完全割裂的。比如冷启动时,目标进程不存在,仍然需要 AMS / ProcessList 协助启动应用进程。

Activity 启动请求进入 ATMS 后,大致链路是:

复制代码
ActivityTaskManagerService.startActivity()
  ↓
startActivityAsUser()
  ↓
ActivityStartController.obtainStarter()
  ↓
ActivityStarter.execute()

ActivityStarter 是 Activity 启动链路中最核心的决策类之一。AOSP 中对它的职责描述是:负责解释如何把一个 Intent 和启动 flags 转换成对应的 Activity、Task 和 Root Task。

它主要处理:

  • Intent 解析

  • Activity 是否存在

  • 权限检查

  • exported 检查

  • 后台启动限制检查

  • LaunchMode

  • Intent Flags

  • taskAffinity

  • 是否复用已有 Task

  • 是否复用已有 Activity

  • 是否创建新的 ActivityRecord

核心链路大致是:

复制代码
ActivityStarter.execute()
  ↓
executeRequest()
  ↓
startActivityUnchecked()
  ↓
startActivityInner()

🔍 源码印证:ActivityStarter 入口

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
    try {
        // 解析 Intent、权限校验等
        res = executeRequest(request);
    } finally {
        onExecutionComplete();
    }
    return res;
}

private int executeRequest(Request request) {
    // 1. 解析 Intent 到 ComponentName
    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
    // 2. 权限检查
    int res = mService.getPermissionPolicy().checkStartActivity(...);
    // 3. 创建 ActivityRecord
    ActivityRecord r = new ActivityRecord.Builder(...).build();
    // 4. 进入启动决策核心
    return startActivityUnchecked(r, sourceRecord, ...);
}

重点:

ActivityStarter 是 Activity 启动决策核心,决定"能不能启动、启动到哪个 Task、创建还是复用"。


五、LaunchMode、Flags 与 Task 决策

常见启动模式包括:

复制代码
standard
singleTop
singleTask
singleInstance
singleInstancePerTask

这些启动模式不是在 Activity 自己内部生效,而是在 System Server 的启动决策阶段生效。

也就是说:

复制代码
ActivityStarter / Task 相关逻辑
  ↓
决定创建新实例,还是复用已有实例

例如:

  • standard:通常创建新 Activity 实例。

  • singleTop:如果目标 Activity 已经位于栈顶,则复用并回调 onNewIntent()

  • singleTask:查找符合条件的已有 Task,可能复用已有 Activity,并清理其上的 Activity。

  • singleInstancePerTask:每个 Task 中只允许一个该 Activity 实例。

🔍 源码印证:startActivityUnchecked 中的启动模式判断

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        ...) {
    // 根据 launchMode 和 flags 设置启动标志
    setInitialState(r, sourceRecord, ...);
    
    // singleTop / FLAG_ACTIVITY_SINGLE_TOP 判断
    if ((mLaunchMode == LAUNCH_SINGLE_TOP || mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP != 0)
            && r.isTopRunningActivity()) {
        // 栈顶复用分支,最终会回调 onNewIntent()
        return deliverToCurrentTopIfNeeded(r, sourceRecord);
    }
    
    // singleTask / singleInstance / FLAG_ACTIVITY_NEW_TASK 处理
    if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
            || mLaunchMode == LAUNCH_SINGLE_TASK
            || mLaunchMode == LAUNCH_SINGLE_INSTANCE
            || mLaunchMode == LAUNCH_SINGLE_INSTANCE_PER_TASK) {
        // 查找可复用的 Task 或 Activity
        findOrCreateTask(r, sourceRecord);
    }
    
    // 继续执行启动流程
    return startActivityInner(...);
}

startActivityUnchecked() 和后续 Task 逻辑会综合判断:

  • launchMode

  • Intent FlagsFLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_SINGLE_TOP

  • taskAffinity

  • 调用方所在 Task

  • 目标 Activity 是否已有实例

  • 是否指定 ActivityOptions

最终决定:

复制代码
创建新的 ActivityRecord
或复用已有 ActivityRecord
或创建新 Task
或复用已有 Task
或把已有 Task 移到前台

重点:

singleTask 不是在 Activity.onCreate() 里生效的,而是在 ActivityStarter.startActivityUnchecked() 的源码分支中生效的。


六、Android 16:后台启动限制与 Intent 安全

Android 16 没有重写 Activity 启动主链路,但它在"是否允许启动"这个安全边界上有值得关注的变化。

1. 后台 Activity 启动限制

官方文档把后台 Activity 启动称为:

复制代码
Background Activity Launch,简称 BAL

它指的是:

复制代码
一个没有前台可见 Activity 的应用,或者通过其他应用传来的 PendingIntent,尝试启动新的 Activity。

后台 Activity 启动限制从 Android 10 就已经存在。Android 16 相关的重点是:SDK 36 新增了更推荐的 PendingIntent 授权模式:

复制代码
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE

它的含义是:

只有发送 PendingIntent 的应用当前可见时,才允许把后台启动 Activity 的能力传递出去。

示例:

java 复制代码
val options = ActivityOptions.makeBasic().apply {
    pendingIntentBackgroundActivityStartMode =
        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE
}

pendingIntent.send(options.toBundle())

🔍 源码印证:后台启动检查入口

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int executeRequest(Request request) {
    // ...
    // 后台 Activity 启动限制检查
    if (mService.mBackgroundActivityStartController != null) {
        int balResult = mService.mBackgroundActivityStartController
                .checkBackgroundActivityStart(callingUid, callingPid, callingPackage,
                        callingRealUid, callingRealPid, intent, resolvedType,
                        activityInfo, resultTo, options, mRequest.startResult);
        if (balResult != ActivityManager.START_SUCCESS) {
            return balResult;
        }
    }
    // ...
}

这意味着分析 Android 16 上的 Activity 启动失败时,不能只看 Intent 和 Manifest,还要看:

  • 调用方是否处于前台或满足 BAL 例外条件

  • 是否通过 PendingIntent 启动

  • PendingIntent 创建方是否授权

  • PendingIntent 发送方是否授权

  • 授权模式是否符合当前可见状态

2. StrictMode 诊断

Android 16 还提供了一个与后台 Activity 启动相关的调试能力:

java 复制代码
StrictMode.setVmPolicy(
    StrictMode.VmPolicy.Builder()
        .detectBlockedBackgroundActivityLaunch()
        .penaltyLog()
        .build()
)

它可以帮助开发者发现:

  • 当前被系统拦截的后台 Activity 启动

  • 未来 targetSdk 升级后可能被拦截的启动行为

3. Intent Redirection 安全增强

Android 16 官方文档还提到,对 Intent Redirection 攻击提供默认安全增强。

Intent Redirection 指的是:攻击者控制一个嵌套 Intent,让受害 App 在自己的上下文中启动这个不可信 Intent,从而访问私有组件、触发敏感操作或获取 URI 权限。

典型风险代码类似:

Kotlin 复制代码
val subIntent = intent.getParcelableExtra<Intent>("sub_intent")
startActivity(subIntent)

Android 16 提供默认防护,并提供新的 opt-out API:

java 复制代码
subIntent.removeLaunchSecurityProtection()

但官方也强调,只有在明确知道风险并确认合法场景时才应该 opt-out。

🔍 源码印证:Intent Redirection 检查位置

虽然 AOSP 中该检查的具体实现位于 IntentActivityStarter 的权限校验阶段,但核心逻辑是在 System Server 解析嵌套 Intent 时,验证目标组件是否与原始 Intent 的授权范围匹配。大致位置如下:

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int resolveIntentAndActivity(...) {
    // ...
    // Android 16 新增:Intent Redirection 安全检查
    if (!isIntentRedirectionAllowed(intent, callingUid)) {
        return START_INTENT_REDIRECTION_NOT_ALLOWED;
    }
    // ...
}

重点:

Android 16 的这些变化影响的是 Activity 启动的合法性和安全边界,不是 startActivity()ActivityThread 的主链路重构。


七、realStartActivityLocked 与 ClientTransaction

ActivityStarter 完成启动决策后,会进入 Task 和窗口容器相关流程。

现代 Android 中,Activity 栈围绕下面这些对象组织:

复制代码
RootWindowContainer
TaskDisplayArea
Task
TaskFragment
ActivityRecord

其中:

  • RootWindowContainer:窗口和任务层级的根容器。

  • TaskDisplayArea:Display 上承载 Task 的区域。

  • Task:任务栈。

  • TaskFragment:Task 内更细粒度的 Activity 容器。

  • ActivityRecord:System Server 中对 Activity 的服务端描述。

App 进程中的一个 Activity 实例,在 System Server 中对应一个 ActivityRecord

典型链路是:

复制代码
RootWindowContainer.resumeFocusedTasksTopActivities()
  ↓
Task.resumeTopActivityUncheckedLocked()
  ↓
TaskFragment.resumeTopActivity()
  ↓
realStartActivityLocked()

当系统决定真正启动目标 Activity 时,realStartActivityLocked() 会构造 ClientTransaction,然后通过 Binder 发送给目标应用进程。

可以理解为:

复制代码
System Server 不直接执行 Activity.onCreate()
而是发送生命周期事务给 App 进程
由 App 主线程自己执行生命周期

🔍 源码印证:ClientTransaction 的构造与发送

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
    // ...
    // 创建客户端事务
    final ClientTransaction clientTransaction = ClientTransaction.obtain(
            proc.getThread(), r.token);
    
    // 添加 LaunchActivityItem(负责 onCreate)
    clientTransaction.addCallback(LaunchActivityItem.obtain(
            new Intent(r.intent), System.identityHashCode(r), r.info,
            new Configuration(mService.getGlobalConfiguration()),
            r.overrideConfig, r.compat, r.launchedFromPackage,
            r.task.voiceInteractor, proc.getReportedProcState(),
            r.icicle, r.persistentState, results, newIntents,
            r.isForward, proc.getProfilerInfo(), r.assistToken,
            r.shareableActivityToken, r.getTargetSdkVersion(),
            r.getProcessLimitInfo()));
    
    // 设置最终生命周期状态为 RESUMED(包含 onStart 和 onResume)
    if (andResume) {
        clientTransaction.setLifecycleStateRequest(
                ResumeActivityItem.obtain(r.isForward,
                        r.shouldSendCompatFakeFocus()));
    }
    
    // 通过 Binder 发送给目标进程
    clientTransaction.schedule();
    // ...
}

典型事务包含:

复制代码
LaunchActivityItem
ResumeActivityItem

早期 Android 使用 ActivityThread.H.LAUNCH_ACTIVITY 这类 Handler 消息调度 Activity 启动。Android P 之后,引入了更统一的 ClientTransaction,把客户端生命周期操作封装成事务。

一次 Activity 启动可以理解为:

复制代码
ClientTransaction
  ├── callback: LaunchActivityItem
  └── lifecycleStateRequest: ResumeActivityItem

其中:

  • LaunchActivityItem:负责创建 Activity,并执行 onCreate()

  • ResumeActivityItem:负责把 Activity 推进到 Resumed 状态。

需要注意:

onStart() 不一定需要 System Server 单独下发一个 StartActivityItem。当生命周期从 Created 推进到 Resumed 时,TransactionExecutor 会根据生命周期路径执行中间状态,因此会触发 onStart()


八、冷启动:进程创建与 Application.onCreate

如果目标 Activity 所在进程还不存在,System Server 不能直接发送 LaunchActivityItem,必须先启动应用进程。

大致流程是:

复制代码
ATMS / AMS
  ↓
ProcessList.startProcessLocked()
  ↓
ZygoteProcess.start()
  ↓
Zygote fork
  ↓
ActivityThread.main()

新进程启动后,会进入:

复制代码
ActivityThread.main()

🔍 源码印证:ActivityThread.main()

java 复制代码
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    // 1. 创建主线程 Looper
    Looper.prepareMainLooper();
    
    // 2. 创建 ActivityThread 实例
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    
    // 3. 获取主线程 Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    
    // 4. 启动 Looper 循环
    Looper.loop();
    
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

这里会:

  • 创建主线程 Looper

  • 创建 ActivityThread

  • 调用 attach()

  • 通过 Binder 告诉系统进程:应用进程已经启动

随后进入应用绑定流程:

复制代码
ActivityThread.main()
  ↓
ActivityThread.attach()
  ↓ Binder
ActivityManager.getService().attachApplication()
  ↓
ActivityManagerService.attachApplication()
  ↓
AMS / ATMS 协作完成应用绑定与 Activity 启动恢复
  ↓
ApplicationThread.bindApplication()
  ↓
ActivityThread.handleBindApplication()
  ↓
创建 Application
  ↓
Instrumentation.callApplicationOnCreate()
  ↓
Application.onCreate()

然后才是:

复制代码
LaunchActivityItem
  ↓
ActivityThread.handleLaunchActivity()
  ↓
performLaunchActivity()
  ↓
Activity.onCreate()

所以结论是:

复制代码
Application.onCreate()
  ↓
Activity.onCreate()

重点:

冷启动时,Application.onCreate() 先于 Activity.onCreate()Application.onCreate() 主要发生在 ActivityThread.handleBindApplication() 阶段,而不是简单地说发生在 performLaunchActivity() 中。


九、ActivityThread 与 performLaunchActivity

目标 App 进程中,真正处理生命周期事务的是:

复制代码
ActivityThread

链路大致是:

复制代码
ApplicationThread.scheduleTransaction()
  ↓
ClientTransactionHandler.scheduleTransaction()
  ↓
ActivityThread.H 发送消息
  ↓
TransactionExecutor.execute()
  ↓
LaunchActivityItem.execute()
  ↓
ActivityThread.handleLaunchActivity()
  ↓
performLaunchActivity()

ActivityThread 虽然名字里有 Thread,但它不是普通意义上的线程类,而是 App 主线程的核心管理者。

performLaunchActivity() 是 Activity 实例真正创建的关键方法,主要做四件事。

🔍 源码印证:performLaunchActivity() 核心流程

java 复制代码
// frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 1. 创建 Activity 的 Context(ContextImpl)
    ContextImpl appContext = createBaseContextForActivity(r);
    
    // 2. 反射创建 Activity 实例
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    } catch (Exception e) {
        throw new RuntimeException("Unable to instantiate Activity", e);
    }
    
    // 3. 调用 Activity.attach(),绑定 Window、Application 等
    activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, title, r.parent,
            r.embeddedID, r.lastNonConfigurationInstances, config,
            r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
            r.assistToken, r.shareableActivityToken);
    
    // 4. 回调 Activity.onCreate()
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    return activity;
}

1. 创建 Activity 的 Context

系统会为 Activity 创建专属 ContextImpl

复制代码
createBaseContextForActivity()

这个 Context 会绑定:

  • LoadedApk

  • Resources

  • Display

  • Configuration

  • Activity token

2. 反射创建 Activity

Activity 实例通过 Instrumentation 创建:

复制代码
Instrumentation.newActivity()

🔍 源码印证:Instrumentation.newActivity()

java 复制代码
// frameworks/base/core/java/android/app/Instrumentation.java
public Activity newActivity(ClassLoader cl, String className, Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    // 反射加载并实例化 Activity
    return (Activity) cl.loadClass(className).newInstance();
}

内部会使用 ClassLoader:

复制代码
ClassLoader.loadClass()
  ↓
Constructor.newInstance()

所以 Activity 本质上是在应用进程内,通过 ClassLoader 反射创建的对象。

3. 调用 Activity.attach()

Activity 对象创建后,会调用:

复制代码
activity.attach(...)

这里会绑定很多核心对象:

  • Context

  • Application

  • Instrumentation

  • Activity token

  • Window(创建 PhoneWindow)

  • WindowManager

  • FragmentController

其中非常关键的是 PhoneWindow,通常会在 Activity.attach() 阶段创建。

🔍 源码印证:Activity.attach() 中创建 PhoneWindow

java 复制代码
// frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ...) {
    attachBaseContext(context);
    // 关键:创建 PhoneWindow
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    // ...
}

所以在 onCreate() 中调用:

复制代码
getWindow()

是可用的。

4. 回调 Activity.onCreate()

最后通过:

复制代码
Instrumentation.callActivityOnCreate()
  ↓
Activity.performCreate()
  ↓
Activity.onCreate()

执行开发者写的 onCreate()

重点:

performLaunchActivity() 创建 Activity 对象,完成 attach,然后通过 Instrumentation 回调 onCreate()


十、Window、onResume 与首帧显示

Activity.attach() 中会创建 PhoneWindow,但这不代表界面已经显示。

开发者在 onCreate() 中调用:

java 复制代码
setContentView(R.layout.activity_main);

大致会进入:

复制代码
Activity.setContentView()
  ↓
PhoneWindow.setContentView()
  ↓
PhoneWindow.installDecor()
  ↓
DecorView 创建 / 内容布局加载

结构大致是:

复制代码
PhoneWindow
  ↓
DecorView
  ↓
ContentParent
  ↓
开发者布局 View

重点:

setContentView() 只是把布局加载到 DecorView 中,不代表 View 已经完成 measure、layout、draw。

LaunchActivityItem 执行完后,TransactionExecutor 会继续根据目标生命周期状态推进。如果目标状态是 RESUMED,生命周期会从:

复制代码
ON_CREATE
  ↓
ON_START
  ↓
ON_RESUME

依次推进。

大致调用是:

复制代码
handleStartActivity()
  ↓
Activity.performStart()
  ↓
Activity.onStart()

然后:

复制代码
handleResumeActivity()
  ↓
performResumeActivity()
  ↓
Activity.performResume()
  ↓
Activity.onResume()

🔍 源码印证:handleResumeActivity 与 onResume 后的窗口添加

java 复制代码
// frameworks/base/core/java/android/app/ActivityThread.java
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, String reason) {
    // 1. 执行 Activity.onResume()
    if (!performResumeActivity(r, finalStateRequest, reason)) {
        return;
    }
    
    // 2. 获取 DecorView
    View decor = r.window.getDecorView();
    decor.setVisibility(View.INVISIBLE);
    ViewManager wm = a.getWindowManager();
    WindowManager.LayoutParams l = r.window.getAttributes();
    
    // 3. 将 DecorView 添加到 WindowManager(关键!)
    if (r.activity.mVisibleFromClient) {
        r.activity.mVisibleFromServer = true;
        wm.addView(decor, l);
        // 注意:此时只是 addView,View 的测量/布局/绘制尚未执行
    }
}

更精确地说,onResume() 是在 handleResumeActivity() 中执行的。onResume() 返回后,ActivityThread 会继续在同一个主线程调度中,将 DecorView 通过本地调用交给 WindowManagerGlobal

复制代码
WindowManagerGlobal.addView()

随后应用进程内会创建 ViewRootImpl,并调用:

复制代码
ViewRootImpl.setView()

ViewRootImpl.setView() 内部会通过 Binder 调用 WMS:

复制代码
WindowManagerService.addWindow()

所以这段更准确的链路是:

复制代码
handleResumeActivity()
  ↓
performResumeActivity()
  ↓
Activity.onResume()
  ↓
WindowManagerGlobal.addView()
  ↓
创建 ViewRootImpl
  ↓
ViewRootImpl.setView()
  ↓ Binder
WindowManagerService.addWindow()

🔍 源码印证:首帧绘制的真正入口 performTraversals()

java 复制代码
// frameworks/base/core/java/android/view/ViewRootImpl.java
private void performTraversals() {
    // 这个方法在 onResume 之后,由 Choreographer 的 VSYNC 信号触发
    if (mLayoutRequested) {
        // 执行 measure
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    }
    if (mLayoutRequested) {
        // 执行 layout
        performLayout(lp, mWidth, mHeight);
    }
    // 执行 draw
    performDraw();
}

注意:

performTraversals() 不是 WMS 回调给 App 的方法,而是应用主线程在后续 VSYNC 驱动下执行的本地绘制流程。

完整首帧链路更接近:

复制代码
onResume()
  ↓
WindowManagerGlobal.addView()
  ↓
ViewRootImpl.setView()
  ↓
WMS.addWindow()
  ↓
Choreographer 等待 VSYNC
  ↓
ViewRootImpl.performTraversals()
  ↓
measure
  ↓
layout
  ↓
draw
  ↓
RenderThread
  ↓
SurfaceFlinger 合成
  ↓
屏幕显示首帧

重点:

onResume() 不是首帧完成的标志。从源码可以看到,onResume() 执行完毕后立即 执行 addView,但此时 View 的 onMeasure/onLayout/onDraw 尚未触发。首帧通常要等 ViewRootImpl.performTraversals() 执行,并经过渲染和合成后才真正显示到屏幕。


十一、完整时序图


十二、关键结论

1. startActivity 不是直接创建 Activity

startActivity() 最终会通过 Instrumentation.execStartActivity() 发起 Binder 调用,进入 System Server。从源码 Instrumentation.newActivity() 可以看出,Activity 实例不是在调用方直接创建的,而是在目标进程的 ActivityThread.performLaunchActivity() 中通过 ClassLoader 反射创建。

2. 启动决策发生在 System Server

ActivityStarter.startActivityUnchecked() 会综合判断:

复制代码
Intent
权限
exported
LaunchMode
Intent Flags
taskAffinity
Task 状态
后台启动限制

然后决定是否允许启动,以及创建还是复用 Activity / Task。

3. 生命周期由 App 主线程执行

System Server 不直接调用:

复制代码
Activity.onCreate()
Activity.onStart()
Activity.onResume()

realStartActivityLocked() 源码可以看到,它通过 ClientTransaction 把生命周期事务发送给目标 App 进程,由 ActivityThreadTransactionExecutor 在主线程执行。

4. Application.onCreate 先于 Activity.onCreate

冷启动时,ActivityThread.main() 会先执行 handleBindApplication() 触发 Application.onCreate(),之后才处理 LaunchActivityItem 执行 performLaunchActivity()Activity.onCreate()

所以不能简单地说 Application 是在 performLaunchActivity() 中才创建并执行 onCreate()

5. onResume 不等于首帧显示

handleResumeActivity() 源码可以看到,onResume() 返回后,会执行 wm.addView(decor, l),将 DecorView 添加到 WindowManager。但真正首帧显示还要经过 ViewRootImpl.performTraversals() 中的 measure/layout/draw,以及 SurfaceFlinger 合成。

6. Android 16 的重点是安全边界增强

Android 16 没有重写 Activity 启动主链路。它更值得关注的是:

  • PendingIntent 后台启动 Activity 的显式授权(MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLE

  • StrictMode.detectBlockedBackgroundActivityLaunch()

  • Intent Redirection 默认安全增强

这些影响的是"是否允许启动"和"如何诊断启动失败",不是生命周期主链路本身。


十三、不展开项与参考资料

以下内容虽然和 Activity 或窗口体验相关,但不属于本文启动主链路,因此不展开:

  1. Predictive Back

    Android 16 默认启用 Predictive Back 系统动画,并影响 onBackPressed()KEYCODE_BACK,但它属于返回导航链路,不属于 startActivity() 创建链路。

  2. Edge-to-edge 与大屏适配

    Android 16 对 edge-to-edge、大屏方向、宽高比、resizability 有行为变化,但它们主要影响窗口展示和适配,不改变 Activity 启动主流程。

  3. singleInstancePerTask 是否在 Android 16 更严格

    源码中存在相关处理,但没有足够证据证明这是 Android 16 特有变化,因此本文不把它作为 Android 16 新变化展开。

  4. 厂商 ROM 差异

    本文基于 AOSP 和官方文档,厂商 ROM 可能对窗口、任务、启动限制做定制。

参考资料:


相关推荐

Android 高级工程师面试参考答案:性能优化

Android 高级工程师面试参考答案:Framework、生命周期、View 与 Binder

相关推荐
chian-ocean2 小时前
Microi吾码:从零到服装ERP:低代码打造企业级系统的实战之旅
android·低代码·rxjava
故渊at4 小时前
第十五板块:Android 系统调试与逆向工程 | 第三十五篇:ART 虚拟机内部机制与 OAT 文件格式
android·虚拟机·art·机器码·oat文件格式
alexhilton10 小时前
Android的Agent优先时代:构建时vs运行时
android·kotlin·android jetpack
Cutecat_11 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
2601_9617652912 小时前
【分享】PlayerPro媒体音乐播放器 完整专业版
android·媒体
JohnnyDeng9414 小时前
【Android】Android 包体积优化:R8/ProGuard 深度配置全攻略
android·性能优化·kotlin·jetpack
故渊at14 小时前
第九板块:Android 多媒体体系 | 第二十四篇:Camera Service 与 HAL3 成像流水线
android·camera·多媒体体系·hal3
Jinkxs18 小时前
Python基础 - 初识内置函数 Python自带的便捷工具
android·java·python
私人珍藏库18 小时前
【Android】VLLO-韩国热门手机剪辑APP
android·app·工具·软件·多功能