Skip to content

App 冷启动全链路分析

一次 App 冷启动横跨 5 个进程、经历 14 个阶段,从用户手指触碰图标到界面可交互,整条链路可以归纳为三个大的阶段:

准备阶段 — 谁来做、在哪做。Launcher 通过 Binder 把 Intent 交给 system_server 的 ATMS;ATMS 在窗口层级树上创建 Task 和 ActivityRecord,同时创建一个 TRANSIT_OPEN 类型的 Shell Transition;随后并行触发两件事:通知 Launcher pause,以及通过 Zygote fork 出 App 新进程。两者都完成后,realStartActivityLocked()LaunchActivityItem 下发到 App。

绘制阶段 — 画什么、怎么画。App 走完 onCreate → onResume 生命周期后,ViewRootImpl 向 WMS 注册窗口(addWindow),等待 VSync 到来后执行 performTraversals():先通过 relayoutWindow() 创建 Surface(DrawState → DRAW_PENDING),再 measure → layout → drawThreadedRenderer 将绘制指令录制为 DisplayList,交由 RenderThread 驱动 GPU 渲染,最终通过 BLASTBufferQueue.queueBuffer() 将 GraphicBuffer 提交给 SurfaceFlinger。绘制完成后 finishDrawing() 通知 WMS,DrawState 一路推进到 HAS_DRAWN

上屏阶段 — 什么时候可见。BLASTSyncEngine 确认所有参与者就绪后,将收集到的 SyncTransaction 原子合并,通过 onTransactionReady() 交给 Shell。Shell 执行 startT.apply() 使 App Layer 在 SurfaceFlinger 中变为可见,随后播放开场动画(Launcher 淡出 / App 滑入)。动画结束时 finishT.apply() 恢复状态。最后 WMS 将焦点切换到新窗口,App 收到 onWindowFocusChanged(true)——启动完成。

本文定位:端到端串联文档。各阶段仅做链路级说明(做了什么、为什么、关键状态变化),详细源码分析链接到对应的专题文档。

涉及进程与模块

涉及进程与模块

进程关键模块职责
LauncherItemClickHandler, Activity, Instrumentation发起启动请求,执行 pause
system_serverATMS, ActivityStarter, AMS, ProcessList路由 Activity、管理生命周期、创建进程
system_serverWMS, WindowState, WindowStateAnimator, WindowSurfacePlacer窗口管理、Surface 创建、布局计算、DrawState 流转
system_serverTransitionController, Transition, BLASTSyncEngineShell Transition 动画协调、SyncGroup 同步
SystemUIWM Shell, Transitions, DefaultTransitionHandler动画执行(接收 TransitionInfo,驱动动画)
SystemUIStartingWindowController, SplashscreenWindowCreatorStartingWindow 创建与移除
ZygoteZygoteConnection, Zygotefork 新进程
AppActivityThread, Activity, ViewRootImpl, Choreographer生命周期、View 树创建、VSync 调度
AppThreadedRenderer, RenderThread, BLASTBufferQueue硬件加速渲染、缓冲区管理
SurfaceFlingerSurfaceFlinger, HWCLayer 合成、帧输出

两条 Transaction 路径

启动过程中存在两条不同的 SurfaceControl.Transaction 提交路径,理解它们的区别对排查问题至关重要:

路径Transaction 类型用途触发时机
Sync 路径SyncTransactionTransition 动画的原子提交BLASTSyncEngine.finishNow() 合并后通过 onTransactionReady() 交给 Shell,Shell 通过 startT.apply() 一次性提交
每帧路径PendingTransaction常规每帧 Surface 属性更新WindowAnimator.animate() 每帧遍历所有窗口,收集 Surface 变更后 mTransaction.apply()

相关文档SurfaceControl Transaction

总时序图

App 冷启动总时序

总调用链

总调用链

一、Launcher 发起启动请求(步骤 ①)

