基于 AOSP 15 (Android 15) 源码分析
摘要: 本文从relayout完成后的
performDraw()出发,沿mDrawState状态机 (DRAW_PENDING → COMMIT_DRAW_PENDING → READY_TO_SHOW → HAS_DRAWN)和prepareSurface显示链路两条主线,完整梳理窗口从"有Surface"到"用户可见"的全过程。包括客户端finishDrawing通知、服务端状态流转、prepareSurfaceLocked Surface显示控制、以及ActivityRecord多窗口协同显示机制。站在Framework开发视角,分析每个状态的进入条件、阻塞点和调试方法。
目录
- [1. 整体架构概览](#1. 整体架构概览 "#1-%E6%95%B4%E4%BD%93%E6%9E%B6%E6%9E%84%E6%A6%82%E8%A7%88")
- [2. mDrawState状态机总览](#2. mDrawState状态机总览 "#2-mdrawstate%E7%8A%B6%E6%80%81%E6%9C%BA%E6%80%BB%E8%A7%88")
- [3. 完整调用链路](#3. 完整调用链路 "#3-%E5%AE%8C%E6%95%B4%E8%B0%83%E7%94%A8%E9%93%BE%E8%B7%AF")
- [4. 客户端侧: performDraw → finishDrawing](#4. 客户端侧: performDraw → finishDrawing "#4-%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%BE%A7-performdraw--finishdrawing")
- [4.1 performTraversals中的draw触发](#4.1 performTraversals中的draw触发 "#41-performtraversals%E4%B8%AD%E7%9A%84draw%E8%A7%A6%E5%8F%91")
- [4.2 createSyncIfNeeded --- BLAST同步组创建](#4.2 createSyncIfNeeded — BLAST同步组创建 "#42-createsyncifneeded--blast%E5%90%8C%E6%AD%A5%E7%BB%84%E5%88%9B%E5%BB%BA")
- [4.3 performDraw → draw --- 绘制执行](#4.3 performDraw → draw — 绘制执行 "#43-performdraw--draw--%E7%BB%98%E5%88%B6%E6%89%A7%E8%A1%8C")
- [4.4 BLAST Buffer同步 --- registerCallbacksForSync](#4.4 BLAST Buffer同步 — registerCallbacksForSync "#44-blast-buffer%E5%90%8C%E6%AD%A5--registercallbacksforsync")
- [4.5 reportDrawFinished --- 通知WMS绘制完成](#4.5 reportDrawFinished — 通知WMS绘制完成 "#45-reportdrawfinished--%E9%80%9A%E7%9F%A5wms%E7%BB%98%E5%88%B6%E5%AE%8C%E6%88%90")
- [5. Binder IPC: IWindowSession.finishDrawing](#5. Binder IPC: IWindowSession.finishDrawing "#5-binder-ipc-iwindowsessionfinishdrawing")
- [6. 服务端核心: mDrawState状态流转](#6. 服务端核心: mDrawState状态流转 "#6-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%A0%B8%E5%BF%83-mdrawstate%E7%8A%B6%E6%80%81%E6%B5%81%E8%BD%AC")
- [6.1 阶段一: WMS.finishDrawingWindow --- 入口分发](#6.1 阶段一: WMS.finishDrawingWindow — 入口分发 "#61-%E9%98%B6%E6%AE%B5%E4%B8%80-wmsfinishdrawingwindow--%E5%85%A5%E5%8F%A3%E5%88%86%E5%8F%91")
- [6.2 阶段二: WindowState.finishDrawing --- 同步与绘制完成处理](#6.2 阶段二: WindowState.finishDrawing — 同步与绘制完成处理 "#62-%E9%98%B6%E6%AE%B5%E4%BA%8C-windowstatefinishdrawing--%E5%90%8C%E6%AD%A5%E4%B8%8E%E7%BB%98%E5%88%B6%E5%AE%8C%E6%88%90%E5%A4%84%E7%90%86")
- [6.3 阶段三: finishDrawingLocked --- DRAW_PENDING → COMMIT_DRAW_PENDING](#6.3 阶段三: finishDrawingLocked — DRAW_PENDING → COMMIT_DRAW_PENDING "#63-%E9%98%B6%E6%AE%B5%E4%B8%89-finishdrawinglocked--draw_pending--commit_draw_pending")
- [6.4 阶段四: commitFinishDrawingLocked --- COMMIT_DRAW_PENDING → READY_TO_SHOW](#6.4 阶段四: commitFinishDrawingLocked — COMMIT_DRAW_PENDING → READY_TO_SHOW "#64-%E9%98%B6%E6%AE%B5%E5%9B%9B-commitfinishdrawinglocked--commit_draw_pending--ready_to_show")
- [6.5 阶段五: performShowLocked --- READY_TO_SHOW → HAS_DRAWN](#6.5 阶段五: performShowLocked — READY_TO_SHOW → HAS_DRAWN "#65-%E9%98%B6%E6%AE%B5%E4%BA%94-performshowlocked--ready_to_show--has_drawn")
- [7. prepareSurface链路: Surface显示控制](#7. prepareSurface链路: Surface显示控制 "#7-preparesurface%E9%93%BE%E8%B7%AF-surface%E6%98%BE%E7%A4%BA%E6%8E%A7%E5%88%B6")
- [7.1 prepareSurface调用入口 --- 两条路径](#7.1 prepareSurface调用入口 — 两条路径 "#71-preparesurface%E8%B0%83%E7%94%A8%E5%85%A5%E5%8F%A3--%E4%B8%A4%E6%9D%A1%E8%B7%AF%E5%BE%84")
- [7.2 prepareSurfaceLocked核心逻辑](#7.2 prepareSurfaceLocked核心逻辑 "#72-preparesurfacelocked%E6%A0%B8%E5%BF%83%E9%80%BB%E8%BE%91")
- [7.3 showRobustly --- Surface真正显示](#7.3 showRobustly — Surface真正显示 "#73-showrobustly--surface%E7%9C%9F%E6%AD%A3%E6%98%BE%E7%A4%BA")
- [7.4 computeShownFrameLocked --- 透明度计算](#7.4 computeShownFrameLocked — 透明度计算 "#74-computeshownframelocked--%E9%80%8F%E6%98%8E%E5%BA%A6%E8%AE%A1%E7%AE%97")
- [7.5 prepareSurface与mDrawState的关系](#7.5 prepareSurface与mDrawState的关系 "#75-preparesurface%E4%B8%8Emdrawstate%E7%9A%84%E5%85%B3%E7%B3%BB")
- [8. ActivityRecord与窗口可见性协同](#8. ActivityRecord与窗口可见性协同 "#8-activityrecord%E4%B8%8E%E7%AA%97%E5%8F%A3%E5%8F%AF%E8%A7%81%E6%80%A7%E5%8D%8F%E5%90%8C")
- [8.1 canShowWindows --- Activity何时允许窗口显示](#8.1 canShowWindows — Activity何时允许窗口显示 "#81-canshowwindows--activity%E4%BD%95%E6%97%B6%E5%85%81%E8%AE%B8%E7%AA%97%E5%8F%A3%E6%98%BE%E7%A4%BA")
- [8.2 updateAllDrawn --- 所有窗口绘制完成](#8.2 updateAllDrawn — 所有窗口绘制完成 "#82-updatealldrawn--%E6%89%80%E6%9C%89%E7%AA%97%E5%8F%A3%E7%BB%98%E5%88%B6%E5%AE%8C%E6%88%90")
- [8.3 onFirstWindowDrawn --- StartingWindow移除时机](#8.3 onFirstWindowDrawn — StartingWindow移除时机 "#83-onfirstwindowdrawn--startingwindow%E7%A7%BB%E9%99%A4%E6%97%B6%E6%9C%BA")
- [9. Surface显示与上屏全流程](#9. Surface显示与上屏全流程 "#9-surface%E6%98%BE%E7%A4%BA%E4%B8%8E%E4%B8%8A%E5%B1%8F%E5%85%A8%E6%B5%81%E7%A8%8B")
- [10. 调试方法](#10. 调试方法 "#10-%E8%B0%83%E8%AF%95%E6%96%B9%E6%B3%95")
- [11. Framework开发常见场景](#11. Framework开发常见场景 "#11-framework%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF")
- [12. 完整时序图](#12. 完整时序图 "#12-%E5%AE%8C%E6%95%B4%E6%97%B6%E5%BA%8F%E5%9B%BE")
- [13. 源码文件索引](#13. 源码文件索引 "#13-%E6%BA%90%E7%A0%81%E6%96%87%E4%BB%B6%E7%B4%A2%E5%BC%95")
1. 整体架构概览
finishDraw流程发生在relayout之后。relayout为窗口创建了Surface并计算了帧,但Surface此时是隐藏 的(mLastHidden = true,mDrawState = DRAW_PENDING)。窗口需要完成第一帧绘制并通过一系列状态转换后,Surface才最终显示。
整个过程涉及两条主线:
- mDrawState状态机 --- 控制窗口绘制的逻辑状态流转
- prepareSurface链路 --- 控制Surface的物理显示/隐藏
scss
┌─────────────────────────────────────────────────────────────────────────┐
│ 应用进程 (App Process) │
│ │
│ relayout返回后: │
│ performMeasure() → performLayout() → performDraw() │
│ │ │
│ ┌──────────────────────────────────────────┘ │
│ │ │
│ │ performDraw() │
│ │ ├── createSyncIfNeeded() 创建SurfaceSyncGroup │
│ │ ├── draw() 硬件渲染器绘制 → 提交Buffer │
│ │ ├── registerCallbacksForSync() 注册BLAST Buffer同步回调 │
│ │ │ └── mBlastBufferQueue.syncNextTransaction() │
│ │ └── [Buffer就绪后回调] │
│ │ └── reportDrawFinished() │
│ │ └── IWindowSession.finishDrawing() │
│ │ │
│ ═════════════════════════ Binder IPC ═══════════════════════════╪═══ │
│ │ │
└──────────────────────────────────────────────────────────────────┼──────┘
│
┌──────────────────────────────────────────────────────────────────┼─────────┐
│ system_server 进程 │ │
│ │ │
│ Session.finishDrawing() ◀───────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────── mDrawState状态机 ────────────────┐ │
│ │ │ │
│ │ WMS.finishDrawingWindow() │ │
│ │ ▼ │ │
│ │ WindowState.finishDrawing() │ │
│ │ │ BLAST同步 / 旋转 / DrawHandler │ │
│ │ ▼ │ │
│ │ finishDrawingLocked() │ │
│ │ │ DRAW_PENDING → COMMIT_DRAW_PENDING ★① │
│ │ ▼ │ │
│ │ requestTraversal() → performSurfacePlacement │ │
│ │ ▼ │ │
│ │ commitFinishDrawingLocked() │ │
│ │ │ COMMIT_DRAW_PENDING → READY_TO_SHOW ★② │
│ │ │ → performShowLocked() │ │
│ │ │ READY_TO_SHOW → HAS_DRAWN ★③ │
│ │ │ │ │
│ └────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────── prepareSurface显示链路 ───────────┐ │
│ │ │ │
│ │ WindowAnimator.animate() │ │
│ │ ▼ │ │
│ │ DisplayContent.prepareSurfaces() │ │
│ │ │ 递归调用子容器 │ │
│ │ ▼ │ │
│ │ WindowState.prepareSurfaces() │ │
│ │ │ 位置/缩放/刷新率 │ │
│ │ ▼ │ │
│ │ WindowStateAnimator.prepareSurfaceLocked(t) │ │
│ │ │ │ │
│ │ ├── mDrawState==HAS_DRAWN? │ │
│ │ │ && mLastHidden? │ │
│ │ │ ↓ Yes │ │
│ │ │ showRobustly(t) → t.show(surface) ★ 上屏 │
│ │ │ │ │
│ │ └── 否则: hide(t) 或 只更新alpha │ │
│ │ │ │
│ └────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ SurfaceFlinger合成 → 显示到屏幕 │
└───────────────────────────────────────────────────────────────────────────┘
核心类职责
| 类名 | 路径 | finishDraw/prepareSurface中的角色 |
|---|---|---|
ViewRootImpl |
core/.../view/ViewRootImpl.java |
客户端绘制完成通知入口,管理BLAST同步 |
SurfaceSyncGroup |
core/.../view/SurfaceSyncGroup.java |
客户端同步组,协调多个Surface的绘制完成 |
BLASTBufferQueue |
core/.../graphics/ |
Buffer同步机制,syncNextTransaction |
Session |
services/.../wm/Session.java |
per-process,透传finishDrawing到WMS |
WindowManagerService |
services/.../wm/ |
finishDrawingWindow入口,触发布局 |
WindowState |
services/.../wm/WindowState.java |
finishDrawing处理,prepareSurfaces入口,performShow |
WindowStateAnimator |
services/.../wm/WindowStateAnimator.java |
mDrawState状态机所有者,prepareSurfaceLocked,showRobustly |
WindowAnimator |
services/.../wm/WindowAnimator.java |
动画驱动器,触发prepareSurfaces递归 |
ActivityRecord |
services/.../wm/ActivityRecord.java |
canShowWindows决策,allDrawn管理 |
DisplayContent |
services/.../wm/DisplayContent.java |
commitFinishDrawingLocked调用者,prepareSurfaces递归分发 |
2. mDrawState状态机总览
mDrawState定义在WindowStateAnimator.java中,是窗口从创建到可见的核心状态机。prepareSurfaceLocked的显示/隐藏决策依赖此状态。
状态定义
java
// WindowStateAnimator.java
/** 没有Surface */
static final int NO_SURFACE = 0;
/** Surface已创建但窗口未绘制,Surface隐藏 */
static final int DRAW_PENDING = 1;
/** 窗口完成首次绘制但Surface未显示,等下次布局时显示 */
static final int COMMIT_DRAW_PENDING = 2;
/** 绘制已提交,等Token中所有窗口就绪后统一显示 */
static final int READY_TO_SHOW = 3;
/** 窗口已首次在屏幕上显示 */
static final int HAS_DRAWN = 4;
状态转换图
scss
relayout
createSurfaceLocked()
│
│ resetDrawState()
▼
┌──────────┐ 客户端finishDrawing ┌──────────────────┐
│ DRAW_ │ ─────────────────────────▶│ COMMIT_DRAW_ │
│ PENDING │ finishDrawingLocked() │ PENDING │
│ (1) │ ★ mDrawState核心转换 │ (2) │
└──────────┘ └───────┬──────────┘
│ │
│ mLastHidden=true performSurfacePlacement
│ Surface不可见 commitFinishDrawingLocked()
│ │
│ ▼
│ ┌──────────────────┐
│ performShowLocked() │ READY_TO_SHOW │
│ 条件全部满足 │ (3) │
│ └───────┬──────────┘
│ │
│ performShowLocked()
│ isReadyForDisplay() ✓
│ canShowWindows() ✓
│ │
│ ▼
│ ┌──────────────────┐
│ │ HAS_DRAWN │
│ prepareSurfaceLocked() │ (4) │
│ → showRobustly(t) │ Surface可见! │
│ → t.show(surface) └──────────────────┘
│ │
▼ ▼
Surface隐藏 Surface显示
异常路径:
┌──────────┐ Surface创建失败/销毁 ┌──────────┐
│ NO_ │ ◀──────────────────────│ 任何状态 │
│ SURFACE │ destroySurface() │ │
│ (0) │ └──────────┘
└──────────┘
每个状态的进入条件、Surface状态与prepareSurface行为
| 状态 | 值 | 进入条件 | Surface状态 | prepareSurfaceLocked行为 |
|---|---|---|---|---|
NO_SURFACE |
0 | 初始 / Surface销毁 | 不存在 | 直接return |
DRAW_PENDING |
1 | createSurfaceLocked()→resetDrawState() |
存在,隐藏 | hide(t) |
COMMIT_DRAW_PENDING |
2 | finishDrawingLocked() |
隐藏 | hide(t) |
READY_TO_SHOW |
3 | commitFinishDrawingLocked() |
隐藏→准备显示 | 可能hide(t)(因performShow未执行) |
HAS_DRAWN |
4 | performShowLocked() |
可见 | showRobustly(t) → t.show() |
3. 完整调用链路
scss
[应用进程] relayout完成后
performTraversals()
│
├── performMeasure() → performLayout()
│
▼
performDraw(surfaceSyncGroup) // ViewRootImpl.java line 5383
│
├── draw(fullRedrawNeeded, surfaceSyncGroup, syncBuffer)
│ └── ThreadedRenderer.draw(mView, ...) // 提交GPU绘制命令
│ └── registerCallbacksForSync()
│ └── mBlastBufferQueue.syncNextTransaction() // Buffer同步
│ └── [GPU完成渲染回调]
│ └── surfaceSyncGroup.markSyncReady()
│ └── [SurfaceSyncGroup完成回调]
│ │
═══════════════════ Binder IPC ════════════════════════════
│
reportDrawFinished(transaction, seqId)
└── IWindowSession.finishDrawing(window, t, seqId)
[system_server]
Session.finishDrawing()
└── WMS.finishDrawingWindow()
│
▼
WindowState.finishDrawing()
│ ├── BLAST同步处理
│ ├── 旋转控制器处理
│ └── executeDrawHandlers()
│
▼
WindowStateAnimator.finishDrawingLocked()
│ ★ mDrawState: DRAW_PENDING → COMMIT_DRAW_PENDING
│
▼
requestTraversal() → performSurfacePlacement()
│
▼
DisplayContent.mApplySurfaceChangesTransaction
│
├── commitFinishDrawingLocked()
│ ★ mDrawState: COMMIT_DRAW_PENDING → READY_TO_SHOW
│ └── performShowLocked()
│ ★ mDrawState: READY_TO_SHOW → HAS_DRAWN
│ mLastAlpha = -1 // 强制下次prepareSurface刷新
│ applyEnterAnimationLocked()
│
└── activity.updateDrawnWindowStates(w)
└── updateAllDrawn() → allDrawn=true → setLayoutNeeded()
│ 动画循环触发
▼
WindowAnimator.animate()
└── dc.prepareSurfaces()
└── WindowState.prepareSurfaces()
├── updateSurfacePositionNonOrganized()
├── updateFrameRateSelectionPriorityIfNeeded()
├── updateScaleIfNeeded()
└── mWinAnimator.prepareSurfaceLocked(t)
│
├── computeShownFrameLocked() // 计算alpha
├── t.setAlpha(surface, alpha)
│
├── mDrawState == HAS_DRAWN && mLastHidden?
│ └── YES: showRobustly(t)
│ ├── setShown(true)
│ └── t.show(mSurfaceControl) ★ Surface上屏
│
└── 否则: hide(t) 或 仅更新属性
4. 客户端侧: performDraw → finishDrawing
4.1 performTraversals中的draw触发
relayout返回后,performTraversals()依次执行measure、layout,最后执行draw:
java
// ViewRootImpl.java performTraversals()
if (!cancelDraw) {
if (mReportNextDraw) {
if (mActiveSurfaceSyncGroup != null) {
mSyncBuffer = true;
}
// ★ 创建WMS同步组(如果需要)
createSyncIfNeeded();
notifyDrawStarted(isInWMSRequestedSync());
mDrewOnceForSync = true;
}
if (!performDraw(mActiveSurfaceSyncGroup)) {
handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, ...);
}
}
Framework开发关注:
mReportNextDraw是WMS请求"下次绘制时通知我"的标记,在relayout返回RELAYOUT_RES_FIRST_TIME或WMS通过setReportNextDraw设置createSyncIfNeeded()在draw之前创建,确保draw完成后能回调通知WMScancelDraw为true时(BLAST cancelAndRedraw),跳过本帧,等下一帧
4.2 createSyncIfNeeded --- BLAST同步组创建
java
// ViewRootImpl.java
private void createSyncIfNeeded() {
if (isInWMSRequestedSync() || !mReportNextDraw) {
return;
}
final int seqId = mSyncSeqId;
mWmsRequestSyncGroupState = WMS_SYNC_PENDING;
// ★ 创建同步组,完成回调中调用 reportDrawFinished
mWmsRequestSyncGroup = new SurfaceSyncGroup("wmsSync-" + mTag, t -> {
mWmsRequestSyncGroupState = WMS_SYNC_MERGED;
// 系统进程需要post到主线程避免死锁
if (mWindowSession instanceof Binder) {
Transaction transactionCopy = new Transaction();
transactionCopy.merge(t);
mHandler.postAtFrontOfQueue(
() -> reportDrawFinished(transactionCopy, seqId));
} else {
reportDrawFinished(t, seqId);
}
});
mWmsRequestSyncGroup.add(this, null /* runnable */);
}
WMS同步状态:
| 状态 | 值 | 含义 |
|---|---|---|
WMS_SYNC_NONE |
0 | 没有WMS请求的同步 |
WMS_SYNC_PENDING |
1 | 同步组已创建,等待绘制完成 |
WMS_SYNC_RETURNED |
2 | reportDrawFinished已发送到WMS |
WMS_SYNC_MERGED |
3 | 同步事务已合并 |
Framework开发关注:
SurfaceSyncGroup的回调是整个客户端finishDraw的触发点------当GPU完成渲染、Buffer就绪后回调触发- 系统进程需要post到Handler执行,避免finishDrawing在WMS持锁线程上被调用导致死锁
seqId来自relayout返回的syncSeqId,WMS用它匹配是哪次同步请求
4.3 performDraw → draw --- 绘制执行
java
// ViewRootImpl.java
private boolean performDraw(@Nullable SurfaceSyncGroup surfaceSyncGroup) {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return false;
}
mIsDrawing = true;
boolean usingAsyncReport;
try {
usingAsyncReport = draw(fullRedrawNeeded, surfaceSyncGroup, mSyncBuffer);
} finally {
mIsDrawing = false;
}
if (mReportNextDraw) {
if (mWindowDrawCountDown != null) {
mWindowDrawCountDown.await();
}
if (mSurfaceHolder != null && mSurface.isValid()) {
usingAsyncReport = true;
SurfaceCallbackHelper sch = new SurfaceCallbackHelper(() -> {
handleSyncRequestWhenNoAsyncDraw(surfaceSyncGroup, ...);
});
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
}
if (!usingAsyncReport) {
handleSyncRequestWhenNoAsyncDraw(surfaceSyncGroup, ...);
}
return true;
}
draw()方法(line 5601)硬件加速关键路径:
java
if (isHardwareEnabled()) {
useAsyncReport = true;
if (activeSyncGroup != null) {
registerCallbacksForSync(syncBuffer, activeSyncGroup);
if (syncBuffer) {
mAttachInfo.mThreadedRenderer.forceDrawNextFrame();
}
}
// ★ 提交GPU绘制命令
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
}
4.4 BLAST Buffer同步 --- registerCallbacksForSync
java
// ViewRootImpl.java
private void registerCallbacksForSync(boolean syncBuffer,
final SurfaceSyncGroup surfaceSyncGroup) {
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
// Surface丢失/上下文停止 → 直接完成
if ((syncResult & (SYNC_LOST_SURFACE_REWARD_IF_FOUND
| SYNC_CONTEXT_IS_STOPPED)) != 0) {
surfaceSyncGroup.markSyncReady();
return null;
}
if (syncBuffer) {
// ★ BLAST Buffer同步: 等Buffer就绪后再标记完成
mBlastBufferQueue.syncNextTransaction(transaction -> {
surfaceSyncGroup.addTransaction(transaction);
surfaceSyncGroup.markSyncReady();
});
}
return didProduceBuffer -> {
if (!didProduceBuffer) {
mBlastBufferQueue.clearSyncTransaction();
surfaceSyncGroup.markSyncReady();
return;
}
if (!syncBuffer) {
surfaceSyncGroup.markSyncReady();
}
};
}
});
}
BLAST Buffer同步时序:
scss
ThreadedRenderer.draw(mView) → GPU命令提交
│
▼
onFrameDraw(syncResult, frame) ← 渲染线程回调
│
├── syncBuffer=true:
│ mBlastBufferQueue.syncNextTransaction(callback)
│ → Buffer就绪 → callback → markSyncReady()
│
└── syncBuffer=false:
frameCommitCallback → markSyncReady()
│
▼
SurfaceSyncGroup完成回调 → reportDrawFinished()
4.5 reportDrawFinished --- 通知WMS绘制完成
java
// ViewRootImpl.java line 5289-5303
private void reportDrawFinished(@Nullable Transaction t, int seqId) {
try {
mWindowSession.finishDrawing(mWindow, t, seqId);
} catch (RemoteException e) {
if (t != null) t.apply();
} finally {
if (t != null) t.clear();
}
}
5. Binder IPC: IWindowSession.finishDrawing
java
// IWindowSession.aidl
void finishDrawing(IWindow window,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId);
| 参数 | 说明 | Framework关注 |
|---|---|---|
window |
客户端窗口标识 | WMS通过windowForClientLocked找到WindowState |
postDrawTransaction |
绘制事务(可能包含Buffer) | WMS会merge到同步事务中 |
seqId |
同步序列号 | 匹配mPrepareSyncSeqId,旧seqId的Buffer会被丢弃 |
6. 服务端核心: mDrawState状态流转
6.1 阶段一: WMS.finishDrawingWindow --- 入口分发
java
// Session.java
public void finishDrawing(IWindow window,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
mService.finishDrawingWindow(this, window, postDrawTransaction, seqId);
}
java
// WindowManagerService.java
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize(Binder.getCallingPid(), Binder.getCallingUid());
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
WindowState win = windowForClientLocked(session, client, false);
ProtoLog.d(WM_DEBUG_ADD_REMOVE,
"finishDrawingWindow: %s mDrawState=%s",
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
// ★ 触发布局循环 → 后续commitFinishDrawingLocked在此循环中执行
mWindowPlacerLocked.requestTraversal();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
Framework开发关注:
finishDrawingWindow在mGlobalLock同步块内执行win.finishDrawing()返回true→ 需要重新布局 →requestTraversal()- 这个
requestTraversal()走到performSurfacePlacement,在那里执行commitFinishDrawingLocked - 如果返回
false(drawState已经不是DRAW_PENDING),不触发额外操作
6.2 阶段二: WindowState.finishDrawing --- 同步与绘制完成处理
java
// WindowState.java
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
// ① 方向变更耗时统计
if (mOrientationChangeRedrawRequestTime > 0) {
Slog.i(TAG, "finishDrawing of orientation change: " + this
+ " " + (SystemClock.elapsedRealtime()
- mOrientationChangeRedrawRequestTime) + "ms");
mOrientationChangeRedrawRequestTime = 0;
}
// ② Activity重启动时通知
if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0
&& mActivityRecord.findMainWindow(false) == this) {
mActivityRecord.finishOrAbortReplacingWindow();
}
// ③ StartingWindow绘制通知
if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) {
mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
.notifyStartingWindowDrawn(mActivityRecord);
}
// ④ ★ BLAST同步序列号匹配
final boolean syncActive = mPrepareSyncSeqId > 0;
final boolean syncStillPending = syncActive && mPrepareSyncSeqId > syncSeqId;
if (syncStillPending && postDrawTransaction != null) {
// 旧seqId的Buffer已过时,丢弃
dropBufferFrom(postDrawTransaction);
}
// ⑤ 执行DrawHandler
final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);
// ⑥ 异步旋转控制器处理
boolean skipLayout = false;
boolean layoutNeeded = false;
final AsyncRotationController asyncRotationController =
mDisplayContent.getAsyncRotationController();
if (asyncRotationController != null
&& asyncRotationController.handleFinishDrawing(this, postDrawTransaction)) {
postDrawTransaction = null;
skipLayout = true;
} else if (syncActive) {
// BLAST同步模式
if (!syncStillPending) {
layoutNeeded = onSyncFinishedDrawing();
}
if (postDrawTransaction != null) {
mSyncTransaction.merge(postDrawTransaction);
postDrawTransaction = null;
}
} else if (syncNextBuffer()) {
// 非BLAST同步模式
layoutNeeded = onSyncFinishedDrawing();
}
// ⑦ ★ 核心状态转换
layoutNeeded |= mWinAnimator.finishDrawingLocked(postDrawTransaction);
return !skipLayout && (hasSyncHandlers || layoutNeeded);
}
四个关键路径:
| 路径 | 条件 | 行为 |
|---|---|---|
| 异步旋转 | asyncRotationController != null |
控制器消费事务,skipLayout=true |
| BLAST同步 | syncActive |
合并到mSyncTransaction,同步组完成后统一显示 |
| 非BLAST同步 | syncNextBuffer() |
直接标记同步完成 |
| 普通路径 | 无同步 | 直接到finishDrawingLocked() |
6.3 阶段三: finishDrawingLocked --- DRAW_PENDING → COMMIT_DRAW_PENDING
java
// WindowStateAnimator.java
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) {
boolean layoutNeeded = false;
// ★ 只有DRAW_PENDING时才转换
if (mDrawState == DRAW_PENDING) {
ProtoLog.v(WM_DEBUG_DRAW,
"finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
mWin, mSurfaceControl);
mDrawState = COMMIT_DRAW_PENDING; // ★ 状态转换
layoutNeeded = true;
}
// 合并客户端的绘制事务
if (postDrawTransaction != null) {
mWin.getSyncTransaction().merge(postDrawTransaction);
layoutNeeded = true;
}
return layoutNeeded;
}
Framework开发关注:
- 只有
mDrawState == DRAW_PENDING时才会转换。如果已是HAS_DRAWN(后续重绘),此方法是空操作 layoutNeeded = true→requestTraversal()→ 触发commitFinishDrawingLocked执行- 后续重绘(resize等)走relayout路径,不经过这个状态机
6.4 阶段四: commitFinishDrawingLocked --- COMMIT_DRAW_PENDING → READY_TO_SHOW
此方法在performSurfacePlacement的mApplySurfaceChangesTransaction中被调用:
java
// DisplayContent.java
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
if (w.mHasSurface) {
final boolean committed = w.mWinAnimator.commitFinishDrawingLocked();
// ...
}
// ...
// ★ 更新Activity的窗口绘制状态
if (activity != null && activity.isVisibleRequested()) {
activity.updateDrawnWindowStates(w); // → updateAllDrawn()
}
};
commitFinishDrawingLocked实现:
java
// WindowStateAnimator.java
boolean commitFinishDrawingLocked() {
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
mDrawState = READY_TO_SHOW; // ★ COMMIT_DRAW_PENDING → READY_TO_SHOW
boolean result = false;
final ActivityRecord activity = mWin.mActivityRecord;
// ★ 判断是否可以立即显示
if (activity == null || activity.canShowWindows()
|| mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = mWin.performShowLocked(); // → READY_TO_SHOW → HAS_DRAWN
}
// 否则: 保持在READY_TO_SHOW,等allDrawn后统一显示
return result;
}
三种显示时机:
| 条件 | 行为 |
|---|---|
activity == null |
系统窗口,立即performShow |
activity.canShowWindows() |
Activity所有窗口已绘制完,统一显示 |
TYPE_APPLICATION_STARTING |
StartingWindow不等其他窗口 |
| 否则 | 保持在READY_TO_SHOW,等updateAllDrawn |
6.5 阶段五: performShowLocked --- READY_TO_SHOW → HAS_DRAWN
java
// WindowState.java
boolean performShowLocked() {
// ① 用户可见性
if (!showToCurrentUser()) {
clearPolicyVisibilityFlag(VISIBLE_FOR_USER);
return false;
}
// ② 通知ActivityRecord(在状态检查之前)
final int drawState = mWinAnimator.mDrawState;
if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
&& mActivityRecord != null) {
if (mAttrs.type != TYPE_APPLICATION_STARTING) {
mActivityRecord.onFirstWindowDrawn(this); // → 移除StartingWindow
} else {
mActivityRecord.onStartingWindowDrawn();
}
}
// ③ 前置条件检查
if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
return false;
}
// ④ ★ 状态转换: READY_TO_SHOW → HAS_DRAWN
mWinAnimator.applyEnterAnimationLocked(); // 入场动画
// ★★★ 关键: 设置mLastAlpha=-1,强制下次prepareSurfaceLocked刷新 ★★★
mWinAnimator.mLastAlpha = -1;
mWinAnimator.mDrawState = HAS_DRAWN; // ★ 最终状态
mWmService.scheduleAnimationLocked();
// ⑤ 递归显示子窗口
if (mHidden) {
mHidden = false;
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState c = mChildren.get(i);
if (c.mWinAnimator.mSurfaceControl != null) {
c.performShowLocked();
if (displayContent != null) {
displayContent.setLayoutNeeded();
}
}
}
}
return true;
}
isReadyForDisplay检查:
java
// WindowState.java
boolean isReadyForDisplay() {
final boolean parentAndClientVisible = !isParentWindowHidden()
&& mViewVisibility == View.VISIBLE;
return mHasSurface
&& isVisibleByPolicy()
&& !mDestroying
&& mToken.isVisible()
&& (parentAndClientVisible
|| isAnimating(TRANSITION | PARENTS));
}
isOnScreen检查(prepareSurfaceLocked使用):
java
// WindowState.java
boolean isOnScreen() {
if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
return false;
}
final ActivityRecord atoken = mActivityRecord;
if (atoken != null) {
final boolean isVisible = isStartingWindowAssociatedToTask()
? mStartingData.mAssociatedTask.isVisible() : atoken.isVisible();
return ((!isParentWindowHidden() && isVisible)
|| isAnimationRunningSelfOrParent());
}
// ...
}
7. prepareSurface链路: Surface显示控制
prepareSurface是mDrawState状态机之外的另一条关键链路------它负责在每次动画帧中根据窗口状态实际控制Surface的显示/隐藏。
7.1 prepareSurface调用入口 --- 两条路径
路径一: commitFinishDrawing后的即时调用
java
// WindowState.java
boolean commitFinishDrawing(SurfaceControl.Transaction t) {
boolean committed = mWinAnimator.commitFinishDrawingLocked();
if (committed) {
// ★ commitFinishDrawingLocked返回true后,立即prepareSurface
// 但此时mDrawState=READY_TO_SHOW(还没到HAS_DRAWN)
// prepareSurfaceLocked不会show------要等performShowLocked后
mWinAnimator.prepareSurfaceLocked(t);
}
// 递归子窗口
for (int i = mChildren.size() - 1; i >= 0; i--) {
committed |= mChildren.get(i).commitFinishDrawing(t);
}
return committed;
}
路径二: 动画循环中的递归调用(主要路径,Surface真正显示的地方)
java
// WindowAnimator.java
private void animate(long frameTimeNs) {
// ...
for (int i = 0; i < numDisplays; i++) {
final DisplayContent dc = root.getChildAt(i);
dc.updateWindowsForAnimator();
dc.prepareSurfaces(); // ★ 递归调用所有窗口的prepareSurfaces
}
}
递归调用链:
java
WindowAnimator.animate()
└── DisplayContent.prepareSurfaces()
└── super.prepareSurfaces() // WindowContainer --- 递归children
└── WindowState.prepareSurfaces()
├── updateSurfacePositionNonOrganized()
├── updateFrameRateSelectionPriorityIfNeeded()
├── updateScaleIfNeeded()
├── mWinAnimator.prepareSurfaceLocked(t) ★ 核心
├── applyDims()
└── super.prepareSurfaces() → 子窗口递归
java
// WindowState.java
void prepareSurfaces() {
mIsDimming = false;
if (mHasSurface) {
updateSurfacePositionNonOrganized(); // 更新Surface位置
updateFrameRateSelectionPriorityIfNeeded(); // 刷新率优先级
updateScaleIfNeeded(); // 缩放
mWinAnimator.prepareSurfaceLocked(getSyncTransaction()); // ★ 核心
applyDims(); // Dim效果
}
super.prepareSurfaces(); // 递归子容器
}
7.2 prepareSurfaceLocked核心逻辑
java
// WindowStateAnimator.java
void prepareSurfaceLocked(SurfaceControl.Transaction t) {
final WindowState w = mWin;
if (!hasSurface()) {
if (w.getOrientationChanging() && w.isGoneForLayout()) {
w.setOrientationChanging(false);
}
return;
}
// ① 计算当前帧的透明度
computeShownFrameLocked();
// ② ★ 核心决策: 显示 or 隐藏
if (!w.isOnScreen()) {
// 窗口不在屏幕上 → 隐藏
hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w);
} else if (mLastAlpha != mShownAlpha || mLastHidden) {
// alpha变化 或 之前隐藏 → 更新
mLastAlpha = mShownAlpha;
t.setAlpha(mSurfaceControl, mShownAlpha);
// ③ ★★★ 关键: 只有HAS_DRAWN状态才show Surface ★★★
if (mDrawState == HAS_DRAWN) {
if (mLastHidden) {
showRobustly(t); // ★ Surface.show()
mLastHidden = false;
if (!displayContent.getLastHasContent()) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
}
}
}
// mDrawState < HAS_DRAWN → 只更新alpha,不show
}
// ④ 方向变更完成检查
if (w.getOrientationChanging()) {
if (!w.isDrawn()) {
w.mWmService.mRoot.mOrientationChangeComplete = false;
} else {
w.setOrientationChanging(false);
}
}
}
prepareSurfaceLocked决策流程图:
ini
prepareSurfaceLocked(t)
│
├── hasSurface()? ──── No → return
│
├── computeShownFrameLocked() → mShownAlpha = mAlpha
│
├── isOnScreen()? ──── No → hide(t)
│
└── Yes:
│
├── alpha变了 或 mLastHidden?
│ │
│ ├── t.setAlpha(surface, mShownAlpha)
│ │
│ ├── mDrawState == HAS_DRAWN? ─── No → 只更新alpha,不show
│ │
│ └── Yes:
│ │
│ ├── mLastHidden == true?
│ │ │
│ │ └── ★ showRobustly(t) ★
│ │ t.show(mSurfaceControl)
│ │ setShown(true)
│ │ mLastHidden = false
│ │
│ └── mLastHidden == false → 已显示,只更新alpha
│
└── 方向变更检查
7.3 showRobustly --- Surface真正显示
java
// WindowStateAnimator.java
private void showRobustly(SurfaceControl.Transaction t) {
if (mSurfaceShown) {
return; // 已经显示
}
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", mTitle);
setShown(true); // mSurfaceShown = true
t.show(mSurfaceControl); // ★ SurfaceControl.show() → SurfaceFlinger
if (mWin.mIsWallpaper) {
EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE, ...);
}
}
java
// WindowStateAnimator.java line 224-229
private void setShown(boolean surfaceShown) {
mSurfaceShown = surfaceShown;
mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mWin, surfaceShown);
mWin.onSurfaceShownChanged(surfaceShown); // 通知WindowState → Input系统
mSession.onWindowSurfaceVisibilityChanged(mWin, mSurfaceShown);
}
Framework开发关注:
showRobustly是Surface真正显示 的地方------t.show(mSurfaceControl)发送给SurfaceFlingersetShown(true)触发onSurfaceShownChanged,影响Input系统(窗口开始接收触摸事件)mSurfaceShown防止重复show
7.4 computeShownFrameLocked --- 透明度计算
java
// WindowStateAnimator.java
void computeShownFrameLocked() {
if (mWin.mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
return;
} else if (mWin.isDragResizeChanged()) {
// drag-resize中 → 不更新shownFrame(等新Surface的draw)
return;
}
mShownAlpha = mAlpha;
}
7.5 prepareSurface与mDrawState的关系
mDrawState和prepareSurface是两条独立的控制线,协同工作:
| mDrawState | performShowLocked动作 | prepareSurfaceLocked行为 |
|---|---|---|
DRAW_PENDING |
未执行 | hide(t) --- Surface隐藏 |
COMMIT_DRAW_PENDING |
未执行 | hide(t) --- Surface隐藏 |
READY_TO_SHOW |
如果通过检查 → 设置HAS_DRAWN, mLastAlpha=-1 | 可能hide(t)(因mDrawState还不是HAS_DRAWN) |
HAS_DRAWN |
已执行 | showRobustly(t) --- Surface显示! |
关键连接点:
performShowLocked设置mDrawState = HAS_DRAWN同时 设置mLastAlpha = -1- 下次
prepareSurfaceLocked被调用时,检测到mLastAlpha != mShownAlpha(因为-1 != mAlpha) - 进入alpha更新分支,检测到
mDrawState == HAS_DRAWN且mLastHidden == true - 调用
showRobustly(t)→t.show(surface)→ SurfaceFlinger显示
这就是为什么performShowLocked之后需要scheduleAnimationLocked ------动画循环触发prepareSurfaces()递归,最终执行prepareSurfaceLocked完成Surface显示。
8. ActivityRecord与窗口可见性协同
8.1 canShowWindows --- Activity何时允许窗口显示
java
// ActivityRecord.java
boolean canShowWindows() {
return mTransitionController.isShellTransitionsEnabled()
? mSyncState != SYNC_STATE_WAITING_FOR_DRAW
: allDrawn;
}
| 模式 | 条件 | 含义 |
|---|---|---|
| Shell Transition | mSyncState != SYNC_STATE_WAITING_FOR_DRAW |
现代过渡模式,同步完成即可 |
| 传统模式 | allDrawn == true |
所有关注窗口都已绘制完成 |
8.2 updateAllDrawn --- 所有窗口绘制完成
java
// ActivityRecord.java
void updateAllDrawn() {
if (!allDrawn) {
final int numInteresting = mNumInterestingWindows;
if (numInteresting > 0 && allDrawnStatesConsidered()
&& mNumDrawnWindows >= numInteresting && !isRelaunching()) {
allDrawn = true;
// ★ 强制额外布局 --- commitFinishDrawingLocked会在其中执行
// 此前READY_TO_SHOW的窗口此时能通过canShowWindows检查
if (mDisplayContent != null) {
mDisplayContent.setLayoutNeeded();
}
mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, this).sendToTarget();
}
}
}
Framework开发关注:
mNumInterestingWindows≠ 所有子窗口,只有"感兴趣的"窗口才计入mNumDrawnWindows在每个窗口finishDrawingLocked后通过updateDrawnWindowStates递增allDrawn = true后,commitFinishDrawingLocked中的canShowWindows()变为true- 这是同Activity多窗口协同显示的机制------保证不会只显示部分窗口
8.3 onFirstWindowDrawn --- StartingWindow移除时机
java
// ActivityRecord.java
void onFirstWindowDrawn(WindowState win) {
firstWindowDrawn = true;
mSplashScreenStyleSolidColor = true;
if (mStartingWindow != null) {
win.cancelAnimation();
}
final Task associatedTask = task.mSharedStartingData != null ? task : null;
if (associatedTask == null) {
removeStartingWindow(); // 独立Task → 直接移除
} else if (associatedTask.getActivity(
r -> r.isVisibleRequested() && !r.firstWindowDrawn) == null) {
// 共享Task → 所有Activity的首窗口都绘制完才移除
final ActivityRecord r = associatedTask.getActivity(ar -> ar.mStartingData != null);
if (r != null) {
r.removeStartingWindow();
}
}
}
9. Surface显示与上屏全流程
从mDrawState=HAS_DRAWN到Surface真正上屏,涉及的完整流程:
scss
performShowLocked()
│
├── mDrawState = HAS_DRAWN
├── mLastAlpha = -1 (强制prepareSurface刷新)
├── scheduleAnimationLocked()
│
▼
WindowAnimator.animate() // 下一个动画帧
│
├── dc.updateWindowsForAnimator()
└── dc.prepareSurfaces() // 递归
│
└── WindowState.prepareSurfaces()
│
└── mWinAnimator.prepareSurfaceLocked(t)
│
├── computeShownFrameLocked() → mShownAlpha = mAlpha
│
├── isOnScreen() → true
│
├── mLastAlpha(-1) != mShownAlpha → 进入更新分支
│ ├── t.setAlpha(surface, alpha)
│ │
│ ├── mDrawState == HAS_DRAWN → YES
│ │ └── mLastHidden == true → YES
│ │ │
│ │ ▼
│ │ showRobustly(t)
│ │ ├── setShown(true)
│ │ │ ├── mSurfaceShown = true
│ │ │ ├── onSurfaceShownChanged(true) → Input系统
│ │ │ └── onWindowSurfaceVisibilityChanged()
│ │ └── t.show(mSurfaceControl) ★ SurfaceFlinger
│ │
│ └── mLastHidden = false
│
└── 方向变更完成检查
│ SurfaceFlinger合成
▼
屏幕显示!
applyEnterAnimationLocked:
java
// WindowStateAnimator.java
void applyEnterAnimationLocked() {
final int transit;
if (mEnterAnimationPending) {
mEnterAnimationPending = false;
transit = WindowManagerPolicy.TRANSIT_ENTER;
} else {
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
// 基应用窗口由ActivityRecord控制动画
if (mAttrType != TYPE_BASE_APPLICATION && !mWin.mIsWallpaper
&& !(mWin.mActivityRecord != null
&& mWin.mActivityRecord.hasStartingWindow())) {
applyAnimationLocked(transit, true);
}
}
10. 调试方法
ProtoLog开关
bash
# finishDraw + prepareSurface相关
adb shell dumpsys activity logging enable WM_DEBUG_DRAW
adb shell dumpsys activity logging enable WM_DEBUG_ADD_REMOVE
adb shell dumpsys activity logging enable WM_DEBUG_ANIM
adb shell dumpsys activity logging enable WM_DEBUG_VISIBILITY
adb shell dumpsys activity logging enable WM_DEBUG_SYNC_ENGINE
adb shell dumpsys activity logging enable WM_DEBUG_STARTING_WINDOW
# Surface显示
adb shell dumpsys activity logging enable WM_SHOW_TRANSACTIONS
adb shell dumpsys activity logging enable WM_SHOW_SURFACE_ALLOC
dumpsys
bash
# 查看mDrawState
adb dumpsys window windows | grep -A 30 "Window #"
# 查看allDrawn状态
adb dumpsys activity activities | grep -E "allDrawn|firstWindowDrawn"
# 查看Surface状态
adb dumpsys SurfaceFlinger --list
adb dumpsys SurfaceFlinger | grep -A 5 "<window_name>"
关键日志
ini
# DRAW_PENDING → COMMIT_DRAW_PENDING
finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING <window> in <surface>
# COMMIT_DRAW_PENDING → READY_TO_SHOW
commitFinishDrawingLocked: mDrawState=READY_TO_SHOW <surface>
# READY_TO_SHOW → HAS_DRAWN
performShowLocked: mDrawState=HAS_DRAWN in <window>
# Surface显示!
SURFACE SHOW (performLayout): <window_title>
# allDrawn触发
allDrawn: <activity> interesting=N drawn=M
# Buffer丢弃
Got a buffer for request id=X but latest request is id=Y. drop it.
perfetto
bash
atrace -b 32768 wm view am gfx input sched freq --async_time > trace.bin
# 搜索: finishDrawingWindow / performShow / prepareSurfaceLocked
# 搜索: showRobustly / commitFinishDrawing / wmUpdateFocus
11. Framework开发常见场景
场景1: 窗口显示白屏/黑屏 --- 按mDrawState逐级排查
arduino
1. mDrawState停在DRAW_PENDING
→ 客户端没有调用finishDrawing
→ 检查: performDraw是否执行?createSyncIfNeeded是否创建?
→ 常见: BLAST同步卡住, GPU渲染失败, SyncGroup回调未触发
2. mDrawState停在COMMIT_DRAW_PENDING
→ performSurfacePlacement没有执行
→ 检查: requestTraversal是否被调用?mDeferDepth > 0?
→ 常见: deferLayout阻塞, mInLayout递归保护
3. mDrawState停在READY_TO_SHOW
→ canShowWindows()返回false
→ 检查: allDrawn? mSyncState? mNumDrawnWindows vs mNumInterestingWindows?
→ 常见: 同Activity其他窗口未完成绘制
4. mDrawState == HAS_DRAWN 但Surface不可见
→ prepareSurfaceLocked没被调用(动画循环没触发)
→ 检查: scheduleAnimationLocked是否执行?
→ 或: isOnScreen()返回false
→ 检查: isVisibleByPolicy? isParentWindowHidden?
场景2: prepareSurfaceLocked没有show Surface
css
前提: mDrawState已经是HAS_DRAWN
1. isOnScreen()返回false?
→ mHasSurface? mDestroying? isVisibleByPolicy?
→ atoken.isVisible()? isParentWindowHidden?
2. mLastHidden已经是false?
→ 之前已经show过了
3. mLastAlpha == mShownAlpha && !mLastHidden?
→ alpha没变化且已显示 → 不需要操作
4. 动画循环没运行?
→ scheduleAnimationLocked没被调用?
→ WindowAnimator.animate()没被执行?
场景3: StartingWindow不消失
markdown
1. performShowLocked是否执行? → onFirstWindowDrawn触发
2. mStartingWindow != null?
3. 共享StartingData: 其他Activity是否都绘制完?
4. removeStartingWindow动画是否完成?
场景4: BLAST同步超时/ANR
markdown
1. syncSeqId匹配? → mPrepareSyncSeqId > syncSeqId → Buffer丢弃
2. syncNextTransaction回调是否触发? → GPU卡住?
3. 系统进程死锁: createSyncIfNeeded的Binder检查
场景5: 多窗口协同显示问题
markdown
1. allDrawn不为true? → mNumDrawnWindows < mNumInterestingWindows
2. canShowWindows()? → Shell Transition查mSyncState / 传统查allDrawn
3. 某窗口被错误排除? → isGoneForLayout检查
场景6: 窗口resize后闪烁
scss
1. computeShownFrameLocked中isDragResizeChanged() → 跳过shownFrame更新
2. resize过程中旧帧在新位置显示? → mDrawState被重置为DRAW_PENDING?
3. prepareSurfaceLocked在HAS_DRAWN和DRAW_PENDING间切换?
场景7: 异步旋转时窗口显示异常
scss
1. AsyncRotationController拦截了finishDrawing?
→ handleFinishDrawing返回true → skipLayout=true
2. 旋转完成后prepareSurfaces是否重新执行?
3. 方向变更卡住? → getOrientationChanging()一直为true → isDrawn()检查
12. 完整时序图
scss
App Process system_server
────────── ─────────────
│
│ [relayout已完成]
│ [Surface已创建, mDrawState=DRAW_PENDING, mLastHidden=true]
│
▼
performTraversals()
├── performMeasure() → performLayout()
├── createSyncIfNeeded()
├── performDraw(surfaceSyncGroup)
│ ├── draw() → ThreadedRenderer.draw(mView)
│ └── registerCallbacksForSync()
│ └── mBlastBufferQueue.syncNextTransaction()
│
│ ... GPU异步渲染 ...
│
│ onFrameDraw → markSyncReady → [SSG回调]
│ │
│ reportDrawFinished(t, seqId)
│ │
│ │ finishDrawing(window, t, seqId)
│ │──────────────────────────────▶│
│ │ │
│ │ WMS.finishDrawingWindow()
│ │ │
│ │ WindowState.finishDrawing()
│ │ [BLAST同步/旋转/seqId匹配]
│ │ │
│ │ finishDrawingLocked()
│ │ ★ mDrawState = COMMIT_DRAW_PENDING
│ │ │
│ │ requestTraversal()
│ │ │
│ │ performSurfacePlacement()
│ │ │
│ │ mApplySurfaceChangesTransaction
│ │ │
│ │ commitFinishDrawingLocked()
│ │ ★ mDrawState = READY_TO_SHOW
│ │ │
│ │ canShowWindows()?
│ │ ┌──Yes─────┤────No──────┐
│ │ │ │ │
│ │ performShowLocked() 等allDrawn
│ │ │
│ │ isReadyForDisplay()?
│ │ ┌──Yes───┤───No───┐
│ │ │ │ │
│ │ applyEnterAnimationLocked()
│ │ │ 等下次布局循环
│ │ mLastAlpha = -1
│ │ ★ mDrawState = HAS_DRAWN
│ │ scheduleAnimationLocked()
│ │ │
│ │ │ ┌──────── 动画循环 ─────────┐
│ │ │ │ WindowAnimator.animate() │
│ │ │ │ dc.prepareSurfaces() │
│ │ │ │ 递归到每个WindowState: │
│ │ │ │ prepareSurfaceLocked(t) │
│ │ │ │ │ │
│ │ │ │ ├── isOnScreen()? YES │
│ │ │ │ ├── mLastAlpha != alpha? YES(-1)
│ │ │ │ ├── mDrawState == HAS_DRAWN? YES
│ │ │ │ └── mLastHidden? YES │
│ │ │ │ │ │
│ │ │ │ ▼ │
│ │ │ │ showRobustly(t) │
│ │ │ │ t.show(mSurfaceControl)│
│ │ │ │ mLastHidden = false │
│ │ │ │ mSurfaceShown = true │
│ │ │ │ │ │
│ │ │ └─────────┼────────────────┘
│ │ │ │
│ │ │ SurfaceFlinger合成上屏 ★
│ │ │
│ mReportNextDraw = false
│ mActiveSurfaceSyncGroup = null
│
▼
[窗口可见, 用户看到内容]
13. 源码文件索引
| 文件 | 路径 | 关键方法/行号 |
|---|---|---|
| ViewRootImpl.java | core/java/android/view/ |
performDraw() ~5383, draw() ~5601, reportDrawFinished() ~5289, createSyncIfNeeded() ~4489, registerCallbacksForSync() ~12702 |
| IWindowSession.aidl | core/java/android/view/ |
finishDrawing() --- Binder接口 |
| Session.java | services/.../wm/ |
finishDrawing() ~314 |
| WindowManagerService.java | services/.../wm/ |
finishDrawingWindow() ~2803 |
| WindowState.java | services/.../wm/ |
finishDrawing() ~5884, performShowLocked() ~4467, commitFinishDrawing() ~4438, prepareSurfaces() ~5337, isReadyForDisplay() ~1983, isOnScreen() ~1917, isDrawn() ~2073, isDisplayed() ~2026 |
| WindowStateAnimator.java | services/.../wm/ |
mDrawState常量 ~129-152, finishDrawingLocked() ~231, commitFinishDrawingLocked() ~261, resetDrawState() ~282, prepareSurfaceLocked() ~440, computeShownFrameLocked() ~420, showRobustly() ~514, setShown() ~224, applyEnterAnimationLocked() ~548, createSurfaceLocked() ~294, destroySurface() ~707 |
| WindowAnimator.java | services/.../wm/ |
animate() ~113 --- prepareSurfaces的触发者 |
| DisplayContent.java | services/.../wm/ |
mApplySurfaceChangesTransaction ~1002, prepareSurfaces() ~5606 |
| ActivityRecord.java | services/.../wm/ |
canShowWindows() ~4877, updateAllDrawn() ~5308, onFirstWindowDrawn() ~6918, prepareSurfaces() ~7831 |
| WindowContainer.java | services/.../wm/ |
prepareSurfaces() ~2934 --- 递归分发, SYNC_STATE_* ~329-342 |
| BLASTSyncEngine.java | services/.../wm/ |
METHOD_*常量 ~87-94 |