解密:DecorView到底添加到哪里去了,为何能显示出来?

作为Android窗口系统的核心设计,WindowManager.addView() 添加 DecorView 的流程涉及 应用进程与系统服务(WMS)的跨进程协作 以及 图形显示系统的联动。以下是源码分析:


1. 添加的终点:WMS 管理的窗口层级

DecorView 最终被添加到 WindowManagerService (WMS) 维护的全局窗口列表 中,并通过 SurfaceFlinger 渲染到屏幕。关键步骤在 ViewRootImpl 中完成:

源码路径:

  • WindowManagerGlobal.addView()ViewRootImpl.setView()WindowSession.addToDisplay() (IPC) → WMS.addWindow()

2. 核心流程源码解析

(1) 应用进程:WindowManagerGlobal.addView()

java 复制代码
// WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params, ...) {
    ViewRootImpl root = new ViewRootImpl(context, display); // 创建ViewRootImpl
    root.setView(view, wparams, panelParentView); // 关键:关联DecorView
}

(2) ViewRootImpl.setView() :连接DecorView与WMS

java 复制代码
// ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    mView = view; // 持有DecorView实例
    requestLayout(); // 触发布局
    res = mWindowSession.addToDisplayAsUser(...); // IPC调用WMS!
}
  • mWindowSessionIWindowSession.Stub 的代理对象,通过 Binder IPC 与 WMS 通信。

(3) WMS 处理窗口添加:WMS.addWindow()

java 复制代码
// WindowManagerService.java
public int addWindow(Session session, IWindow client, ...) {
    WindowState win = new WindowState(...); // 创建窗口状态对象
    win.attach(); // 建立与客户端的连接
    mWindowMap.put(client.asBinder(), win); // 存入全局Map
    win.addWindowToListInOrderLocked(); // 根据Z-order排序
    WindowSurfaceController surfaceController = win.createSurfaceLocked(); // 创建Surface!
}
  • IWindow client :由 ViewRootImpl.W (Binder对象) 实现,用于 WMS 回调应用进程。
  • WindowState:WMS 中代表一个窗口的核心类,管理窗口状态、层级、动画等。

3. 显示的关键:Surface 的创建与绘制

(1) WindowState.createSurfaceLocked()

java 复制代码
// WindowState.java
void createSurfaceLocked() {
    mWinAnimator.createSurfaceLocked(); // 委托给WindowSurfaceController
}

// WindowSurfaceController.java
void createSurface() {
    mSurface = new Surface(); // 创建Surface对象
    Session.windowAddedLocked(...); // 通过SurfaceFlinger申请图形缓冲区
}
  • Surface :代表一个图形缓冲区,由 SurfaceFlinger 分配和管理。

(2) ViewRootImpl 触发绘制

java 复制代码
// ViewRootImpl.java
void performTraversals() {
    performMeasure();  // 测量
    performLayout();   // 布局
    performDraw();     // 绘制
}

private void performDraw() {
    draw(fullRedrawNeeded); // 触发硬件/软件绘制
}

private void draw(boolean fullRedrawNeeded) {
    Surface surface = mSurface; // 从WMS申请的Surface
    Canvas canvas = surface.lockCanvas(dirty); // 获取Canvas
    mView.draw(canvas); // DecorView绘制内容到Canvas
    surface.unlockCanvasAndPost(canvas); // 提交缓冲区到SurfaceFlinger!
}
  • unlockCanvasAndPost() :通过 BufferQueue 将图形缓冲区提交给 SurfaceFlinger 合成。

4. 显示到屏幕:SurfaceFlinger 合成

  1. 应用进程 :通过 Surface.unlockCanvasAndPost() 将帧数据放入 BufferQueue

  2. SurfaceFlinger

    • VSYNC 信号到达时,从所有窗口的 BufferQueue 中取帧。
    • 根据 WMS 提供的窗口层级(Z-order) 进行图层合成。
    • 将最终帧输出到 FrameBuffer 显示到屏幕。

关键设计总结

组件 作用
DecorView 窗口的根视图,承载UI内容,但自身不直接显示。
ViewRootImpl 连接 DecorView 与 WMS 的桥梁,负责测量、布局、绘制及IPC通信。
WMS 系统服务,管理所有窗口状态(WindowState)、层级和动画。
Surface 由 WMS 申请,SurfaceFlinger 分配的实际图形缓冲区,视图内容绘制于此。
SurfaceFlinger 系统服务,合成所有窗口的 Surface,输出到屏幕。

为何能显示?核心链条

  1. 窗口注册ViewRootImpl 通过 IPC 将 DecorView 添加到 WMS 的窗口树。
  2. Surface 分配:WMS 向 SurfaceFlinger 申请图形缓冲区(Surface)。
  3. 视图绘制ViewRootImplDecorView 内容绘制到 Surface。
  4. 缓冲区提交 :通过 unlockCanvasAndPost() 提交帧到 SurfaceFlinger。
  5. 图层合成:SurfaceFlinger 根据 WMS 提供的 Z-order 合成所有窗口的 Surface。
  6. 显示输出:合成后的帧通过 FrameBuffer 输出到物理屏幕。

关键点DecorView 本身只是一个普通 View 树,其显示能力完全依赖于 WMS 分配的 SurfaceViewRootImpl 的绘制提交机制。跨进程协作(应用 ↔ WMS ↔ SurfaceFlinger)是实现窗口显示的核心基础。

相关推荐
xzkyd outpaper7 分钟前
Kotlin 协程启动方式
android·开发语言·kotlin
用户2018792831672 小时前
Activity 与 Service、BroadcastReceiver、ContentProvider中ANR 的差异
android
用户2018792831672 小时前
WindowManager 添加 DecorView 的本质及显示原理
android
Harry技术3 小时前
Trae搭建Android 开发中 MVVM 架构,使用指南:组件、步骤与最佳实践
android·kotlin·trae
悠哉清闲5 小时前
Room 数据存储
android·数据库
恋猫de小郭11 小时前
Flutter 3.35 发布,快来看看有什么更新吧
android·前端·flutter
雨白14 小时前
加密、签名与编码
android
李新_15 小时前
【Android Bug Fix】UI不响应、异位异常排查
android·程序员
帅得不敢出门16 小时前
Android Framework定制长按电源键关机的窗口
android·java·framework