Android-Framework-06-WMS-01-Window

190 阅读18分钟

1 Window、WindowManager、WMS

image.png

Window:在Android视图体系中Window就是一个窗口的概念。Android中所有的视图都是依赖于Window显示的。

WindowManager:对Window的管理,包括新增、更新和删除等。

WMS:窗口的最终管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理。

2 Window的基本概念

2.1 常见Window

image.png

2.2 窗口的次序

image.png

2.3 Window分类

image.png

Application Window:Activity就是一个典型的应用程序窗口。

Sub Window:子窗口,顾名思义,它不能独立存在,需要附着在其他窗口才可以,PopupWindow就属于子窗口。

System Window:输入法窗口、系统音量条窗口、系统错误窗口都属于系统窗口

2.3.1 ApplicationWindow

image.png

public static final int FIRST_APPLICATION_WINDOW = 1;

public static final int TYPE_BASE_APPLICATION = 1;

public static final int TYPE_APPLICATION = 2;

public static final int TYPE_APPLICATION_STARTING = 3;

public static final int TYPE_DRAWN_APPLICATION = 4;

public static final int LAST_APPLICATION_WINDOW = 99;

2.3.2 Sub Window

image.png

public static final int FIRST_SUB_WINDOW = 1000;

public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;

public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;

public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;

public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;

public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW +4;

public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW+5;

public static final int LAST_SUB_WINDOW = 1999;

2.3.3 System Window

image.png

public static final int FIRST_SYSTEM_WINDOW = 2000;

public static final int TYPE_STATUS_BAR =FIRST_SYSTEM_WINDOW;

public static final int TYPE_SEARCH_BAR =FIRST_SYSTEM_WINDOW+1;

public static final int TYPE_PHONE =FIRST_SYSTEM_WINDOW+2;

public static final int TYPE_SYSTEM_ALERT =FIRST_SYSTEM_WINDOW+3;

public static final int TYPE_KEYGUARD =FIRST_SYSTEM_WINDOW+4;

public static final int TYPE_TOAST =FIRST_SYSTEM_WINDOW+5;

...

2.4 窗口的次序

image.png

Android WindowManagerService 的窗口管理体系中,WindowState 的主序(主层级)和子序(子层级)主要是用于描述窗口在屏幕显示中的层级关系和顺序,确保窗口按照优先级正确显示。


1. 主序(主层级)

主序决定窗口的大层级(Z-Order),是由窗口的 类型WindowManager.LayoutParams.type)决定的,通常分为以下几类:

常见主层级
  1. 系统优先窗口

    • 包括状态栏(Status Bar)、导航栏(Navigation Bar)、系统对话框等。

    • 通常优先级最高,显示在所有应用窗口之上。

    • 示例:

      • TYPE_STATUS_BAR(状态栏)
      • TYPE_NAVIGATION_BAR(导航栏)
      • TYPE_SYSTEM_ERROR(系统错误提示)
  2. 应用窗口

    • 包括普通的 Activity 窗口。

    • 属于应用正常使用的显示内容,通常显示在用户界面中间层。

    • 示例:

      • TYPE_APPLICATION(普通应用窗口)
      • TYPE_APPLICATION_OVERLAY(悬浮窗口,如悬浮按钮)
  3. 子窗口(附属窗口)

    • 附属于主窗口的对话框或弹窗。

    • 示例:

      • TYPE_APPLICATION_PANEL(应用面板,如弹出的对话框)
      • TYPE_APPLICATION_SUB_PANEL(子面板,如上下文菜单)
  4. 其他特殊窗口

    • 包括 Toast 提示、悬浮窗口等。

    • 示例:

      • TYPE_TOAST(Toast 提示)
      • TYPE_PHONE(电话窗口)

2. 子序(子层级)

子序是在主序之内进一步排序的依据,主要由窗口的 Z-Order 和显示优先级决定。子序主要解决相同类型的窗口内部如何排序的问题。