做了什么:用户点击图标后,Launcher 将触摸事件转化为 Intent,经过 Instrumentation.execStartActivity() 跨进程调用到 ActivityTaskManagerService.startActivity()

关键状态变化:无。

典型耗时:1~5ms(Binder IPC 开销)。

关键日志

Tag日志含义
ActivityTaskManagerSTART u0 {intent} from uid NATMS 收到启动请求

详细分析应用启动流程 §1.1 流程概览

二、ATMS 路由与窗口层级树操作(步骤 ②)

做了什么:ATMS 收到请求后,经过 ActivityStarter.execute() 完成以下操作:

  1. 解析请求参数Request.resolveActivity() 解析 resolveInfoactivityInfo
  2. 创建 ActivityRecord:Activity 在 system_server 的代表,同时也是一个 WindowToken
  3. 创建/获取 TaskgetOrCreateRootTask()DefaultTaskDisplayArea 下创建 Task
  4. 挂载 ActivityRecord 到 TasksetNewTask() + addOrReparentStartingActivity()
  5. 移动 Task 到顶部Task.moveToFront() 确保新启动的 Activity 在最上面
  6. 创建 Shell TransitionTransitionController.createTransition(TRANSIT_OPEN) 创建 Transition 并建立 SyncGroup
  7. 触发 StartingWindowTask.startActivityLocked()showStartingWindow() 添加启动窗口
  8. 触发 Launcher pause 和进程创建(并行)

关键状态变化

  • 窗口层级树新增 Task + ActivityRecord
  • Shell Transition 进入 Collecting 状态
  • StartingWindow 开始创建(异步,在 SystemUI 进程)

典型耗时:5~20ms。

关键日志

Tag日志含义
WindowManagerCreating Transition: TransitionRecord{id=N type=OPEN}Transition 创建
WindowManagerCollecting in transition N: ActivityRecord{...}ActivityRecord 被收集到 Transition

详细分析

ATMS 路由与 Transition 创建时序

三、Launcher Pause 与 Zygote Fork(步骤 ③,并行)

TaskFragment.resumeTopActivity() 同时触发两条并行路径:

③-A Launcher Pause

做了什么pauseBackTasks() 遍历所有叶子 Task,对 Launcher 构建 PauseActivityItem 触发 pause。Launcher 执行完 onPause() 后,通过 activityPaused() 通知 system_server。

关键状态变化:Launcher ActivityRecord 状态 → PAUSINGPAUSED

③-B Zygote Fork 新进程

做了什么startProcessAsync()ProcessList.startProcessLocked()ZygoteProcess.start() 通过 LocalSocket 通知 Zygote fork 子进程。新进程启动后执行 ActivityThread.main(),创建主线程 Looper,通过 attachApplication() Binder 回调注册到 AMS。

关键状态变化:新进程创建,ApplicationThread Binder 对象注册到 AMS。

并发竞争:两条路径执行顺序不确定。只有两者都完成后,才能进入步骤 ④ 的 realStartActivityLocked()。如果一方先完成,realStartActivityLocked() 会因条件不满足而直接 return,等另一方完成后再次触发。

典型耗时

  • Launcher pause:5~20ms
  • Zygote fork:10~50ms

关键日志

Tag日志含义
ActivityManagerStart proc <pid>:<processName>/<uid> for activity ...进程创建完成

详细分析

Zygote Fork 与进程注册时序

四、realStartActivityLocked — 启动 Activity(步骤 ④)

做了什么ActivityTaskSupervisor.realStartActivityLocked() 在确认 pause 完成且进程就绪后,构建 ClientTransaction,将 LaunchActivityItem(触发 onCreate)和 ResumeActivityItem(触发 onResume)下发到 App 进程。

