AOSP15 WMS/AMS系统开发 - WindowManagerService finishDraw与prepareSurface流程详解

基于 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 = truemDrawState = DRAW_PENDING)。窗口需要完成第一帧绘制并通过一系列状态转换后,Surface才最终显示。

整个过程涉及两条主线:

  1. mDrawState状态机 --- 控制窗口绘制的逻辑状态流转
  2. 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完成后能回调通知WMS
  • cancelDraw为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开发关注:

  • finishDrawingWindowmGlobalLock同步块内执行
  • 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 = truerequestTraversal() → 触发commitFinishDrawingLocked执行
  • 后续重绘(resize等)走relayout路径,不经过这个状态机

6.4 阶段四: commitFinishDrawingLocked --- COMMIT_DRAW_PENDING → READY_TO_SHOW

此方法在performSurfacePlacementmApplySurfaceChangesTransaction中被调用:

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)发送给SurfaceFlinger
  • setShown(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显示!

关键连接点:

  1. performShowLocked设置mDrawState = HAS_DRAWN同时 设置mLastAlpha = -1
  2. 下次prepareSurfaceLocked被调用时,检测到mLastAlpha != mShownAlpha(因为-1 != mAlpha)
  3. 进入alpha更新分支,检测到mDrawState == HAS_DRAWNmLastHidden == true
  4. 调用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
相关推荐
帅次4 小时前
Modifier 链与顺序、测量与命中区域
android·kotlin·compose·modifier
leory4 小时前
请详细描述Handler消息机制的工作原理
android·面试
leory4 小时前
请描述Binder IPC的基本原理和工作流程
android·面试
leory4 小时前
View的事件分发机制是怎样的?dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent的关系?
android·面试
zander2584 小时前
Canal本地部署保姆级教程
android
小仙女喂得猪5 小时前
2026 Android 组件化项目的AICoding落地实践
android·kotlin·ai编程
leory5 小时前
请详细描述JVM的垃圾回收机制?
android·面试
leory5 小时前
volatile关键字的作用是什么?它能保证原子性吗?
android·面试
消失的旧时光-19435 小时前
为什么 Linux / Android 系统里全是 struct + 函数指针?—— 一篇讲透 C 语言如何实现面向对象(OOP)
android·linux·c语言