常见影响因素
  1. 窗口层级值(mLayer

    • WindowManagerService 为每个窗口计算其层级值 mLayer
    • 通常根据窗口类型和 Z-Order 的规则动态计算。
  2. 窗口 Token 顺序

    • 多个窗口共用一个 WindowToken(例如同一任务栈的多个 Activity 窗口)时,子序按照创建顺序或焦点状态调整。
  3. Activity/Task 窗口关系

    • 例如,多个 Activity 窗口之间,当前 Activity 的窗口通常优先显示。
  4. 动画效果影响

    • 某些窗口动画(如打开、关闭过渡动画)可能临时改变子序。

3. 主序和子序的计算流程

主序和子序的计算逻辑主要在 WindowManagerService 的 WindowState 类中完成:

  1. 主序计算

    • 按窗口类型,确定主层级:

      java
      复制代码
      int baseLayer = getBaseLayer(params.type);
      
  2. 子序调整

    • 根据 Token 顺序或窗口特性调整子序:

      java
      复制代码
      int layer = baseLayer + token.layerOffset;
      
  3. 最终层级确定

    • 如果有动画或临时调整,动态更新子序:

      java
      复制代码
      layer += animationLayerAdjustment;
      

4. 示例:主序与子序的关系

以普通应用窗口和悬浮窗口为例:

  • 主序

    • 应用窗口的主序(TYPE_APPLICATION)低于系统窗口。
    • 悬浮窗口(TYPE_APPLICATION_OVERLAY)的主序比普通应用窗口高。
  • 子序

    • TYPE_APPLICATION_OVERLAY 内部,多个悬浮窗口根据创建顺序或指定 Z-Order 排列。

5. 结论

  • 主序 决定窗口的大层级,按照窗口类型排序,确保系统窗口优先于应用窗口。
  • 子序 进一步细化相同类型窗口的排列顺序,通过窗口的 Z-OrderToken 等属性动态调整。

主序和子序的协作机制,确保 Android 系统的窗口在复杂场景下能够按预期正确显示。主序用于描述窗口及其子窗口在所有窗口中的显示位置。子序则描述了一个子窗口在其兄弟窗口中的显示位置。主序越大,则窗口及其子窗口的显示位置相对于其他窗口的位置越靠前。子序越大,则子窗口相对于其兄弟窗口的位置越靠前。对于父窗口而言,其主序取决于其类型,其子序则保持为0。而子窗口的主序与其父窗口一样,子序则取决于其类型。

2.5 窗口的标志

  • // 当 Window 可见时允许锁屏FLAG_ALLOW_LOCK_WHILE_SCREEN_ON

  • // Window 不能获得输入焦点,即不接受任何按键或按钮事件,例如该 Window 上 有 EditView,点击 EditView 是 不会弹出软键盘的

  • // Window 范围外的事件依旧为原窗口处理;例如点击该窗口外的view,依然会有响应。另外只要设置了此Flag,都将会启用FLAG_NOT_TOUCH_MODAL

FLAG_NOT_FOCUSABLE = 0x00000008;

  • // 设置了该 Flag,将 Window 之外的按键事件发送给后面的 Window 处理, 而自己只会处理 Window 区域内的触摸事件

  • // Window 之外的 view 也是可以响应 touch 事件。

FLAG_NOT_TOUCH_MODAL = 0x00000020;

  • // 设置了该Flag,表示该 Window 将不会接受任何 touch 事件,例如点击该 Window 不会有响应,只会传给下面有聚焦的窗口。

FLAG_NOT_TOUCHABLE ;

  • // 只要 Window 可见时屏幕就会一直亮着 FLAG_KEEP_SCREEN_ON

  • // 允许 Window 超过屏幕之外 FLAG_LAYOUT_NO_LIMITS

  • // 当用户的脸贴近屏幕时(比如打电话),不会去响应此事件 FLAG_IGNORE_CHEEK_PRESSES ;

  • // 窗口可以在锁屏的 Window 之上显示, 使用 Activity#setShowWhenLocked(boolean) 方法代替FLAG_SHOW_WHEN_LOCKED = 0x00080000;

3 WindowManager

image.png

3.1 添加Window

image.png

Activity#attach()方法之内PhoneWindow被创建,并同时创建一WindowManagerImpl负责维护PhoneWindow内的内容。

在Activity#onCreate()中调用setContentView()方法,这个方法内部创建一个DecorView实例作为PhoneWindow的内容。

WindowManagerImpl决定管理DecorView,并创建一个ViewRootImpl实例,将ViewRootImpl与View树进行关联,这样ViewRootImpl就可以指挥View树的具体工作。

3.2 activity与 PhoneWindow与DecorView关系

image.png

DecorView是FrameLayout的子类,它可以被认为是Android视图树的根节点视图

image.png

3.3 WindowManagerGlobal

image.png

3.4 ViewRootImpl

image.png

ViewRootImpl 是 Android 中一个非常重要的类,它是 View 树的根节点,负责将 View 层与 WindowManager 系统服务连接起来。ViewRootImpl 的职责是管理 View 的绘制、布局和事件分发,以及与窗口系统交互。

ViewRootImpl 是由 WindowManager 创建的。具体来说,它是在 WindowManagerImpl 调用 addView() 方法时,由 WindowManagerGlobal 内部负责创建的。


创建过程概述

  1. Activity 启动时

    • 每个 Activity 会创建一个 Window 对象(通常是 PhoneWindow)。
    • PhoneWindow 的顶层视图是 DecorView,负责管理界面的 UI 树。
    • WindowManager.addView() 被调用时,DecorView 会被添加到窗口系统中。
  2. WindowManager.addView() 方法

    • WindowManager 是一个接口,实际实现类是 WindowManagerImpl
    • WindowManagerImpladdView() 方法最终调用了 WindowManagerGlobal.addView()
  3. WindowManagerGlobal 创建 ViewRootImpl

    • WindowManagerGlobal.addView() 方法中,ViewRootImpl 实例被创建,并与 DecorView 绑定。

1. ViewRootImpl 的定位

  1. View 树的根节点

    • 在 Android 的 UI 系统中,View 树的根节点并不是直接由开发者创建的,而是由系统自动生成的 ViewRootImpl
    • 它是 DecorView 和窗口(WindowManager)之间的桥梁。
    • DecorViewActivity 的顶级视图,包含了标题栏、内容视图等。而 ViewRootImpl 是实际管理 DecorView 的类。
  2. 连接 ViewWindowManager

    • ViewRootImpl 通过 WindowManagerGlobal 将视图树与 WindowManager 进行绑定。
    • 每个 View 树的根节点都由一个 ViewRootImpl 实例管理。

2. ViewRootImpl 的主要职责

(1)视图绘制流程

image.png

  • ViewRootImpl 负责整个 View 树的绘制流程,包括以下三个主要阶段:

    1. 测量(Measure)

      • 触发 ViewGroup 和其子视图的 onMeasure 方法,计算每个视图的大小。
    2. 布局(Layout)

      • 确定每个 View 的位置,调用 onLayout 方法。
    3. 绘制(Draw)

      • 调用每个 ViewonDraw 方法,将视图渲染到屏幕上。
  • 这些流程是由 ViewRootImplperformTraversals 方法触发的。

(2)事件分发

image.png

  • ViewRootImpl 负责将用户输入事件(如触摸、按键等)从系统事件队列传递到 View 树。

  • 事件分发流程:

    • ViewRootImplInputDispatcher 获取事件。
    • 调用 View 树根节点的 dispatchTouchEventdispatchKeyEvent 方法,将事件分发给视图。

image.png

DecorView虽然是ViewGroup,但它并不会直接分发给它的child,也不会传递给它的父View,而是先分发给Activity,为什么要这么做呢?

image.png 我们可想DecorView 拿到事件后,若直接向下分发,那就没Activity的事了,但Activity也想成为事件分发的一环,并还想作为优先级较高的部分。所以就可以通过这种方式,绕了一圈又回到DecorView并再往下分发。DecorView在这里承担两个职责:

  • 在接收到输入事件时,它不同于普通View,分发给子view,而是会先将事件分发给上层的Activity

  • 接收到上层Activity分发下的事件后,又会变成普通View,进行ViewGroup的事件分发

(3)管理窗口的生命周期
  • ViewRootImpl 通过 WindowManager 来管理窗口(Window)的添加、删除和更新。
  • 它接收窗口的各种状态变化(如大小调整、焦点变化),并通知 View 树更新。

image.png

(4)消息处理
  • ViewRootImpl 使用 Handler 来处理与 UI 相关的消息。

  • 常见的消息:

    • 绘制视图(MSG_DO_TRAVERSAL
    • 处理输入事件(MSG_PROCESS_INPUT_EVENTS
    • 窗口大小调整(MSG_RESIZED

3. ViewRootImpl 的核心方法

(1)performTraversals
  • 这是 ViewRootImpl 中最重要的方法之一,用于完成视图的测量、布局和绘制流程。

  • 具体流程:

    1. 调用 View.measure(),计算视图的大小。
    2. 调用 View.layout(),确定视图的位置。
    3. 调用 View.draw(),将视图绘制到屏幕上。
(2)dispatchInputEvent
  • 用于处理输入事件,如触摸和按键事件。

  • 流程:

    1. 将事件传递给 DecorView
    2. 通过 ViewGroup 的事件分发机制,将事件传递到目标 View
(3)scheduleTraversals
  • 触发一次完整的视图刷新流程。
  • 当视图树发生变化(如视图大小、位置变化或需要重绘)时调用。
(4)setView
  • 负责将一个 DecorView 与窗口系统绑定。
  • Activity 启动时,WindowManager.addView() 方法会调用此方法,将 DecorView 添加到窗口中。

4. ViewRootImpl 的生命周期

  1. 初始化

    • WindowManager.addView() 被调用时,ViewRootImpl 会被创建,并绑定一个 DecorView
  2. 运行时管理

    • 在应用运行过程中,ViewRootImpl 负责处理视图树的绘制、布局、事件分发等。
  3. 销毁

    • WindowManager.removeView() 被调用时,ViewRootImpl 会将视图树从窗口中移除,并释放相关资源。

5. ViewRootImpl 的作用与意义

  • 连接桥梁

    • 作为 View 树和系统窗口的连接桥梁,它将用户的操作与应用的 UI 渲染有效结合。
  • 高效管理 UI

    • 通过消息队列、输入分发、绘制流程等,ViewRootImpl 高效地管理了 UI 的更新和响应。
  • 优化系统性能

    • 它通过分帧绘制、事件优化等机制,确保了 UI 的流畅性。

6. ViewRootImpl 的典型调用流程

以下是 ViewRootImpl 在一个 Activity 启动过程中的调用流程:

  1. Activity 创建窗口

    • Activity 启动时,Window 对象被创建。
    • Window 的顶级视图是 DecorView
  2. WindowManager 添加视图

    • WindowManager.addView() 被调用。
    • 系统会创建一个 ViewRootImpl 实例,并调用其 setView() 方法,将 DecorViewViewRootImpl 绑定。
  3. 触发视图绘制

    • ViewRootImplperformTraversals 方法被调用,完成视图的测量、布局和绘制流程。
  4. 事件分发

    • 用户的触摸或按键事件通过 InputDispatcher 传递给 ViewRootImpl
    • 事件通过 ViewRootImpl.dispatchInputEvent() 方法分发到 DecorView,并最终传递到目标 View

4 UI刷新的流程

1. 刷新流程概述

Android UI 刷新是一个复杂的过程,主要由以下步骤组成:

  1. 触发刷新请求:应用逻辑调用 invalidate()requestLayout()
  2. 主线程任务调度:通过 ViewRootImplscheduleTraversals(),将刷新任务发送到消息队列。
  3. 执行绘制流程ViewRootImpl 执行视图树的三大流程:measure(测量)、layout(布局)、draw(绘制)。
  4. 与硬件加速交互:通过 Choreographer 控制帧同步和绘制时机。
  5. 渲染到屏幕:最终将 UI 数据交给 GPU 进行绘制,并通过 SurfaceFlinger 显示在屏幕上。

2. 刷新触发机制

刷新流程通常由以下两种情况触发:

  • 视图内容变化

    • 调用 View.invalidate():只触发重绘,不涉及视图树的重新布局。
    • 调用 View.requestLayout():视图大小或位置发生变化,触发布局和绘制。
  • 系统事件

    • 如屏幕旋转、窗口大小改变或 Activity 生命周期回调(如 onResume)等。

3. 主线程任务调度

  1. View.invalidate()requestLayout()

    • invalidate() 会标记当前视图为需要重绘。
    • requestLayout() 会标记视图树为需要重新布局,并触发整个视图树的重新绘制。
  2. ViewRootImpl.scheduleTraversals()

    • invalidate()requestLayout() 最终都会调用 ViewRootImpl.scheduleTraversals()
    • 它会将一个刷新任务(doTraversal)投递到主线程的消息队列中。
  3. 通过 LooperHandler 调度

    • ViewRootImpl 使用主线程的 Handler 将刷新任务发送到 MessageQueue
    • 当主线程空闲时,处理该刷新任务。

4. 绘制流程

核心绘制流程由 ViewRootImpl.performTraversals() 方法驱动,依次完成以下三个阶段:

(1)测量阶段(Measure)
  • 调用 View.measure(),从根视图开始递归测量每个子视图的尺寸。
  • 每个视图通过其 onMeasure() 方法决定自己的大小。
  • 结果存储在 MeasureSpec 中。
(2)布局阶段(Layout)
  • 调用 View.layout(),从根视图开始递归为每个子视图设置具体的位置。
  • 每个视图通过其 onLayout() 方法决定子视图的位置。
(3)绘制阶段(Draw)
  • 调用 View.draw(),从根视图开始递归绘制视图树。

  • 绘制过程依次调用:

    1. drawBackground() :绘制背景。
    2. onDraw() :绘制视图内容。
    3. dispatchDraw() :绘制子视图。
    4. drawForeground() :绘制前景。

5. 帧同步与硬件加速

  1. Choreographer

    • Choreographer 是 Android 控制帧同步的核心组件。
    • 它会根据屏幕刷新频率(通常是 60 FPS,即每 16ms 一帧)调用 doFrame() 方法,确保绘制过程与屏幕刷新节奏一致。
  2. 硬件加速

    • 绘制过程通常使用 GPU 硬件加速,通过 OpenGL 将视图内容渲染到缓冲区。
    • Android 使用 DisplayList(显示列表)记录视图的绘制命令,并通过 RenderThread 提交给 GPU。

6. 渲染到屏幕

  1. Surface 和 SurfaceFlinger

    • ViewRootImpl 最终将绘制内容提交到 Surface
    • Surface 是视图内容在系统中的缓冲区,属于 SurfaceControl 管理的图层。
  2. 合成与显示

    • 系统中的 SurfaceFlinger 合成所有应用窗口的内容,并通过硬件 Composer 显示到屏幕上。

7. 完整调用链

代码触发流程
java
复制代码
View.invalidate() → ViewParent.invalidateChild() → ViewRootImpl.invalidateChild()  
→ scheduleTraversals() → doTraversal()  
→ performTraversals() → measure() → layout() → draw()
核心方法调用链
  1. invalidate()requestLayout() 标记视图树需要更新。
  2. scheduleTraversals() 提交刷新任务到主线程消息队列。
  3. doTraversal() 开始视图树的 measurelayoutdraw 阶段。
  4. 调用 Choreographer.postFrameCallback() 注册下一帧刷新。
  5. 最终绘制内容提交到 Surface,通过 SurfaceFlinger 合成显示。

8 面试问题

    1. 连续两次setTextView到底会触发几次UI重绘呢?

image.png

image.png

image.png

等到VSYNC到来后,会移除同步栅栏,并率先开始执行当前帧的处理,调用逻辑如下

image.png

VSYNC要客户端主动申请,才会有有VSYNC到来才会刷新,UI没更改,不会请求VSYNC也就不会刷新UI局部,重绘其实只会去重绘带刷新的View

    1. 为什么Android APP的帧率一般是60FPS?

1. 硬件刷新率的限制

  • 屏幕刷新率

    • 大多数 Android 设备的屏幕刷新率是 60Hz,即屏幕每秒刷新60次。
    • 应用的绘制频率与屏幕刷新率同步,以避免出现画面撕裂(tearing)或卡顿现象。
    • 如果帧率超过屏幕刷新率,额外的帧也无法在屏幕上显示,因此没必要绘制更多帧。

2. 帧时间计算(16ms规则)

  • 每帧时间限制

    • 60FPS意味着每帧的显示时间是 1秒 ÷ 60 = 16.67ms
    • Android 应用需要在这 16ms 内完成所有操作(包括布局计算、绘制、动画、输入事件处理等)。
    • 超过 16ms,就会导致掉帧(frame drop),肉眼会察觉到卡顿。
  • 理论帧率公式

    • 帧率(FPS) = 1 ÷ 每帧所需时间。
    • 如果绘制一帧的时间为 33ms,则帧率降为 30FPS

3. 人眼视觉感知

  • 视觉流畅性的需求

    • 人眼对动态画面的流畅感要求一般在 24-30FPS 以上。
    • 60FPS 被认为是流畅的临界值,足够应对普通应用场景。
  • 更高帧率的平滑效果

    • 高帧率(如120FPS)在游戏和交互性强的场景下表现更好,但会显著增加设备功耗和发热问题。
    • 对于普通移动应用来说,60FPS 已经是性能和功耗的最佳平衡点。

4. Vsync 同步机制

  • 什么是 Vsync?

    • Android 使用 Vsync(Vertical Synchronization)信号来同步屏幕刷新和应用绘制。
    • Vsync 每16.67ms发出一次信号,通知系统准备好下一帧内容。
  • Choreographer 的帧调度

    • Android 的 Choreographer 组件通过监听 Vsync 信号,调用 doFrame() 方法完成绘制任务。
    • 应用的绘制时间点与屏幕刷新周期保持一致,从而避免画面撕裂或不一致。

5 SurfaceFlinger

SurfaceFlinger 第一定律 是指 SurfaceFlinger 合成所有应用窗口内容时的一个基本规则:

"屏幕上的每个像素只能由一个图层提供。"


含义详解

  • SurfaceFlinger 是 Android 中负责图像合成与显示的系统服务。它将来自不同应用或窗口的图层(Layer)合成到一块缓冲区(FrameBuffer)上,并最终通过硬件 Composer 显示在屏幕上。

  • 第一定律 的核心思想是:在任何时刻,屏幕上每个像素点的显示内容都由某个图层独占。

    • 不允许多个图层的内容同时覆盖到同一个像素点。
    • 每个像素点的最终颜色值只能来源于一个图层。

SF是整个Android系统渲染的核心进程。所有应用的渲染逻辑最终都会来到SF中进行处理,最终会把处理后的图像数据交给CPU或者GPU进行绘制。

在每一个应用中都以Surface作为一个图元传递单元,向SF这个服务端传递图元数据。

image.png


作用与设计目的

  1. 避免重复渲染

    • 如果同一个像素被多个图层同时覆盖,系统需要反复计算,导致性能下降。
    • 第一定律确保每个像素只被计算一次,提高了渲染效率。
  2. 明确显示逻辑

    • 确定前景、背景层级(Z-Order)和覆盖关系,确保显示逻辑清晰。
    • 当多个图层存在重叠时,Z-Order 决定优先级,最上层的图层内容会显示。
  3. 优化硬件 Composer

    • 硬件 Composer 是 SurfaceFlinger 用于图像合成的关键组件,第一定律使其无需处理复杂的图层交叠问题。

应用场景

  1. 窗口系统合成

    • 当多个应用窗口(如 Activity、对话框、悬浮窗)同时存在时,SurfaceFlinger 按 Z-Order 合成这些窗口,只显示最上层内容。
  2. 游戏与多媒体播放

    • 游戏场景中,UI 图层、渲染内容图层、特效图层等按顺序合成,避免画面错乱。
    • 视频播放时,播放器的 Surface 会优先显示。
  3. 过渡动画

    • 在应用切换时,通过设置图层的透明度和层级,完成动画效果,而不会破坏显示的完整性。

第一定律的实现

SF是以生产者以及消费者为核心设计思想,把每一个应用进程作为生产者生产图元保存到SF的图元队列中,SF则作为消费者依照一定的规则把生产者存放到SF中的队列一一处理。 image.png

  1. 图层管理

    • SurfaceFlinger 管理每个图层(Layer)的 Z-Order。
    • 根据 Z-Order 决定图层的显示优先级,确保屏幕每个像素的显示来源是最高优先级的图层。
  2. 合成操作

    • SurfaceFlinger 收集所有需要显示的图层数据(通常为 Surface 提供的缓冲区)。
    • 对重叠区域,按照 Z-Order 选择最高优先级的图层内容。
  3. 透明度处理

    • 如果图层具有透明属性(Alpha 值),则对背景进行混合(Blending)操作,计算出最终显示的颜色值。