前置条件

  1. 目标进程已创建(wpc.hasThread() == true
  2. 所有需要 pause 的 Activity 已完成 pause

关键状态变化ActivityRecord.setProcess(proc) 将 ActivityRecord 绑定到进程(此后 attachedToProcess() 返回 true)。

详细分析应用启动流程 §四、真正启动 Activity

五、Activity 生命周期(步骤 ⑤)

做了什么:App 进程收到 ClientTransaction 后依次执行:

  1. handleLaunchActivity()
    • Instrumentation.newActivity() 通过反射创建 Activity
    • Activity.attach() 创建 PhoneWindow 并关联 WindowManager
    • Activity.onCreate()setContentView() 创建 DecorView + inflate 布局
  2. Activity.onStart()
  3. Activity.onResume()

此时 View 树已创建但窗口尚未与 WMS 通信

典型耗时

  • Application.onCreate:0~500ms+(取决于 SDK 初始化)
  • Activity.onCreate / inflate:20~200ms(取决于布局复杂度)

关键日志

Tag日志含义
ActivityTaskManagerActivity reported start: ActivityRecord{...}Activity onStart 完成

详细分析Activity 启动流程详解

六、窗口创建与注册(步骤 ⑥)

做了什么handleResumeActivity()onResume() 之后调用 wm.addView(decor)

  1. 创建 ViewRootImpl:App 端与 WMS 通信的核心桥梁
  2. ViewRootImpl.setView()
    • requestLayout() → 注册 VSync 回调(异步,等待下一帧)
    • Session.addToDisplayAsUser() → 同步 Binder 调用 WMS.addWindow()
  3. WMS.addWindow()
    • 创建 WindowState(初始 DrawState = NO_SURFACE
    • 将 WindowState 挂载到 ActivityRecord(WindowToken)下
    • 存入 mWindowMap(key = IBinder, value = WindowState)

关键时序addWindow(同步)先于 relayoutWindow(异步,等 VSync)执行。

关键状态变化:WindowState 创建,DrawState = NO_SURFACE

关键日志

Tag日志含义
WindowManageraddWindow: Window{...} type=BASE_APPLICATION窗口添加到 WMS

详细分析

addWindow 与 InputChannel 建立时序

七、VSync 到来 → performTraversals(步骤 ⑦)

做了什么requestLayout() 通过 Choreographer 注册了 VSync 回调。VSync-app 信号到来时,doFrame() 按 INPUT → ANIMATION → TRAVERSAL 顺序执行,最终触发 performTraversals()

  1. relayoutWindow():跨进程请求 WMS 创建 Buffer 类型的 SurfaceControl,并计算窗口大小/位置。WMS 创建 Surface 后设置 DrawState = DRAW_PENDING,Surface 通过出参返回 App。
  2. performMeasure() / performLayout():View 树的测量和布局。
  3. createSyncIfNeeded():创建 SurfaceSyncGroup,注册 reportDrawFinished 回调。
  4. performDraw():触发 View 树绘制。

关键状态变化DrawState: NO_SURFACE → DRAW_PENDING(Surface 已创建但尚未绘制)。

典型耗时:relayoutWindow 5~15ms + measure/layout 5~50ms。

关键日志

Tag日志含义
WindowManagerRelayout Window{...}: oldVis=GONE newVis=VISIBLErelayoutWindow 创建 Surface

详细分析

八、硬件加速渲染管线(步骤 ⑧)

本阶段是现有详解文档未覆盖的内容,此处适当展开。

performDraw() 触发硬件加速渲染流水线,整个过程跨越两个线程:

渲染管线

8.1 主线程:录制 DisplayList

ThreadedRenderer.draw()(line 833)首先调用 updateRootDisplayList(),遍历 View 树将每个 View 的绘制操作记录到 RenderNode 的 DisplayList 中。这是录制而非立即执行——类似于录制一段绘制脚本,稍后由 GPU 回放。

随后调用 syncAndDrawFrame()(line 566,JNI → native nSyncAndDrawFrame),将主线程状态同步到 RenderThread,由 RenderThread 接管后续 GPU 渲染。

8.2 RenderThread:GPU 渲染

RenderThread 是独立于主线程的渲染线程。DrawFrameTask.drawFrame()CanvasContext.draw() 解析 DisplayList 中的绘制指令,转换为 GPU 指令(OpenGL ES 或 Vulkan),GPU 将渲染结果写入 GraphicBuffer

8.3 BLASTBufferQueue:缓冲区提交

BLASTBufferQueue(line 28, graphics/java/android/graphics/BLASTBufferQueue.java)是 App 端的缓冲区队列管理器。RenderThread 通过 dequeueBuffer() 获取空闲 GraphicBuffer,GPU 写入后通过 queueBuffer() 提交给 SurfaceFlinger。

8.4 SurfaceFlinger 合成

SurfaceFlinger 在 VSYNC-sf 信号到来时,先通过 commitTransactions() 应用所有 SurfaceControl.Transaction(包括 t.show()、位置变更等),然后 composite() 将所有可见 Layer 通过 HWC(Hardware Composer)或 GPU 合成输出到屏幕。

典型耗时:GPU 渲染首帧 5~30ms + SurfaceFlinger 合成约 1 帧(8~16ms)。

相关文档SurfaceControl Transaction

九、绘制完成通知与 DrawState 流转(步骤 ⑨)

做了什么:RenderThread 绘制完成后,通过 SurfaceSyncGroup 回调机制最终调用 reportDrawFinished()Session.finishDrawing() 跨进程通知 WMS。

WMS 收到后触发 DrawState 状态机流转:

DRAW_PENDING → COMMIT_DRAW_PENDING → READY_TO_SHOW → HAS_DRAWN
     ↑                ↑                    ↑              ↑
finishDrawingLocked  requestTraversal   commitFinish    performShowLocked
                     触发 layout        DrawingLocked    → showRobustly()
  1. finishDrawingLocked()DRAW_PENDING → COMMIT_DRAW_PENDING
  2. requestTraversal() 触发一次窗口 layout
  3. commitFinishDrawingLocked()COMMIT_DRAW_PENDING → READY_TO_SHOW,然后立即尝试 performShowLocked()
  4. performShowLocked()READY_TO_SHOW → HAS_DRAWN
  5. prepareSurfaceLocked()showRobustly():执行 t.show(mSurfaceControl) 将 Surface 标记为可见

关键理解HAS_DRAWN 只是逻辑状态标记,真正上屏还需要 Transaction.apply() 提交到 SurfaceFlinger。

DrawState 流转

详细分析

九-A、WMS performSurfacePlacement 大循环

上述 DrawState 流转并非自动发生,它由 WMS 端的 performSurfacePlacement 大循环驱动。这个循环在多个时机被触发(addWindow 后、relayoutWindow 中、finishDrawing 后),是 WMS 中最核心的机制之一。

大循环执行流程

WindowSurfacePlacer.performSurfacePlacement()       // 最多循环 6 次
  → RootWindowContainer.performSurfacePlacementNoTrace()
    ├── ① updateFocusedWindowLocked()               // 焦点检查
    ├── ② applySurfaceChangesTransaction()           // 核心:布局 + Surface 属性更新
    │     ├── performLayout()                        // 计算每个窗口的 frame
    │     │     └── DisplayPolicy.layoutWindowLw()
    │     │         └── WindowLayout.computeFrames()
    │     ├── forAllWindows(mApplySurfaceChangesTransaction)  // 遍历所有窗口
    │     │     └── commitFinishDrawingLocked()       // DrawState 推进
    │     │         └── performShowLocked()           // → HAS_DRAWN
    │     ├── prepareSurfaces()                       // Surface show/hide/alpha
    │     │     └── showRobustly() → t.show(SC)
    │     └── activity.updateAllDrawn()               // allDrawn 判定
    ├── ③ handleResizingWindows()                    // 通知 App 窗口 resize
    ├── ④ mSyncEngine.onSurfacePlacement()           // 驱动 SyncGroup.tryFinish()
    └── ⑤ checkAppTransitionReady()                  // Transition 就绪检查

这个循环贯穿了步骤 ⑥(addWindow 后首次触发)到步骤 ⑨(finishDrawing 后再次触发)的整个过程。每次触发都可能推进 DrawState、更新 Surface 属性、检查 SyncGroup 完成状态。

详细分析

十、SyncGroup 完成与 Shell Transition 动画(步骤 ⑩)

做了什么:窗口大循环中 BLASTSyncEngine.onSurfacePlacement() 检查 SyncGroup 中所有参与者是否完成绘制。当所有条件满足后:

  1. tryFinish()finishNow():收集所有参与者的 mSyncTransaction 合并为一个原子 startTransaction
  2. Transition.onTransactionReady()
    • commitVisibleActivities() 更新可见性
    • calculateTargets() 计算动画目标
    • buildFinishTransaction() 构建 finishT(动画结束时 apply)
    • 通知 Shell 侧
  3. Shell 侧 Transitions.onTransitionReady()
    • setupStartState() 设置初始可见性(OPEN 窗口 alpha=0、TO_BACK 窗口在 finishT 中 hide)
    • setupAnimHierarchy() 将 leash reparent 到 rootLeash
    • 选择 TransitionHandler 播放动画(通常 DefaultTransitionHandler
  4. 动画播放:Launcher 淡出 / 新 App 滑入
  5. finishTransition():动画结束,finishT.apply() 恢复窗口状态,cleanupTransaction 释放 leash

超时机制BLASTSyncEngine 设置 5 秒超时,超时后强制进入下一阶段。

典型耗时:动画 200~500ms。

关键日志

Tag日志含义
WindowManagerSyncGroup N: Finished!所有参与者绘制完成
WindowManagerCalling onTransitionReady info={id=N t=OPEN ...}Core 侧通知 Shell
WindowManagerShellPlaying animation for (#N) ...Shell 开始播放动画
WindowManagerShellTransition animation finished动画结束
WindowManagerFinish Transition (#N): ... finished=NNNmsCore 侧清理完成

详细分析Shell Transition 机制

SyncGroup 完成到 Shell 动画时序

十一、焦点窗口切换(步骤 ⑫)

本阶段是现有详解文档未完整覆盖的内容,此处适当展开。

11.1 触发时机

窗口可见性变化、新窗口添加/移除、Activity 切换时,WMS 调用 updateFocusedWindowLocked() 重新计算焦点。在 App 启动场景中,焦点切换发生在新 App 窗口变为可见之后。

11.2 焦点计算

焦点更新的完整链路:

WMS.updateFocusedWindowLocked()                    // line 7261
  → RootWindowContainer.updateFocusedWindowLocked() // line 602 - 遍历所有 DisplayContent
    → DisplayContent.updateFocusedWindowLocked()    // line 4581
      → findFocusedWindow()                         // line 4555
        → forAllWindows(mFindFocusedWindow, true)   // 从上到下遍历窗口
      → mCurrentFocus = newFocus                    // 更新焦点
      → InputMonitor.setInputFocusLw()              // line 4686 - 通知 Input 系统
java
// DisplayContent.java line 4555
WindowState findFocusedWindow() {
    mTmpWindow = null;
    forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
    if (mTmpWindow == null) {
        return null;
    }
    return mTmpWindow;
}

mFindFocusedWindow(line 940)是一个 lambda,对每个窗口检查 canReceiveKeys(),从上到下遍历,找到第一个满足以下条件的 WindowState

  • 可见(isVisibleRequestedOrAdding()
  • 可接收焦点(canReceiveKeys():无 FLAG_NOT_FOCUSABLE 标志)
  • 位于焦点 Display 上

11.3 通知 InputDispatcher

焦点更新后,通过 InputMonitor 将新的焦点窗口信息同步到 native 层的 InputDispatcher

java
// InputMonitor.java line 417
void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
    final IBinder focus = newWindow != null ? newWindow.mInputChannelToken : null;
    if (focus == mInputFocus) {
        return;  // 焦点未变,直接返回
    }
    if (newWindow != null && newWindow.canReceiveKeys()) {
        newWindow.mToken.paused = false;
    }
    setUpdateInputWindowsNeededLw();
    if (updateInputWindows) {
        updateInputWindowsLw(false /* force */);  // 调度更新到 InputDispatcher
    }
}

11.4 App 收到焦点回调

焦点切换完成后,InputDispatcher 通过 InputChannel 将焦点事件发送到 App 进程,ViewRootImpl 收到通知:

java
// ViewRootImpl.java line 12048
public void windowFocusChanged(boolean hasFocus) {
    synchronized (this) {
        mWindowFocusChanged = true;
        mUpcomingWindowFocus = hasFocus;
    }
    Message msg = Message.obtain();
    msg.what = MSG_WINDOW_FOCUS_CHANGED;
    mHandler.sendMessage(msg);  // 投递到主线程
}

// 主线程处理 → handleWindowFocusChanged() (line 5355)
//   → dispatchFocusEvent() (line 5446)
//     → mView.dispatchWindowFocusChanged(hasWindowFocus)
//       → Activity.onWindowFocusChanged(true)    ← App 启动完成的标志

onWindowFocusChanged(true) 通常被视为 App 启动完成、界面可交互的标志。

关键日志

Tag日志含义
input_focus (EventLog 62001)Focus request ...WMS 请求焦点切换(InputMonitor line 581)
input_focus (EventLog 62001)Focus entering ...InputDispatcher 确认焦点切换(native 层)

相关文档

十二、首帧后的持续 Surface 更新

首帧上屏并不意味着 Surface 操作结束。动画播放期间及之后,WindowAnimator 通过 PendingTransaction 路径 持续驱动每帧的 Surface 属性更新:

WindowAnimator.animate()                        // 每帧由 Choreographer 触发
  ├── DisplayContent.prepareSurfaces()
  │     └── 每个 WindowContainer.prepareSurfaces()
  │         └── WindowStateAnimator.prepareSurfaceLocked(t)
  │             ├── t.setAlpha(mSurfaceControl, mShownAlpha)  // 透明度
  │             ├── t.setMatrix(...)                           // 变换矩阵
  │             └── showRobustly(t) / hide(t)                 // show/hide
  └── mTransaction.merge(dc.getPendingTransaction())
      └── mTransaction.apply()                               // 每帧 apply → SurfaceFlinger

与 Sync 路径的区别

  • Sync 路径(Transition 期间):所有 Surface 变更收集到 SyncTransaction,由 BLASTSyncEngine.finishNow() 合并为一个原子 Transaction,通过 onTransactionReady() 一次性交给 Shell
  • PendingTransaction 路径(常规每帧):WindowAnimator.animate() 每帧遍历所有窗口,直接 apply() 到 SurfaceFlinger

Transition 动画结束后,finishT.apply() 恢复窗口状态,此后 Surface 更新完全切换到 PendingTransaction 路径。

十三、窗口可见性与 Transition Collect 的联系

窗口可见性变化(setVisibility(true/false))与 Shell Transition 的 Collecting 阶段紧密关联:

  • setVisibility(true) 被调用时,如果当前有 Transition 正在 Collecting,该 WindowContainer 会被 collect() 到 Transition 中
  • 可见性变更不会立即 apply 到 Surface,而是暂存在 SyncTransaction 中,等待 SyncGroup 完成后原子提交
  • 这保证了多个窗口的可见性变化(如 Launcher hide + App show)能在同一帧原子提交,避免视觉闪烁

详细分析可见性管理 §1.7 setVisibility 详细流程

冷启动各阶段耗时参考

阶段典型耗时主要耗时原因优化方向
Launcher → ATMS1~5msBinder IPC 开销
Zygote Fork10~50ms进程创建 + 内存映射USAP 预 fork 池
Application.onCreate0~500ms+SDK 初始化、SP 读取等懒加载、异步初始化
Activity.onCreate / inflate20~200ms布局复杂度、View 层级深度扁平化布局、ViewStub
measure / layout / draw5~50msView 树遍历、自定义 View减少 measure 次数
GPU 渲染首帧5~30msShader 编译(首次)、纹理上传Shader 预热
SurfaceFlinger 合成8~16ms(约 1 帧)等待下一个 VSYNC-sf
Shell Transition 动画200~500ms动画时长设定

关键类与文件速查

组件关键类源码路径
Activity 管理ActivityTaskManagerServiceservices/core/.../wm/ActivityTaskManagerService.java
Activity 启动ActivityStarterservices/core/.../wm/ActivityStarter.java
Activity 栈ActivityTaskSupervisorservices/core/.../wm/ActivityTaskSupervisor.java
进程管理ProcessListservices/core/.../am/ProcessList.java
App 主线程ActivityThreadcore/java/android/app/ActivityThread.java
事务框架ClientTransaction, LaunchActivityItemcore/java/android/app/servertransaction/
窗口管理WindowManagerServiceservices/core/.../wm/WindowManagerService.java
窗口状态WindowStateservices/core/.../wm/WindowState.java
窗口树根RootWindowContainerservices/core/.../wm/RootWindowContainer.java
View 树根ViewRootImplcore/java/android/view/ViewRootImpl.java
VSync 协调Choreographercore/java/android/view/Choreographer.java
硬件渲染ThreadedRenderer (extends HardwareRenderer)core/java/android/view/ThreadedRenderer.java
Surface 状态WindowStateAnimatorservices/core/.../wm/WindowStateAnimator.java
Shell TransitionTransition, TransitionControllerservices/core/.../wm/Transition.java
同步引擎BLASTSyncEngineservices/core/.../wm/BLASTSyncEngine.java
缓冲区队列BLASTBufferQueuecore/java/android/graphics/BLASTBufferQueue.java
Input 焦点InputMonitorservices/core/.../wm/InputMonitor.java

关键日志速查

阶段Tag关键日志含义
启动请求ActivityTaskManagerSTART u0 {intent} from uid NATMS 收到启动请求
进程启动ActivityManagerStart proc <pid>:<name>/<uid> for activity ...进程创建完成
Transition 创建WindowManagerCreating Transition: TransitionRecord{id=N type=OPEN}Shell Transition 开始
窗口添加WindowManageraddWindow: Window{...} type=BASE_APPLICATION窗口注册到 WMS
绘制完成WindowManagerFinishing drawing window Window{...}: mDrawState=DRAW_PENDINGApp 绘制完成通知
Surface 显示WindowManagerSURFACE SHOW (performLayout): ...Surface show
同步完成WindowManagerSyncGroup N: Finished!所有参与者就绪
同步超时BLASTSyncEngineSync group N timeout5 秒超时强制推进
动画开始WindowManagerShellPlaying animation for (#N) ...Shell 播放动画
动画结束WindowManagerShellTransition animation finished动画完成
Transition 完成WindowManagerFinish Transition (#N): ... finished=NNNmsCore 清理完成
焦点切换input_focus (EventLog 62001)Focus request ... / Focus entering ...焦点窗口变更(WMS 侧 InputMonitor,native 侧 InputDispatcher
StartingWindowWindowManagerCreating SplashScreenStartingDataStartingWindow 创建
StartingWindow 移除WindowManagerSchedule remove starting ActivityRecord{...}StartingWindow 移除

附录:ProtoLog 开启命令

bash
# Shell Transition 相关
adb shell wm logging enable-text WM_DEBUG_WINDOW_TRANSITIONS WM_DEBUG_WINDOW_TRANSITIONS_MIN WM_DEBUG_SYNC_ENGINE

# StartingWindow 相关
adb shell wm logging enable-text WM_DEBUG_STARTING_WINDOW

# 焦点窗口相关
adb shell wm logging enable-text WM_DEBUG_FOCUS WM_DEBUG_FOCUS_LIGHT