一、引子:从 Activity 生命周期日志说起
在分析 Android Activity 的启动和销毁流程时,经常可以看到两类日志:
wm_*:由
system_server进程打印,反映系统侧 Activity 的生命周期状态调度。wm_on_*:由应用进程打印,反映应用侧生命周期回调的执行情况。
例如,在 Activity 销毁过程中,可能观察到以下日志顺序:

Activity 的销毁并不是由应用进程独立完成的,而是 system_server 与应用进程相互配合的结果。
系统首先决定 Activity 是否需要退出,然后通知应用进程执行对应的生命周期回调。应用进程执行完成后,再将执行结果反馈给系统,由系统决定是否继续推进下一阶段。
因此,本文主要研究以下几个问题:
-
应用调用
finish()后,如何通知system_server? -
system_server如何维护 Activity 的生命周期状态? -
系统如何通过
ClientTransaction通知应用执行生命周期? -
为什么 Activity 的销毁需要经过 PAUSING、PAUSED、STOPPING 等状态?
-
系统如何确认一个 Activity 已经完成销毁?
本文以一个处于 RESUMED 状态的 Activity 主动调用 finish() 为例进行分析。
二、整体架构:谁负责决策,谁负责执行?
在分析具体源码之前,首先需要理解 Android Activity 生命周期的管理架构。
1. 系统侧决策
system_server 通过 ActivityTaskManagerService、ActivityRecord、ActivityStack 等对象管理 Activity 的状态。
它负责判断:
当前 Activity 处于什么状态?
是否需要先执行 pause?
是否需要等待其他 Activity 恢复?
是否可以立即销毁?
2 . 应用侧执行
应用进程收到命令后,由 ActivityThread 和 TransactionExecutor 执行对应操作,最终调用 Activity 的生命周期方法。
4. 应用反馈系统
应用执行完成后,在需要反馈的阶段通过 Binder 通知 system_server。
三、Activity 的两套状态
理解销毁流程之前,需要区分两个容易混淆的概念。
3.1 系统侧 ActivityRecord 的状态
源码位置:frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
ActivityRecord 维护了一个 mState 字段,用于记录系统侧 Activity 的生命周期状态。
相关状态包括:INITIALIZING STARTED RESUMED PAUSING PAUSED STOPPING
STOPPED FINISHING DESTROYING DESTROYED
系统通过 setState() 更新状态。
prev.setState(PAUSING, "startPausingLocked");
3.2 应用侧 Activity 的生命周期
应用进程维护自己的 Activity 实例,并通过 ActivityThread 执行:
onCreate()
onStart()
onResume()
onPause()
onStop()
onDestroy()
系统侧 ActivityRecord.mState 与应用侧生命周期存在对应关系,但两者并不等价,也不一定同时更新。
另外,Activity 不是线程。Activity 是运行在应用进程中的组件对象,生命周期回调通常在应用主线程执行。销毁 Activity 不等于销毁主线程或应用进程。
四、第一阶段:finish() 请求系统结束 Activity
假设当前 Activity 处于 RESUMED 状态,应用主动调用finish();
4.1 应用进程调用 finish()
源码:
frameworks/base/core/java/android/app/Activity.java
核心调用:
ActivityTaskManager.getService().finishActivity(
mToken,
resultCode,
resultData,
finishTask
);
这里通过 Binder 跨进程调用 system_server。
其中 mToken 用于标识当前 Activity,使系统能够找到对应的 ActivityRecord。
4.2 system_server 接收请求
源码:
ActivityTaskManagerService.java
入口:
finishActivity(...)
随后进入:
ActivityRecord.finishIfPossible(...)
在这里,系统开始处理 Activity 的结束请求。
其中一个关键操作:
makeFinishingLocked();
将 ActivityRecord.finishing 标记为 true。
这里需要区分:
finishing = true:表示当前 Activity 已被标记为需要结束。
mState = FINISHING:表示 ActivityRecord 进入特定生命周期管理状态。
此处还会打印:
EventLogTags.writeWmFinishActivity(...);
对应日志:
wm_finish_activity:[0,47338819,278,com.xxxxxx app-request]
这条日志表示系统已经开始处理 Activity 的结束请求,并不意味着 onDestroy() 已经执行。
五、第二阶段:RESUMED → PAUSING → PAUSED
5.1 系统开始执行 pause
当前 Activity 处于 RESUMED 状态,系统需要先让它暂停。
源码:
ActivityStack.java
关键函数:
startPausingLocked(...)
系统首先执行:
prev.setState(PAUSING, "startPausingLocked");
随后打印:
wm_pause_activity
然后通过:
mAtmService.getLifecycleManager()
.scheduleTransaction(
prev.app.getThread(),
prev.appToken,
PauseActivityItem.obtain(...)
);
向应用进程发送 PauseActivityItem。
5.2 应用进程执行 PauseActivityItem
系统侧调用:
ClientLifecycleManager.scheduleTransaction()
↓
ClientTransaction.schedule()
↓ Binder
ApplicationThread.scheduleTransaction()
应用进程收到 Binder 请求后,并不是直接在 Binder 线程执行 onPause()。
而是将事务投递到应用主线程:
ApplicationThread.scheduleTransaction()
↓
ActivityThread.sendMessage(EXECUTE_TRANSACTION)
↓
ActivityThread.H.handleMessage()
↓
TransactionExecutor.execute()
↓
PauseActivityItem.execute()
↓
ActivityThread.handlePauseActivity()
↓
Instrumentation.callActivityOnPause()
↓
Activity.onPause()
这也说明:
Binder 负责跨进程传递命令,ActivityThread 负责在应用主线程执行生命周期。
5.3 应用执行完成后反馈系统
PauseActivityItem 中除了 execute(),还存在 postExecute()。
在执行完暂停操作后,应用通过:
ActivityTaskManager.getService()
.activityPaused(token);
通知 system_server。
系统接收到回调后,最终进入:
ActivityStack.completePauseLocked(...)
更新状态:
prev.setState(PAUSED, "completePausedLocked");
至此,系统侧完成:
RESUMED → PAUSING → PAUSED
这里体现出一个重要机制:
系统先将 Activity 标记为 PAUSING,再通知应用执行 onPause(),最后根据应用反馈完成 PAUSED 状态的确认。
六、第三阶段:PAUSED → STOPPING
在 completePauseLocked() 中,系统会继续判断 Activity 是否需要结束。
由于前面已经执行:
makeFinishingLocked();
因此:
prev.finishing == true
系统会进入后续结束处理逻辑。
关键函数:
ActivityRecord.completeFinishing(...)
在本文研究的路径中,经过条件判断后进入:
addToStopping(...)
将 Activity 加入:
ActivityStackSupervisor.mStoppingActivities
并更新系统侧状态:
setState(STOPPING, "completeFinishing");
需要注意,这一步主要是系统内部的状态调度。
将 ActivityRecord 设置为 STOPPING,不等于应用已经执行了 onStop()。
这里还有一个重要问题:
为什么系统不在 Activity pause 完成后立即销毁它,而是先加入等待处理的集合?
因为 Activity 的结束还可能受到其他 Activity 的启动、恢复、窗口切换和可见性等条件影响。
系统需要协调这些操作,而不是简单地连续调用所有生命周期方法。
七、第四阶段:STOPPING → FINISHING → DESTROYING
后续在处理等待停止和结束的 Activity 时,会进入:
ActivityStackSupervisor.java
关键函数:
processStoppingAndFinishingActivities(...)
这里会检查待处理 Activity 的状态以及 finishing 标记。
对于符合条件、需要结束的 Activity,继续执行销毁流程。
关键函数:
ActivityRecord.destroyIfPossible(...)
在本文所分析的路径中,系统可能先执行:
setState(FINISHING, "destroyIfPossible");
随后进入实际销毁调度。
关键函数:
destroyImmediately(...)
这里会打印:
EventLogTags.writeWmDestroyActivity(...);
对应日志:wm_destroy_activity
这条日志说明系统开始调度销毁,但并不代表应用已经执行完 onDestroy()。
7.1 系统发送 DestroyActivityItem
如果 Activity 仍关联着有效的应用进程,系统可以通过:
mAtmService.getLifecycleManager()
.scheduleTransaction(
app.getThread(),
appToken,
DestroyActivityItem.obtain(
finishing,
configChangeFlags
)
);
通知应用执行销毁。
然后系统侧将状态设置为:
setState(
DESTROYING,
"destroyActivityLocked. finishing and not skipping destroy"
);
此时系统处于等待或处理销毁完成的阶段。
八、第五阶段:应用执行 onDestroy()
应用进程收到 DestroyActivityItem 后,进入:
TransactionExecutor.execute()
↓
executeLifecycleState()
↓
DestroyActivityItem.execute()
↓
ActivityThread.handleDestroyActivity()
↓
ActivityThread.performDestroyActivity()
↓
Instrumentation.callActivityOnDestroy()
↓
Activity.onDestroy()
8.1 cycleToPath() 的作用
在执行最终生命周期请求前,TransactionExecutor 可能调用:
cycleToPath(
r,
lifecycleItem.getTargetState(),
true,
transaction
);
它的作用是根据应用侧记录的当前生命周期状态和目标状态,计算需要补齐的中间生命周期操作。
例如,当应用侧尚未执行 onStop(),但需要进入销毁阶段时,执行器可能先补齐停止操作。
ActivityRecord.mState:system_server 维护的状态。
ActivityClientRecord的生命周期状态:应用进程用于执行事务的状态。
cycleToPath():根据应用侧状态计算生命周期执行路径。因此,不能直接把系统侧
FINISHING状态当作cycleToPath()的输入状态。
是否需要补齐中间生命周期,还需要结合 TransactionExecutor、TransactionExecutorHelper 和应用侧当前状态具体分析。
8.2 Activity.onDestroy() 执行
最终通过:
mInstrumentation.callActivityOnDestroy(r.activity);
调用应用中的:
Activity.onDestroy();
至此,应用侧完成对应的销毁回调。
但是,这并不意味着系统侧已经完成 ActivityRecord 的销毁管理。
九、第六阶段:DESTROYING → DESTROYED
对于正常完成的销毁流程,应用还需要向系统反馈。
通过:
ActivityTaskManager.getService()
.activityDestroyed(token);
跨进程通知 system_server。
系统进入:
ActivityTaskManagerService.activityDestroyed()
↓
ActivityRecord.destroyed(...)
↓
removeFromHistory()
在相关清理路径中更新:
setState(DESTROYED, "removeFromHistory");
这里需要注意,ActivityRecord 可能随后被移出任务历史并清理关联关系,因此 DESTROYED 不代表系统会长期保留这个 ActivityRecord。
至此,本文所分析的正常 finish 销毁流程完成。
十、总结:Activity 生命周期到底由谁控制?
通过上述分析,可以将整个过程整理为:
应用进程 system_server
Activity.finish()
────────────────────────→ finishActivity()
↓
finishIfPossible()
↓
finishing = true
↓
mState = PAUSING
←──────────────────────── PauseActivityItem
Activity.onPause()
────────────────────────→ activityPaused()
↓
mState = PAUSED
↓
completeFinishing()
↓
mState = STOPPING
↓
等待后续处理条件
↓
destroyIfPossible()
↓
mState = FINISHING
←──────────────────────── DestroyActivityItem
应用侧补齐必要生命周期
↓
Activity.onDestroy()
────────────────────────→ activityDestroyed()
↓
清理 ActivityRecord
↓
DESTROYED
上述是本文研究的其中一条典型路径,并不是所有 Activity 都必须严格经过完全相同的状态顺序。
从架构上看,Android 将 Activity 生命周期的决策权放在 system_server,将实际生命周期回调的执行放在应用进程。
系统通过
ActivityRecord维护管理状态,通过ClientTransaction下发执行命令,应用通过 Binder 回调向系统反馈执行结果。这套机制使系统能够统一协调多个 Activity、多个 Task 和多个应用进程之间的生命周期切换,而不是由应用自行决定所有状态变化。