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

相关推荐
石头猫灯37 分钟前
一次 CMS 被黑实录:完整事件思路梳理
android·学习
zhonyu鱼40 分钟前
Escrcpy:用电脑键盘鼠标操作安卓手机的跨平台投屏工具
android·计算机外设·电脑
千里马学框架1 小时前
安卓开机性能优化:如何安全高效地裁剪 SystemService
android·智能手机·framework·wms·手机·性能·车载
Android打工仔1 小时前
一次 Android 拍照后卡顿的 Perfetto 定位与优化实践
android·性能优化
OpenFDE开源桌面1 小时前
实操:如何将安卓 App与Linux系统应用级融合(附代码)
android·linux
xiangxiongfly9151 小时前
Android VideoView总结
android·videoview
杉氧1 小时前
从 Modifier 到 Flexbox:React Native 布局与样式设计哲学
android·前端·react native
Kapaseker2 小时前
我常用的 5 个 Kotlin 优化小技巧
android·kotlin
恋猫de小郭2 小时前
Flutter 多窗口支持类型和 API 介绍
android·前端·flutter
张风捷特烈2 小时前
当 AI 遇见 Flutter | 打造 500+ Widget 专属Logo
android·前端·flutter