解密: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)是实现窗口显示的核心基础。

相关推荐
1570925113420 小时前
Android进阶之光:HTTP协议原理深度解析
android·网络协议·http
终端安全笔记20 小时前
安卓五品牌通道差在哪:监管通道拆解
android
v_348360876221 小时前
Android native端 堆栈打印
android·算法
一笑的小酒馆1 天前
AndroidKMP之导航和WebView
android
2501_932750261 天前
Android BottomNavigationView 入门介绍
android
Godikov1 天前
硬件异步事件下的业务一致性:智能柜领取/归还流程的竞态设计
android
Godikov1 天前
不用 Netty:Android 手写 TCP 客户端实战——自定义协议帧、粘包处理与可靠重连
android
事圆则缓1 天前
Java 面向对象如何落到 Android View 体系
android
iPad协议个微协议1 天前
# 微信自动营销系统如何基于 WechatApi 做事件驱动设计
android·微信·企业微信·个人开发·wechatapi·微信个人号开发
AirDroid_cn1 天前
隐私沙盒:第三方应用读取剪切板内容如何拦截?
android·gitee