在 Android 系统中,窗口管理(尤其是多应用、多窗口、弹窗等场景)由 WindowManagerService (WMS) 统一协调,其核心职责是管理所有窗口的层级(Z-Order)、位置、尺寸、焦点和生命周期。以下是其管理机制的分层解析:
1. 窗口的类型与层级(Z-Order)
(1) 窗口类型分类
| 类型 | 示例 | 层级范围 | 说明 |
|---|---|---|---|
| 应用窗口 | Activity、Dialog | 1~99 | 应用主窗口及其子窗口(如弹窗)。 |
| 子窗口 | PopupWindow、Spinner | 1000~1999 | 必须依附于父窗口(如 Activity),层级由父窗口决定。 |
| 系统窗口 | 状态栏、导航栏、Toast、输入法 | 2000~2999 | 全局可见,独立于应用窗口,由系统进程管理。 |
| 系统警报窗口 | 来电提醒、系统级弹窗 | 3000~3999 | 最高优先级,覆盖所有其他窗口。 |
- Z-Order 规则:值越大,层级越高,窗口越靠前显示(覆盖低层级窗口)。
(2) 层级管理关键点
- 窗口的添加顺序:同类型窗口按添加顺序叠加,后添加的层级更高。
- 动态调整:可通过
WindowManager.LayoutParams.z属性手动调整层级(需权限)。
2. 多应用窗口的管理
(1) 多任务与窗口堆栈
- Activity 堆栈(TaskStack):每个应用的 Activity 按任务(Task)组织,WMS 维护全局的窗口堆栈。
- 窗口归属:每个窗口关联到对应的应用进程,WMS 通过 Binder IPC 管理跨进程通信。
- 焦点窗口:WMS 根据窗口层级和用户交互(如点击)确定焦点窗口,输入事件(触摸、按键)只会分发到焦点窗口。
(2) 多窗口模式
| 模式 | 说明 |
|---|---|
| 分屏模式 | 两个应用窗口并列显示,WMS 计算各自尺寸并限制触摸事件到活动窗口。 |
| 画中画(PiP) | 视频小窗口浮动在其他窗口之上,WMS 管理其位置和焦点。 |
| 自由窗体模式 | 允许窗口自由调整大小(如平板模式),WMS 动态计算布局。 |
3. 应用内多页面与弹窗管理
(1) Activity 与 Window 的关系
- 单 Activity 多窗口:一个 Activity 可关联多个窗口(如主窗口 + 多个 Dialog)。
- 窗口切换:Activity 切换时,旧窗口销毁,新窗口添加到窗口堆栈。
(2) 弹窗的管理
- Dialog:作为子窗口依附于 Activity 窗口,层级高于 Activity 内容但低于系统窗口。
- PopupWindow:必须指定锚点 View,层级由父窗口决定。
- Toast:属于系统窗口,层级较低(通常不会遮挡输入法)。
弹窗显示流程
- 创建窗口:通过
WindowManager.addView()添加弹窗视图。 - 层级计算:WMS 根据弹窗类型和父窗口确定其 Z-Order。
- 输入事件处理:弹窗获得焦点时,WMS 将触摸事件路由到弹窗。
(3) 页面切换与窗口生命周期
- Activity 切换:旧 Activity 的窗口被标记为
DESTROYED,新窗口添加到堆栈顶部。 - 过渡动画:WMS 协调新旧窗口的动画(如滑动、淡入淡出),确保平滑切换。
4. WindowManagerService 的核心机制
(1) 窗口的添加与移除
- 添加窗口:
- 应用调用
WindowManager.addView()。 - WMS 通过 Binder IPC 接收请求,分配窗口标识符(
WindowId)和Surface。
- 应用调用
- 移除窗口:
- 应用调用
WindowManager.removeView()。 - WMS 销毁窗口并释放资源(如 Surface)。
- 应用调用
(2) 布局计算(Layout)
- 窗口尺寸:根据
LayoutParams(如MATCH_PARENT、WRAP_CONTENT)和父窗口约束计算。 - 位置调整:
- 重力(Gravity):控制窗口在屏幕中的对齐方式。
- 偏移量(x/y):手动指定窗口位置(如
Toast的底部显示)。
(3) 输入事件路由
- 触摸事件分发:
- WMS 根据窗口层级和位置,确定哪个窗口应接收事件。
- 通过
InputDispatcher将事件发送到目标窗口的应用进程。
- 焦点管理:
- 窗口获得焦点时,WMS 通知应用进程(触发
onWindowFocusChanged())。
- 窗口获得焦点时,WMS 通知应用进程(触发
(4) 合成与显示
- Surface 提交:每个窗口的渲染结果写入
Surface的 Back Buffer。 - SurfaceFlinger 合成:按窗口层级(Z-Order)混合所有
Surface,输出到屏幕。
5. 典型场景分析
(1) 弹窗覆盖输入法
- 问题:输入法窗口(系统窗口,层级 2000+)应覆盖应用窗口,但弹窗可能遮挡输入法。
- 解决:输入法窗口的层级高于普通应用弹窗,WMS 确保输入法始终位于最前。
(2) 多应用分屏
- 流程:
- 用户进入分屏模式,WMS 为两个应用分配独立区域。
- 每个应用的窗口尺寸被限制为分屏区域大小。
- 输入事件根据触摸位置路由到对应应用。
(3) 系统警报窗口(如来电提醒)
- 优先级:系统警报窗口(层级 3000+)覆盖所有其他窗口。
- 焦点抢夺:即使其他窗口正在交互,警报窗口也会立即获得焦点。
6. 关键优化与调试
(1) 性能优化
- 减少窗口层级:避免不必要的窗口叠加(如多个透明 Dialog)。
- 硬件加速:启用 GPU 渲染,减少主线程负担。
- 避免泄漏:及时移除不再使用的窗口(如
PopupWindow.dismiss())。
(2) 调试工具
- dumpsys window:查看所有窗口的层级、尺寸和状态。
adb shell dumpsys window - Layout Inspector:分析应用内窗口的视图层级。
- Systrace:监控窗口布局和绘制的耗时。
总结
WindowManagerService 作为 Android 窗口管理的核心,通过以下机制协调多应用、多窗口的复杂性:
- 层级控制(Z-Order):按窗口类型和优先级决定显示顺序。
- 布局计算:动态调整窗口尺寸和位置。
- 输入路由:确保焦点窗口正确接收用户交互。
- 生命周期管理:处理窗口的创建、销毁和切换。
理解这些机制,开发者可以更好地处理弹窗、多任务等场景,同时规避性能问题和显示异常。
在 Android 系统中,窗口管理涉及 多进程协作,核心对象(如 View 树、窗口树、Layer 树)分布在不同的进程中,通过跨进程通信(IPC)和共享内存机制交互。以下是各对象的创建者、所属进程和跨进程操作方式的详细解析:
1. 对象归属与创建者
(1) View 树
- 创建者:应用进程(主线程)。
- 所属进程:应用进程(如
com.example.app)。 - 组成:
- 根视图:
DecorView(由PhoneWindow创建)。 - 子 View:通过
LayoutInflater解析 XML 或代码动态添加的View和ViewGroup。
- 根视图:
(2) 窗口树(WindowState 树)
- 创建者:
WindowManagerService(WMS)。 - 所属进程:
system_server进程(系统服务进程)。 - 组成:
- 窗口节点:
WindowState(每个窗口对应一个WindowState,存储窗口的尺寸、层级、Surface等信息)。 - 管理逻辑:WMS 维护全局窗口树,按 Z-Order 排序。
- 窗口节点:
(3) Layer 树
- 创建者:
SurfaceFlinger。 - 所属进程:
surfaceflinger进程(负责合成的系统服务进程)。 - 组成:
- 图层节点:
Layer(每个窗口对应一个Layer,存储图层的GraphicBuffer、变换矩阵等)。 - 合成逻辑:
SurfaceFlinger按 Z-Order 合成所有Layer。
- 图层节点:
2. 跨进程操作方式
(1) 应用进程 ↔ WindowManagerService
-
通信方式:Binder IPC。
-
关键操作:
- 添加/移除窗口:
- 应用调用
WindowManager.addView(),通过 Binder 调用WMS.addWindow()。 - WMS 创建
WindowState并分配Surface。
- 应用调用
- 更新窗口属性:
- 应用调用
WindowManager.updateViewLayout(),通知 WMS 调整窗口尺寸、层级等。
- 应用调用
- 输入事件路由:
- WMS 通过
InputDispatcher将触摸事件发送到应用进程的ViewRootImpl。
- WMS 通过
- 添加/移除窗口:
-
数据传递:
- 窗口参数:
WindowManager.LayoutParams通过 Binder 传递。 - Surface 控制:WMS 通过
SurfaceControl(Binder 对象)授予应用进程访问Surface的权限。
- 窗口参数:
(2) 应用进程 ↔ SurfaceFlinger
- 通信方式:共享内存 + Binder IPC。
- 关键操作:
- 提交渲染数据:
- 应用通过
eglSwapBuffers()将渲染结果写入Surface的GraphicBuffer(共享内存)。 - 通过
IGraphicBufferProducer.queueBuffer()(Binder 调用)通知SurfaceFlinger有新帧。
- 应用通过
- 缓冲区管理:
BufferQueue(应用与SurfaceFlinger共享的双缓冲队列)通过Gralloc驱动分配共享内存。
- 提交渲染数据:
(3) WMS ↔ SurfaceFlinger
- 通信方式:Binder IPC。
- 关键操作:
- 窗口层级同步:
- WMS 通知
SurfaceFlinger窗口的 Z-Order 和可见性。
- WMS 通知
- 合成策略调整:
- 根据窗口属性(如透明、动画)选择 GPU 合成或硬件合成器(HWComposer)。
- 窗口层级同步:
3. 关键对象生命周期
(1) View 树生命周期
- 创建:由应用进程的
Activity或Fragment触发,通过setContentView()解析 XML。 - 销毁:
Activity.onDestroy()时,ViewRootImpl调用WindowManager.removeView()移除窗口,触发 WMS 销毁WindowState。
(2) WindowState 生命周期
- 创建:
WMS.addWindow()时生成。 - 销毁:应用调用
removeView()或窗口关闭时,WMS 移除WindowState并释放Surface。
(3) Layer 生命周期
- 创建:首次提交
GraphicBuffer时,SurfaceFlinger为窗口创建Layer。 - 销毁:窗口移除或
Surface释放时,SurfaceFlinger销毁Layer。
4. 跨进程数据流示例(以弹窗显示为例)
- 应用进程:
- 创建
PopupWindow,调用WindowManager.addView()。
- 创建
- WMS:
- 在
system_server进程创建WindowState,分配Surface。
- 在
- 应用进程:
- 通过
Surface的Canvas或硬件加速渲染弹窗内容。
- 通过
- SurfaceFlinger:
- 接收
GraphicBuffer,创建Layer并按 WMS 指定的 Z-Order 合成。
- 接收
- 显示硬件:
- 在下一个 VSync 周期显示合成后的帧。
5. 技术总结
- 进程边界:
- 应用进程:管理 View 树和本地窗口渲染。
- system_server:WMS 管理全局窗口树。
- surfaceflinger:SurfaceFlinger 管理 Layer 树和合成。
- 跨进程机制:
- Binder IPC:用于控制信令(如窗口添加、属性更新)。
- 共享内存:通过
GraphicBuffer传递像素数据(避免拷贝开销)。
- 性能关键点:
- 减少不必要的窗口层级和透明区域(降低合成负载)。
- 避免频繁的跨进程调用(如多次
addView/removeView)。
通过这种多进程协作机制,Android 实现了复杂的窗口管理功能,同时保证了性能和安全性。开发者应理解这些底层交互,以优化 UI 渲染和避免跨进程瓶颈。
在 Android 系统中,视图渲染数据、窗口管理信息和最终渲染数据的转化与协作,是一个跨进程、分层级的高效流程。以下是它们的关联与转化过程:
1. 视图渲染数据(应用进程内生成)
(1) 数据内容
- View 树的绘制指令:通过
View.draw()生成的图形操作(如绘制矩形、文本、图片)。 - 硬件加速优化:
- DisplayList:记录绘制命令的指令集(如
Canvas.drawRect()转换为 GPU 指令)。 - RenderNode:硬件加速的绘制单元,支持属性动画和变换。
- DisplayList:记录绘制命令的指令集(如
(2) 生成流程
- Measure/Layout:确定每个 View 的尺寸和位置。
- Draw:
- 软件绘制:直接在
Canvas上操作Bitmap(CPU 生成像素数据)。 - 硬件加速:将
Canvas操作转换为DisplayList,由RenderThread提交到 GPU 渲染。
- 软件绘制:直接在
(3) 数据形式
- 软件绘制:
Bitmap像素数据。 - 硬件加速:
DisplayList或RenderNode(GPU 指令的抽象)。
2. 窗口管理信息(系统进程管理)
(1) 数据内容
- 窗口属性:尺寸、位置、层级(Z-Order)、可见性、焦点状态。
- 窗口树结构:由
WindowManagerService(WMS)维护的全局窗口列表(WindowState列表)。
(2) 管理流程
- 窗口创建:应用调用
WindowManager.addView(),WMS 分配Surface并创建WindowState。 - 层级排序:根据窗口类型(应用窗口、系统窗口)和添加顺序计算 Z-Order。
- 输入事件路由:根据窗口层级和触摸位置确定目标窗口。
(3) 数据形式
- WindowState:系统进程(
system_server)中的对象,存储窗口属性。 - SurfaceControl:控制
Surface的创建和配置(如缓冲区大小、格式)。
3. 最终渲染数据(系统进程合成与硬件输出)
(1) 数据内容
- 合成后的帧数据:所有窗口的渲染结果按 Z-Order 混合后的最终像素数据。
- 硬件缓冲区:
GraphicBuffer(通过共享内存传递的像素缓冲区)。
(2) 合成流程
- 提交渲染数据:应用将渲染结果写入
Surface的 Back Buffer(通过eglSwapBuffers())。 - 图层收集:
SurfaceFlinger从所有窗口的BufferQueue获取最新GraphicBuffer。 - 合成与输出:按 Z-Order 混合图层,写入显示硬件的 Front Buffer,由 VSync 信号触发屏幕刷新。
(3) 数据形式
- GraphicBuffer:共享内存中的像素缓冲区(避免跨进程拷贝)。
- 合成策略:使用 GPU 或硬件合成器(HWComposer)执行混合操作。
4. 三者如何发生关系?
(1) 视图渲染数据 → 窗口管理信息的绑定
- Surface 的关联:
- 每个窗口对应一个
Surface,应用进程将视图渲染数据写入其 Back Buffer。 - WMS 管理窗口的
Surface属性(如尺寸、位置),决定它最终在屏幕上的显示区域。
- 每个窗口对应一个
- 层级控制:
- WMS 维护窗口的 Z-Order,告诉
SurfaceFlinger哪个窗口的图层应该覆盖在上层。
- WMS 维护窗口的 Z-Order,告诉
(2) 窗口管理信息 → 最终渲染数据的转化
- 图层合成规则:
SurfaceFlinger根据 WMS 提供的窗口 Z-Order 和位置信息,决定图层的叠加顺序。- 透明区域和动画效果(如 Alpha 值)由 GPU 或 HWComposer 计算混合结果。
- 跨进程数据传递:
- 应用进程通过
GraphicBuffer(共享内存)将渲染数据传递给SurfaceFlinger。 - WMS 通过 Binder IPC 将窗口属性同步给
SurfaceFlinger。
- 应用进程通过
(3) 最终渲染数据 → 屏幕显示
- 硬件协作:
- 显示控制器(Display Controller)从 Front Buffer 读取像素数据。
- 通过屏幕的像素阵列和时序控制器(Timing Controller)输出光信号。
5. 全流程示例(以点击按钮触发 UI 更新为例)
-
应用进程:
- 用户点击按钮,修改
TextView的文本,调用invalidate()。 ViewRootImpl触发performTraversals(),执行 Measure → Layout → Draw。- 生成新的
DisplayList(硬件加速)或Bitmap(软件绘制)。
- 用户点击按钮,修改
-
窗口管理(WMS):
- WMS 维护窗口的尺寸和 Z-Order,确保该窗口位于其他窗口之上。
- 如果窗口位置或层级变化,WMS 通过 Binder 通知
SurfaceFlinger。
-
渲染数据提交:
- 渲染线程将
DisplayList转换为 GPU 指令,写入Surface的 Back Buffer。 - 通过
IGraphicBufferProducer.queueBuffer()提交到SurfaceFlinger。
- 渲染线程将
-
合成与显示:
SurfaceFlinger按 WMS 提供的 Z-Order 合成所有窗口的图层。- 合成后的帧通过 VSync 信号显示到屏幕。
6. 关键优化点
(1) 减少渲染数据量
- 避免过度绘制:使用
canvas.clipRect()限制绘制区域。 - 硬件加速优化:复用
DisplayList,减少 GPU 指令生成开销。
(2) 降低窗口管理开销
- 减少窗口层级:避免不必要的弹窗或透明窗口。
- 批量更新属性:合并多次
View属性修改,减少 IPC 调用。
(3) 合成效率提升
- 使用不透明图层:避免 Alpha 混合计算。
- 硬件合成器(HWComposer):利用专用硬件加速图层混合。
总结
- 视图渲染数据是应用进程内生成的绘制指令或像素数据。
- 窗口管理信息由 WMS 维护,决定窗口的显示属性和层级。
- 最终渲染数据是
SurfaceFlinger按窗口管理规则合成的结果。
三者通过 跨进程通信(Binder) 和 共享内存(GraphicBuffer) 协作,最终由显示硬件输出到屏幕。理解这一流程,有助于开发者优化 UI 性能,避免卡顿和过度绘制。
在 Android 系统中,ActivityManagerService(AMS) 是负责管理应用组件(如 Activity、Service)生命周期、任务栈、进程调度和跨应用协作的核心系统服务。尽管 AMS 不直接参与窗口渲染或图层合成,但它通过与 WindowManagerService(WMS)、SurfaceFlinger 及其他组件的协作,间接影响窗口的显示流程。以下是 AMS 在这些过程中的核心作用及协作机制:
1. 管理 Activity 生命周期,触发窗口的创建与销毁
(1) Activity 启动与窗口创建
- 流程:
- 应用调用
startActivity(),AMS 根据 Intent 解析目标 Activity。 - AMS 创建新 Activity 实例,并通知应用进程执行
onCreate()→onStart()→onResume()。 - 在
onResume()阶段,应用通过WindowManager.addView()请求 WMS 添加窗口(如DecorView)。
- 应用调用
- AMS 的角色:
- 管理 Activity 状态机,确保生命周期回调的正确执行。
- 若目标 Activity 属于其他应用,AMS 会启动新进程并初始化组件。
(2) Activity 销毁与窗口移除
- 流程:
- 用户按返回键或调用
finish(),AMS 触发onPause()→onStop()→onDestroy()。 - 在
onDestroy()阶段,应用调用WindowManager.removeView()移除窗口。
- 用户按返回键或调用
- AMS 的角色:
- 回收 Activity 资源,并通知 WMS 销毁关联的
WindowState。
- 回收 Activity 资源,并通知 WMS 销毁关联的
2. 维护任务栈(TaskStack),影响窗口的层级(Z-Order)
(1) 任务栈与窗口层级
- 任务栈(Task):AMS 将同一应用的多个 Activity 组织成任务栈(后进先出)。
- Z-Order 规则:WMS 根据 AMS 维护的任务栈顺序,决定窗口的显示层级。
- 前台任务:窗口层级最高,覆盖其他任务。
- 后台任务:窗口被暂停或隐藏(如
onStop()),层级降低。
(2) 多任务场景(分屏、画中画)
- AMS 的协调:
- 分屏模式下,AMS 将两个任务标记为前台,WMS 为每个任务分配独立区域。
- 画中画(PiP)模式下,AMS 通知 WMS 将视频窗口固定为系统窗口(高 Z-Order)。
3. 进程管理,保障窗口渲染的资源分配
(1) 进程生命周期与窗口渲染
- 前台进程:拥有可见 Activity 的进程,AMS 优先分配 CPU/内存资源,确保窗口渲染流畅。
- 后台进程:若进程被 AMS 标记为低优先级(如进入后台),可能被限制资源或终止,导致窗口无法更新。
(2) 进程死亡与恢复
- 场景:应用进程因内存不足被 AMS 终止。
- 恢复流程:
- AMS 保存 Activity 状态(如
Bundle)。 - 用户返回应用时,AMS 重新启动进程并恢复 Activity。
- 应用重新创建窗口,触发完整绘制流程。
- AMS 保存 Activity 状态(如
4. 协调转场动画与窗口切换
(1) Activity 切换动画
- AMS 的协作:
- AMS 定义 Activity 转场动画类型(如
slide_in_right)。 - WMS 根据动画类型,调整新旧窗口的变换矩阵(如平移、透明度),SurfaceFlinger 合成最终效果。
- AMS 定义 Activity 转场动画类型(如
(2) 窗口焦点切换
- 焦点传递:
- AMS 通知 WMS 新 Activity 的窗口获得焦点。
- WMS 通过
InputDispatcher将输入事件路由到新窗口。
5. 处理系统级弹窗与交互
(1) 权限请求对话框
- 流程:
- 应用请求敏感权限,AMS 拦截并弹出系统级对话框。
- 对话框作为高 Z-Order 系统窗口,由 WMS 管理。
- AMS 的角色:
- 校验权限状态,控制对话框的显示逻辑。
(2) ANR 弹窗(Application Not Responding)
- 流程:
- AMS 检测到应用主线程阻塞(5 秒无响应)。
- AMS 创建 ANR 对话框(系统窗口),覆盖当前应用窗口。
- 用户可选择关闭应用或等待。
6. 跨进程通信与安全管控
(1) Binder IPC 的中介
- 场景:应用 A 启动应用 B 的 Activity。
- 应用 A 通过 Binder 调用 AMS 的
startActivity()。 - AMS 校验权限,启动应用 B 的进程。
- AMS 通知 WMS 为应用 B 分配窗口。
- 应用 A 通过 Binder 调用 AMS 的
(2) 窗口权限校验
- 系统窗口权限:
- 只有系统应用才能创建某些高 Z-Order 窗口(如状态栏)。
- AMS 校验调用方权限,WMS 拒绝非法请求。
总结:AMS 与 WMS/SurfaceFlinger 的协作全貌
- AMS 驱动生命周期:决定何时创建/销毁 Activity,间接控制窗口的添加/移除。
- WMS 管理窗口属性:根据 AMS 维护的任务栈和焦点状态,设置窗口的 Z-Order、尺寸和位置。
- SurfaceFlinger 合成图层:按 WMS 提供的层级信息,混合所有窗口的渲染结果。
- AMS 保障进程存活:确保前台应用有足够资源维持窗口渲染。
性能优化视角
- 减少 Activity 启动耗时:优化
onCreate()和布局加载,避免 AMS 触发 ANR。 - 避免内存泄漏:及时销毁不再使用的 Activity,防止 AMS 误判进程优先级。
- 合理使用进程:多模块应用可拆分进程,AMS 会独立管理其窗口和资源。
在 Android 中,Activity、Window、DecorView、ViewRootImpl 和 View 之间的关系可以通过以下层次结构和协作流程来理解:
1. 组件定义与职责
| 组件 | 职责 |
|---|---|
| Activity | 管理用户界面和生命周期,作为应用与用户交互的入口。 |
| Window | 抽象窗口概念,管理窗口的属性和内容(如背景、标题栏)。 |
| DecorView | 窗口的根视图,包含系统装饰(状态栏、导航栏)和用户内容区域。 |
| ViewRootImpl | 连接窗口与系统服务(如 WindowManagerService),管理视图的绘制和事件。 |
| View | UI 的基本单元,所有控件(如 TextView、Button)的基类。 |
2. 关系与协作流程
(1) Activity 创建 Window
- 触发时机:在
Activity.attach()方法中,创建PhoneWindow(Window 的具体实现)。 - 代码逻辑:
// Activity.java public void attach(...) { mWindow = new PhoneWindow(this); mWindow.setWindowManager(...); }
(2) Window 初始化 DecorView
- 触发时机:当 Activity 第一次调用
setContentView()时,PhoneWindow创建DecorView。 - 代码逻辑:
// PhoneWindow.java public void setContentView(int layoutResID) { if (mContentParent == null) { installDecor(); // 创建 DecorView } mLayoutInflater.inflate(layoutResID, mContentParent); } - DecorView 结构:
- 标题栏(可选):由
android.R.id.title标识。 - 内容区域:由
android.R.id.content标识,用户布局添加至此。
- 标题栏(可选):由
(3) ViewRootImpl 的创建与关联
- 触发时机:在
ActivityThread.handleResumeActivity()中,当 Activity 变为可见时。 - 代码逻辑:
// ActivityThread.java public void handleResumeActivity(...) { ViewManager wm = activity.getWindowManager(); wm.addView(decorView, params); // 触发 ViewRootImpl 创建 } - ViewRootImpl 的作用:
- 将
DecorView添加到WindowManager。 - 管理视图的测量(Measure)、布局(Layout)、绘制(Draw)。
- 处理输入事件(触摸、按键)的分发。
- 将
(4) View 树的构建与绘制
- 构建流程:通过
setContentView()将用户布局添加到DecorView的内容区域,形成View树。 - 绘制流程:
- 触发:
ViewRootImpl.performTraversals()。 - 步骤:
- Measure:计算每个
View的尺寸。 - Layout:确定每个
View的位置。 - Draw:将
View内容绘制到Surface。
- Measure:计算每个
- 触发:
3. 层次结构图示
+---------------------+
| Activity | ← 管理生命周期和窗口
+---------------------+
|
| 持有
↓
+---------------------+
| Window | ← 管理窗口属性和内容(PhoneWindow 实现)
+---------------------+
|
| 创建
↓
+---------------------+
| DecorView | ← 根视图,包含系统装饰和用户内容
|---------------------|
| - TitleBar (可选) |
| - Content (ID: content) | ← 用户布局添加至此(通过 setContentView())
+---------------------+
|
| 添加为窗口的根视图
↓
+---------------------+
| ViewRootImpl | ← 管理绘制、事件分发和系统服务通信
+---------------------+
|
| 管理
↓
+---------------------+
| View | ← UI 控件(TextView、Button 等)
+---------------------+
4. 关键交互场景
(1) 用户点击按钮
- 输入事件传递:
ViewRootImpl通过InputEventReceiver接收触摸事件。- 事件从
DecorView开始,递归分发给子View。
- UI 更新:
- 修改
TextView文本后,调用invalidate()触发重绘。 ViewRootImpl调度performTraversals(),执行绘制流程。
- 修改
(2) Activity 切换
- 旧 Activity 销毁:
onPause()→onStop()→onDestroy()。WindowManager移除DecorView,ViewRootImpl被销毁。
- 新 Activity 显示:
- 新
DecorView通过ViewRootImpl添加到WindowManager。 SurfaceFlinger合成新窗口的图层。
- 新
5. 总结
- Activity 是用户交互的容器,通过
Window管理窗口。 - Window 的具体实现是
PhoneWindow,负责初始化DecorView和用户内容。 - DecorView 是窗口的根视图,包含系统装饰和用户布局。
- ViewRootImpl 是连接应用与系统服务的桥梁,管理视图的绘制和事件。
- View 是 UI 的构建单元,构成视图树并由
ViewRootImpl驱动渲染。
这种分层架构使得 Android 能够高效管理复杂的 UI 和窗口交互,同时保证灵活性和性能。
在 Android 系统中,Activity、Window、DecorView、ViewRootImpl、View 均属于 应用进程,而系统服务(如 WindowManagerService、SurfaceFlinger)运行在独立的 系统进程 中。以下是它们的进程归属和跨进程协作机制:
1. 进程归属
| 组件/服务 | 所属进程 | 说明 |
|---|---|---|
| Activity | 应用进程(如 com.example.app) | 用户交互的入口,管理 UI 生命周期。 |
| Window | 应用进程 | 抽象窗口,由 PhoneWindow 实现,管理 DecorView 和窗口属性。 |
| DecorView | 应用进程 | 窗口的根视图,包含系统装饰(状态栏)和用户布局(android.R.id.content)。 |
| ViewRootImpl | 应用进程 | 连接应用窗口与系统服务,管理视图的测量、布局、绘制和输入事件。 |
| View | 应用进程 | UI 控件(如 TextView、Button)。 |
| WMS | system_server 系统进程 | 管理窗口的创建、层级(Z-Order)、焦点和尺寸。 |
| SurfaceFlinger | surfaceflinger 系统进程 | 合成所有窗口的图层(Layer),输出到屏幕。 |
| AMS | system_server 系统进程 | 管理 Activity 生命周期、任务栈和进程调度。 |
| IMS | system_server 系统进程 | 分发输入事件(触摸、按键)到目标窗口。 |
2. 进程间关联与协作
(1) 应用进程 ↔ 系统进程(WMS/AMS/IMS)
- 通信机制:Binder IPC。
- 典型场景:
- 窗口创建:
- 应用进程调用
WindowManager.addView(),通过 Binder 调用WMS.addWindow()。 - WMS 在系统进程中创建
WindowState,分配Surface,并通过IWindowSession返回结果。
- 应用进程调用
- 输入事件传递:
- IMS 在系统进程接收触摸事件,通过
InputDispatcher发送到应用进程的ViewRootImpl。 ViewRootImpl将事件分发给DecorView及其子View。
- IMS 在系统进程接收触摸事件,通过
- Activity 生命周期:
- AMS 通过 Binder 通知应用进程执行
onCreate()、onResume()等生命周期方法。
- AMS 通过 Binder 通知应用进程执行
- 窗口创建:
(2) 应用进程 ↔ SurfaceFlinger
- 通信机制:共享内存(GraphicBuffer) + Binder IPC。
- 典型场景:
- 渲染数据提交:
- 应用进程通过 GPU 渲染 UI 到
Surface的 Back Buffer(共享内存)。 - 通过 Binder 调用
IGraphicBufferProducer.queueBuffer()通知SurfaceFlinger有新帧。
- 应用进程通过 GPU 渲染 UI 到
- 图层合成:
SurfaceFlinger从BufferQueue读取GraphicBuffer,按窗口层级合成最终帧。- 合成结果通过显示控制器(Display Controller)输出到屏幕。
- 渲染数据提交:
3. 跨进程协作流程示例
场景:用户启动 Activity
- AMS 启动进程:
- AMS 在系统进程中检查目标 Activity 的进程是否存在,若不存在则启动新进程。
- Activity 初始化:
- 应用进程创建
Activity实例,调用onCreate()→setContentView()→ 构建DecorView。
- 应用进程创建
- 窗口注册到 WMS:
ViewRootImpl通过WindowManager.addView()将DecorView添加到 WMS。- WMS 分配
Surface并维护窗口的WindowState。
- 渲染与合成:
- 应用进程渲染 UI 到
Surface,提交到SurfaceFlinger。 SurfaceFlinger合成所有窗口的图层,输出到屏幕。
- 应用进程渲染 UI 到
- 输入事件处理:
- IMS 将触摸事件发送到应用进程的
ViewRootImpl,由DecorView分发到子View。
- IMS 将触摸事件发送到应用进程的
4. 关键对象与数据流
| 对象/数据 | 所属进程 | 跨进程传递方式 | 说明 |
|---|---|---|---|
| WindowState | system_server | Binder IPC(WindowManagerService) | WMS 内部管理的窗口状态,记录层级、尺寸等。 |
| Surface | 应用进程 | 共享内存(GraphicBuffer) | 窗口的绘图缓冲区,通过 BufferQueue 共享。 |
| InputChannel | 应用进程 | Binder IPC(InputDispatcher) | 输入事件通道,由 IMS 创建并与应用进程绑定。 |
| Layer | surfaceflinger | 共享内存(GraphicBuffer) | SurfaceFlinger 管理的图层数据。 |
5. 性能与安全机制
- 共享内存优化:
GraphicBuffer通过Gralloc驱动分配,应用进程和SurfaceFlinger直接访问,避免数据拷贝。
- Binder 线程池:
- 应用进程和系统服务通过 Binder 线程池处理并发请求,避免阻塞主线程。
- 权限控制:
- WMS 校验窗口类型权限(如系统窗口需
SYSTEM_ALERT_WINDOW权限)。 - AMS 校验跨应用启动 Activity 的权限。
- WMS 校验窗口类型权限(如系统窗口需
总结
- 应用进程:负责 UI 构建(Activity、View 树)、事件处理和本地渲染。
- 系统进程:管理全局状态(窗口层级、输入事件、图层合成)。
- 跨进程协作:通过 Binder IPC 传递控制信令,通过 共享内存 传递渲染数据,实现高效交互。
- 核心流程:AMS 驱动生命周期 → WMS 管理窗口 → IMS 路由输入 → SurfaceFlinger 合成输出。
这一协作机制确保了 Android 在多进程环境下仍能提供流畅的 UI 体验和高效的资源管理。
在 Android 中,当应用进程通过 ViewRootImpl 和 WindowManager.addView() 将 DecorView 添加到 WindowManagerService (WMS) 时,DecorView 本身不会直接跨进程传递。相反,系统通过以下方式完成跨进程通信和数据传递:
1. 跨进程传递的核心对象
DecorView 的信息是通过 窗口属性(WindowManager.LayoutParams) 和 Binder 代理对象(IWindow) 跨进程传递的,而非传递 DecorView 的实例。具体流程如下:
(1) 应用进程侧
- 创建
ViewRootImpl:WindowManagerGlobal.addView()创建ViewRootImpl,并关联DecorView。
- 封装窗口属性:
- 将窗口参数(尺寸、层级、类型等)封装到
WindowManager.LayoutParams。
- 将窗口参数(尺寸、层级、类型等)封装到
- 创建 Binder 代理对象:
ViewRootImpl创建一个IWindow.Stub的代理对象(W),用于与 WMS 通信。- 该代理对象实现了
IWindow接口,允许 WMS 反向调用应用进程(如通知窗口焦点变化)。
(2) 跨进程调用
- IPC 方法:通过
IWindowSession.addToDisplay()向 WMS 发起跨进程调用。 - 传递内容:
IWindow代理对象(W):标识窗口的唯一性,用于 WMS 回调应用进程。WindowManager.LayoutParams:窗口的元数据(如type、flags、width、height等)。- 父窗口句柄(可选):若为子窗口(如弹窗),需指定父窗口的
IWindow对象。
(3) WMS 系统进程侧
- 创建
WindowState:- WMS 根据传递的
IWindow和WindowManager.LayoutParams创建WindowState对象。 WindowState是 WMS 内部管理窗口的核心对象,存储窗口属性、层级(Z-Order)、Surface等信息。
- WMS 根据传递的
- 分配
Surface:- WMS 通过
SurfaceControl为窗口分配Surface(绘图缓冲区),并通过 Binder 将Surface的控制权返回给应用进程。
- WMS 通过
2. 关键对象的作用
| 对象 | 所属进程 | 作用 |
|---|---|---|
DecorView | 应用进程 | 窗口的根视图,管理用户界面布局。 |
ViewRootImpl | 应用进程 | 连接 DecorView 和 WMS,驱动测量、布局、绘制,并处理输入事件。 |
IWindow.Stub | 应用进程 | Binder 服务端,接收 WMS 的回调(如焦点变化、窗口尺寸调整)。 |
IWindow 代理 | 跨进程(Binder) | WMS 通过该代理调用应用进程的方法(如 resized()、dispatchAppVisibility())。 |
WindowState | 系统进程 | WMS 内部管理窗口状态的对象,存储窗口属性、Surface、层级等信息。 |
3. 数据传递示意图
应用进程(com.example.app) 系统进程(system_server)
+-----------------------------+ +-----------------------------+
| | | |
| 1. ViewRootImpl | | |
| - 关联 DecorView | | |
| - 创建 IWindow.Stub (W) | | |
| | | |
| 2. WindowManagerGlobal | | |
| - 调用 addView() | | |
| - 封装 LayoutParams | | |
| | | |
| 3. Binder IPC | | |
| - 调用 IWindowSession | | |
| .addToDisplay(W, params)| | |
| | | |
| | | 4. WMS |
| | | - 创建 WindowState |
| | | - 分配 Surface |
| | | - 管理窗口层级 |
+-----------------------------+ +-----------------------------+
4. 为什么不能直接传递 DecorView?
- 进程隔离:
- Android 的进程隔离机制禁止直接传递对象(如
View)到其他进程。 DecorView是应用进程内的复杂对象,包含大量与 UI 相关的状态和方法,无法直接序列化。
- Android 的进程隔离机制禁止直接传递对象(如
- 性能与安全:
- 直接传递视图层级会导致大量数据拷贝,影响性能。
- 通过代理对象(
IWindow)和元数据(LayoutParams)传递,保证安全性和效率。
5. 窗口内容(如 DecorView 的绘制)如何传递?
Surface共享机制:- WMS 为窗口分配
Surface(通过SurfaceControl),应用进程通过 OpenGL 或 Canvas 将内容渲染到Surface的缓冲区。 Surface的缓冲区通过 共享内存(GraphicBuffer) 实现跨进程访问。
- WMS 为窗口分配
- 合成与显示:
SurfaceFlinger从共享内存中读取所有窗口的渲染数据,按层级合成后输出到屏幕。
总结
- 传递的内容:
- 窗口元数据:
WindowManager.LayoutParams(封装窗口属性)。 - Binder 代理对象:
IWindow(用于双向通信)。
- 窗口元数据:
- WMS 侧的对象:
WindowState(管理窗口状态)和Surface(绘图缓冲区)。 DecorView仍留在应用进程:它负责管理 UI 布局和绘制,最终内容通过共享的Surface传递到系统进程。
这种设计既保证了进程隔离的安全性,又通过共享内存和 Binder 代理实现了高效的窗口管理。
在 Android 系统中,Surface 是窗口内容绘制的核心对象,而 WindowState 是系统进程(system_server)中管理窗口状态的核心对象。当应用进程通过 WindowManager.addView() 添加窗口时,WindowManagerService (WMS) 在系统进程中创建 WindowState 并分配 Surface,随后将 Surface 的控制权通过跨进程机制传递给应用进程。以下是这一过程的详细机制:
1. Surface 的创建与跨进程传递
(1) 系统进程中的操作
- 创建
WindowState:- 当应用调用
WindowManager.addView()时,WMS 在系统进程中创建WindowState,记录窗口的尺寸、层级(Z-Order)、输入通道等属性。
- 当应用调用
- 分配
Surface:- WMS 通过
SurfaceControl(底层图形服务接口)为窗口分配Surface。 Surface的底层是 图形缓冲区(GraphicBuffer),通过Gralloc驱动在共享内存(ashmem)中分配,允许多进程访问。
- WMS 通过
- 封装
Surface:Surface对象本身无法直接跨进程传递,但 WMS 会返回其控制权的 代理对象(如IGraphicBufferProducer)。- 代理对象通过 Binder IPC 传递,应用进程通过它操作
Surface。
(2) 跨进程传递机制
- Binder IPC:
- WMS 将
Surface的控制权封装为IWindowSession.addToDisplay()的返回值。 - 应用进程通过
SurfaceControl或IGraphicBufferProducer代理对象操作远程的Surface。
- WMS 将
- 共享内存:
GraphicBuffer通过Gralloc分配在共享内存中,应用进程和SurfaceFlinger均可访问,避免数据拷贝。
2. Surface 在应用进程中的形态
(1) 应用进程的 Surface 对象
- 代理对象:
- 应用进程持有的
Surface对象实际上是一个 Binder 代理对象(如IGraphicBufferProducer),指向系统进程中的真实Surface。 - 该代理对象通过
Parcel序列化跨进程传递。
- 应用进程持有的
- 图形缓冲区的操作:
- 应用进程通过代理对象获取
GraphicBuffer,将 UI 内容渲染到共享内存的缓冲区。 - 示例:
Canvas canvas = surface.lockCanvas();通过代理对象锁定缓冲区并获取Canvas。
- 应用进程通过代理对象获取
(2) 关键类与接口
| 类/接口 | 所属进程 | 作用 |
|---|---|---|
Surface | 应用进程 | 代理对象,封装对远程 GraphicBuffer 的操作(如锁定、提交缓冲区)。 |
IGraphicBufferProducer | 系统进程 | Binder 接口,定义缓冲区生产者的操作(如 dequeueBuffer、queueBuffer)。 |
GraphicBuffer | 共享内存 | 实际存储像素数据的缓冲区,跨进程共享。 |
3. WindowState 与 Surface 的对应关系
(1) 系统进程中的 WindowState
- 职责:
- 存储窗口的元数据:尺寸、层级、焦点状态、输入通道等。
- 管理
Surface的生命周期(创建、销毁、尺寸调整)。
- 与
Surface的关联:WindowState持有SurfaceControl,控制Surface的底层属性(如缓冲区大小、格式)。
(2) 应用进程中的 Surface 操作
- 绘制流程:
- 应用进程通过
Surface.lockCanvas()获取Canvas,执行 UI 绘制。 - 绘制完成后,调用
Surface.unlockCanvasAndPost(),通过代理对象通知SurfaceFlinger提交缓冲区。
- 应用进程通过
- 跨进程协作:
SurfaceFlinger监听BufferQueue,当应用提交新帧时,按窗口层级(Z-Order)合成所有Surface。
4. 数据流示意图
应用进程 系统进程(WMS) SurfaceFlinger
+-----------------------------+ +-----------------------------+ +-----------------------------+
| | | | | |
| 1. ViewRootImpl | | | | |
| - 调用 addView() | | | | |
| | | | | |
| 2. 接收 Binder 返回的 | | 3. WMS 创建 WindowState | | |
| IGraphicBufferProducer | ←---- | 和 SurfaceControl | | |
| | | | | |
| 4. 通过代理对象操作 Surface | | | | |
| - lockCanvas() | | | | |
| - 绘制到 GraphicBuffer | | | | |
| - unlockAndPost() | ----- | ---------------------------- | -----> | 5. SurfaceFlinger 合成图层 |
| | | | | |
+-----------------------------+ +-----------------------------+ +-----------------------------+
5. 关键总结
Surface的跨进程本质:- 应用进程持有的
Surface是远程对象的代理,实际图形数据存储在共享内存的GraphicBuffer中。 - 通过 Binder 代理(如
IGraphicBufferProducer)实现跨进程控制。
- 应用进程持有的
WindowState的作用:- 系统进程中的
WindowState管理窗口状态,与Surface的生命周期绑定。
- 系统进程中的
- 性能与安全:
- 共享内存机制避免了像素数据的跨进程拷贝,提升渲染性能。
- Binder 代理和权限控制(如
SYSTEM_ALERT_WINDOW)保障窗口操作的安全性。
通过这种机制,Android 实现了高效的多窗口管理和跨进程渲染协作,同时确保系统稳定性和安全性。
在 Android 系统中,Activity、Window、窗口管理器(WMS) 以及 Activity 栈(Task) 之间通过多层协作实现应用界面的显示与管理。以下是它们的关键关联和工作流程:
1. Activity 与 Window 的关联
(1) 创建 Window 对象
-
Activity 初始化时创建 Window:
- 每个 Activity 在
onCreate()前会调用attach()方法,初始化一个PhoneWindow对象(Window 接口的实现类)。 PhoneWindow是 Activity 的顶层窗口容器,管理DecorView(窗口的根视图)。
// Activity.java final void attach(...) { mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowManager(...); } - 每个 Activity 在
(2) 设置视图内容
-
setContentView():- Activity 调用
setContentView()将布局文件解析为View树,并附加到DecorView的contentParent区域。
// Activity.java public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } - Activity 调用
(3) 窗口的显示
-
在
onResume()时关联到 WindowManager:- 当 Activity 进入前台(
onResume()),系统通过WindowManager将DecorView添加到窗口层级中。 ViewRootImpl作为窗口与WMS的桥梁,处理底层通信(如布局、绘制、输入事件)。
// ActivityThread.java → handleResumeActivity() ViewManager wm = activity.getWindowManager(); wm.addView(decorView, layoutParams); // 最终调用到 WindowManagerGlobal.addView() - 当 Activity 进入前台(
2. Activity 栈与窗口的关系
(1) Activity 栈(Task)
- 由 ActivityManagerService (AMS) 管理:
- Task 是 AMS 维护的 Activity 回退栈,决定 Activity 的启动顺序和返回逻辑。
- 栈顶 Activity 的窗口位于屏幕最上层,其他 Activity 的窗口可能被隐藏或销毁。
(2) 窗口层级(Z-Order)
- 由 WindowManagerService (WMS) 管理:
- WMS 维护所有窗口的
WindowState,根据 窗口类型(应用窗口、子窗口、系统窗口) 和 层级值(Z-Order) 排序。 - Activity 的窗口属于 应用窗口,其 Z-Order 由 AMS 的 Task 栈顺序决定。
- WMS 维护所有窗口的
(3) 协作流程
- 切换 Activity:
- AMS 将新 Activity 压入 Task 栈顶,通知 WMS 调整窗口层级。
- WMS 将新 Activity 的窗口设为前台窗口,旧 Activity 的窗口可能进入后台或被销毁。
ViewRootImpl通过relayoutWindow()更新窗口属性(如尺寸、可见性)。
3. 关键组件关系图
应用进程 system_server(系统进程)
+-----------------------------+ +-----------------------------+ +-----------------------------+
| Activity | | ActivityManagerService (AMS) | | WindowManagerService (WMS) |
| - PhoneWindow | | - 管理 Activity 栈 (Task) | | - 管理 WindowState 和 Z-Order |
| - DecorView (根视图) | | - 处理 Activity 生命周期 | | - 处理窗口布局、合成、输入事件 |
| - ViewRootImpl | ↔ Binder ↔ | | ↔ Binder ↔ | |
+-----------------------------+ +-----------------------------+ +-----------------------------+
流程说明:
- Activity 启动:
- AMS 创建 Activity 实例,压入 Task 栈顶。
- Activity 初始化
PhoneWindow和DecorView,通过ViewRootImpl向 WMS 注册窗口。
- 窗口显示:
- WMS 根据 AMS 的 Task 栈顺序调整窗口 Z-Order。
ViewRootImpl处理布局(measure/layout)和绘制(draw),通过Surface提交帧到SurfaceFlinger。
- Activity 切换:
- AMS 将旧 Activity 移至后台,新 Activity 压入栈顶。
- WMS 更新窗口层级,旧窗口可能被隐藏(
onStop())或销毁(onDestroy())。
4. 窗口管理器(WMS)的核心职责
- 窗口生命周期管理:
- 处理
addWindow()、removeWindow()、relayoutWindow()请求。 - 维护
WindowState,记录窗口属性(尺寸、可见性、输入通道等)。
- 处理
- 层级与合成:
- 根据窗口类型(应用窗口、子窗口、系统弹窗)分配 Z-Order。
- 将窗口的
Surface按 Z-Order 排序,通知SurfaceFlinger合成最终图像。
- 输入事件分发:
- 通过
InputManagerService将触摸事件路由到前台窗口。
- 通过
5. Activity 栈与窗口的映射示例
假设应用有两个 Activity:MainActivity 和 DetailActivity,启动顺序为 MainActivity → DetailActivity。
| Activity 栈(AMS) | 窗口状态(WMS) | 用户可见界面 |
|---|---|---|
| Task: [Main, Detail] | DetailActivity 的窗口 Z-Order 更高 | 显示 DetailActivity |
| 用户按下返回键 → MainActivity 回到栈顶 | WMS 将 MainActivity 的窗口提升到前台 | 显示 MainActivity |
6. 总结
- Activity 是窗口的宿主:
- 每个 Activity 拥有一个
PhoneWindow,通过DecorView管理视图内容。 ViewRootImpl连接应用进程与 WMS,处理窗口的底层操作。
- 每个 Activity 拥有一个
- AMS 与 WMS 分工协作:
- AMS 管理 Activity 栈,决定哪些 Activity 应该显示或隐藏。
- WMS 管理窗口层级,确保前台 Activity 的窗口位于最上层。
- 跨进程通信:
- AMS 和 WMS 通过 Binder IPC 与应用进程通信,协调 Activity 生命周期和窗口状态。
理解这些关联机制,有助于优化应用界面性能(如减少过度绘制)、处理窗口层级问题(如系统弹窗覆盖)以及调试窗口相关的异常(如黑屏、卡顿)。
在 Android 系统中,Activity、Window、窗口管理器(WMS) 以及 Activity 栈(Task) 之间通过多层协作实现应用界面的显示与管理。以下是它们的关键关联和工作流程:
1. Activity 与 Window 的关联
(1) 创建 Window 对象
-
Activity 初始化时创建 Window:
- 每个 Activity 在
onCreate()前会调用attach()方法,初始化一个PhoneWindow对象(Window 接口的实现类)。 PhoneWindow是 Activity 的顶层窗口容器,管理DecorView(窗口的根视图)。
// Activity.java final void attach(...) { mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowManager(...); } - 每个 Activity 在
(2) 设置视图内容
-
setContentView():- Activity 调用
setContentView()将布局文件解析为View树,并附加到DecorView的contentParent区域。
// Activity.java public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } - Activity 调用
(3) 窗口的显示
-
在
onResume()时关联到 WindowManager:- 当 Activity 进入前台(
onResume()),系统通过WindowManager将DecorView添加到窗口层级中。 ViewRootImpl作为窗口与WMS的桥梁,处理底层通信(如布局、绘制、输入事件)。
// ActivityThread.java → handleResumeActivity() ViewManager wm = activity.getWindowManager(); wm.addView(decorView, layoutParams); // 最终调用到 WindowManagerGlobal.addView() - 当 Activity 进入前台(
2. Activity 栈与窗口的关系
(1) Activity 栈(Task)
- 由 ActivityManagerService (AMS) 管理:
- Task 是 AMS 维护的 Activity 回退栈,决定 Activity 的启动顺序和返回逻辑。
- 栈顶 Activity 的窗口位于屏幕最上层,其他 Activity 的窗口可能被隐藏或销毁。
(2) 窗口层级(Z-Order)
- 由 WindowManagerService (WMS) 管理:
- WMS 维护所有窗口的
WindowState,根据 窗口类型(应用窗口、子窗口、系统窗口) 和 层级值(Z-Order) 排序。 - Activity 的窗口属于 应用窗口,其 Z-Order 由 AMS 的 Task 栈顺序决定。
- WMS 维护所有窗口的
(3) 协作流程
- 切换 Activity:
- AMS 将新 Activity 压入 Task 栈顶,通知 WMS 调整窗口层级。
- WMS 将新 Activity 的窗口设为前台窗口,旧 Activity 的窗口可能进入后台或被销毁。
ViewRootImpl通过relayoutWindow()更新窗口属性(如尺寸、可见性)。
3. 关键组件关系图
应用进程 system_server(系统进程)
+-----------------------------+ +-----------------------------+ +-----------------------------+
| Activity | | ActivityManagerService (AMS) | | WindowManagerService (WMS) |
| - PhoneWindow | | - 管理 Activity 栈 (Task) | | - 管理 WindowState 和 Z-Order |
| - DecorView (根视图) | | - 处理 Activity 生命周期 | | - 处理窗口布局、合成、输入事件 |
| - ViewRootImpl | ↔ Binder ↔ | | ↔ Binder ↔ | |
+-----------------------------+ +-----------------------------+ +-----------------------------+
流程说明:
- Activity 启动:
- AMS 创建 Activity 实例,压入 Task 栈顶。
- Activity 初始化
PhoneWindow和DecorView,通过ViewRootImpl向 WMS 注册窗口。
- 窗口显示:
- WMS 根据 AMS 的 Task 栈顺序调整窗口 Z-Order。
ViewRootImpl处理布局(measure/layout)和绘制(draw),通过Surface提交帧到SurfaceFlinger。
- Activity 切换:
- AMS 将旧 Activity 移至后台,新 Activity 压入栈顶。
- WMS 更新窗口层级,旧窗口可能被隐藏(
onStop())或销毁(onDestroy())。
4. 窗口管理器(WMS)的核心职责
- 窗口生命周期管理:
- 处理
addWindow()、removeWindow()、relayoutWindow()请求。 - 维护
WindowState,记录窗口属性(尺寸、可见性、输入通道等)。
- 处理
- 层级与合成:
- 根据窗口类型(应用窗口、子窗口、系统弹窗)分配 Z-Order。
- 将窗口的
Surface按 Z-Order 排序,通知SurfaceFlinger合成最终图像。
- 输入事件分发:
- 通过
InputManagerService将触摸事件路由到前台窗口。
- 通过
5. Activity 栈与窗口的映射示例
假设应用有两个 Activity:MainActivity 和 DetailActivity,启动顺序为 MainActivity → DetailActivity。
| Activity 栈(AMS) | 窗口状态(WMS) | 用户可见界面 |
|---|---|---|
| Task: [Main, Detail] | DetailActivity 的窗口 Z-Order 更高 | 显示 DetailActivity |
| 用户按下返回键 → MainActivity 回到栈顶 | WMS 将 MainActivity 的窗口提升到前台 | 显示 MainActivity |
6. 总结
- Activity 是窗口的宿主:
- 每个 Activity 拥有一个
PhoneWindow,通过DecorView管理视图内容。 ViewRootImpl连接应用进程与 WMS,处理窗口的底层操作。
- 每个 Activity 拥有一个
- AMS 与 WMS 分工协作:
- AMS 管理 Activity 栈,决定哪些 Activity 应该显示或隐藏。
- WMS 管理窗口层级,确保前台 Activity 的窗口位于最上层。
- 跨进程通信:
- AMS 和 WMS 通过 Binder IPC 与应用进程通信,协调 Activity 生命周期和窗口状态。
理解这些关联机制,有助于优化应用界面性能(如减少过度绘制)、处理窗口层级问题(如系统弹窗覆盖)以及调试窗口相关的异常(如黑屏、卡顿)。
在 Android 系统中,窗口管理器服务(WindowManagerService, WMS) 负责管理所有窗口的层级(Z-Order)和显示状态。不同应用场景下,窗口栈(即窗口的 Z-Order 排列)会有不同的结构。以下是几种典型场景的窗口栈状态:
1. 没有应用运行时(仅系统窗口)
当设备处于空闲状态(无前台应用运行),窗口栈主要由系统窗口构成:
窗口栈(Z-Order 从高到低)
+-----------------------------+
| 1. 输入法窗口(如果需要) | → 如键盘输入弹窗(TYPE_INPUT_METHOD)
+-----------------------------+
| 2. 系统弹窗(如电源菜单、通知栏) | → TYPE_SYSTEM_DIALOG / TYPE_SYSTEM_ALERT
+-----------------------------+
| 3. 状态栏(Status Bar) | → TYPE_STATUS_BAR
+-----------------------------+
| 4. 导航栏(Navigation Bar) | → TYPE_NAVIGATION_BAR
+-----------------------------+
| 5. 壁纸(Wallpaper) | → TYPE_WALLPAPER
+-----------------------------+
- 特点:只有系统级窗口,无应用窗口。
- WMS 行为:所有窗口层级由系统服务直接管理,应用窗口处于未激活状态。
2. 单个应用运行时(前台全屏 Activity)
当用户启动一个全屏应用(如主屏幕或单 Activity 应用):
窗口栈(Z-Order 从高到低)
+-----------------------------+
| 1. 应用的主窗口(Main Activity) | → TYPE_BASE_APPLICATION(应用主窗口)
+-----------------------------+
| 2. 系统弹窗(如果需要) | → 如 Toast(TYPE_TOAST)
+-----------------------------+
| 3. 状态栏 / 导航栏 | → 覆盖在应用窗口下方
+-----------------------------+
| 4. 壁纸 | → 被应用窗口完全遮挡
+-----------------------------+
- 特点:
- 应用的
TYPE_BASE_APPLICATION窗口位于栈顶,覆盖系统窗口。 - 状态栏和导航栏可能显示为沉浸式或透明(取决于应用配置)。
- 应用的
- WMS 行为:
- 应用窗口通过
ViewRootImpl注册到 WMS,获得最高优先级(前台窗口)。 - 系统窗口(如状态栏)可能通过
FLAG_LAYOUT_IN_SCREEN与FLAG_LAYOUT_INSET_DECOR与应用窗口共存。
- 应用窗口通过
3. 多个应用运行时(一个前台,一个后台)
当用户启动两个应用(如应用 A 在前台,应用 B 在后台):
窗口栈(Z-Order 从高到低)
+-----------------------------+
| 1. 应用 A 的主窗口(前台 Activity) | → TYPE_BASE_APPLICATION
+-----------------------------+
| 2. 应用 B 的主窗口(后台 Activity) | → 可能被标记为不可见或暂停(STATE_STOPPED)
+-----------------------------+
| 3. 系统弹窗(如通知栏) | → TYPE_SYSTEM_ALERT
+-----------------------------+
| 4. 状态栏 / 导航栏 | → 覆盖在后台应用窗口上方
+-----------------------------+
- 特点:
- 前台应用(A)的窗口位于栈顶,覆盖后台应用(B)的窗口。
- 后台应用窗口可能被 WMS 标记为
不可见或暂停,但仍保留在窗口栈中(取决于系统资源策略)。
- WMS 行为:
- 当应用切换到后台时,WMS 通过
relayoutWindow()更新其窗口状态(如隐藏Surface)。 - 窗口的
Surface可能被销毁以节省资源,但WindowState对象仍保留(用于快速恢复)。
- 当应用切换到后台时,WMS 通过
4. 多个应用同时前台运行(分屏或画中画)
当两个应用同时处于前台(如分屏模式或画中画):
窗口栈(Z-Order 从高到低)
+-----------------------------+
| 1. 画中画窗口(应用 B 的视频窗口) | → TYPE_APPLICATION_OVERLAY(覆盖其他窗口)
+-----------------------------+
| 2. 分屏窗口(应用 A 的上半部分) | → TYPE_BASE_APPLICATION(分屏任务 1)
+-----------------------------+
| 3. 分屏窗口(应用 C 的下半部分) | → TYPE_BASE_APPLICATION(分屏任务 2)
+-----------------------------+
| 4. 系统弹窗(如输入法) | → TYPE_INPUT_METHOD
+-----------------------------+
| 5. 状态栏 / 导航栏 | → 位于分屏窗口下方
+-----------------------------+
- 特点:
- 分屏模式下,每个分屏区域的窗口属于不同的
Task,但都被视为前台窗口。 - 画中画窗口(如视频播放器)作为
TYPE_APPLICATION_OVERLAY类型,覆盖其他应用窗口。
- 分屏模式下,每个分屏区域的窗口属于不同的
- WMS 行为:
- 分屏窗口的 Z-Order 由分屏位置决定(例如,上半部分窗口优先于下半部分)。
- 画中画窗口通过
WindowManager.LayoutParams.flags标记为可交互(FLAG_NOT_TOUCH_MODAL),允许穿透点击事件。
5. 多个应用弹窗覆盖(如系统级弹窗 + 应用弹窗)
当多个弹窗同时显示(如系统权限弹窗 + 应用对话框):
窗口栈(Z-Order 从高到低)
+-----------------------------+
| 1. 系统权限弹窗(如相机权限请求) | → TYPE_SYSTEM_ALERT(最高优先级)
+-----------------------------+
| 2. 应用 A 的对话框 | → TYPE_APPLICATION(普通应用弹窗)
+-----------------------------+
| 3. 应用 B 的主窗口(后台) | → TYPE_BASE_APPLICATION(暂停状态)
+-----------------------------+
| 4. 状态栏 / 导航栏 | → 覆盖在后台应用窗口上方
+-----------------------------+
- 特点:
- 系统弹窗(
TYPE_SYSTEM_ALERT)优先级高于普通应用弹窗(TYPE_APPLICATION)。 - 系统弹窗会阻塞应用输入事件,直到用户响应。
- 系统弹窗(
- WMS 行为:
- 系统弹窗通过
WindowManager.LayoutParams.type标记为高优先级,强制置顶。 - 应用弹窗的 Z-Order 由
type和flags共同决定(例如FLAG_LAYOUT_IN_SCREEN)。
- 系统弹窗通过
关键规则总结
- 窗口类型决定基础层级:
- 系统窗口(如
TYPE_SYSTEM_ALERT) > 应用窗口(如TYPE_BASE_APPLICATION) > 子窗口(如TYPE_APPLICATION_PANEL)。
- 系统窗口(如
- 同一类型窗口按时间顺序排列:
- 后添加的窗口默认位于同一层级的上方(可通过
flags调整优先级,如FLAG_LAYER_TYPE)。
- 后添加的窗口默认位于同一层级的上方(可通过
- 分屏和画中画的特殊处理:
- 分屏窗口共享前台状态,但 Z-Order 由分屏位置决定。
- 画中画窗口作为
TYPE_APPLICATION_OVERLAY类型,可覆盖其他应用窗口。
- 系统弹窗的强制置顶:
- 系统级弹窗(如权限请求)始终位于栈顶,阻塞用户操作。
调试工具
adb shell dumpsys window:查看当前窗口栈状态、WindowState和 Z-Order。adb shell dumpsys activity:查看 Activity 栈(Task)与窗口的映射关系。
通过理解这些场景,可以更好地优化应用窗口层级(如避免过度使用 SYSTEM_ALERT)、处理多窗口交互(如分屏适配),以及调试窗口覆盖问题(如弹窗被遮挡)。
在 Android 系统中,当多个应用运行且每个应用包含多个 Activity,同时考虑 Launcher 应用时,WindowManagerService(WMS) 通过以下机制管理窗口层级和窗口与进程的对应关系:
1. 窗口层级(Z-Order)管理
WMS 根据 窗口类型、任务栈(Task)状态 和 用户交互优先级 动态调整窗口的显示顺序。
(1) 窗口类型与默认优先级
窗口的层级由 WindowManager.LayoutParams.type 决定,优先级从高到低如下:
- 系统窗口:状态栏(
TYPE_STATUS_BAR)、导航栏(TYPE_NAVIGATION_BAR)、系统弹窗(TYPE_SYSTEM_ALERT)。 - 应用窗口:
- 前台应用的主窗口(
TYPE_BASE_APPLICATION)。 - 子窗口(如对话框
TYPE_APPLICATION)。
- 前台应用的主窗口(
- Launcher 窗口:属于普通应用窗口,但当用户返回桌面时,其窗口优先级提升。
(2) 任务栈与窗口层级
- Activity 任务栈(Task):
- 由 ActivityManagerService(AMS) 维护,栈顶 Activity 的窗口会被 WMS 置顶。
- 例如:用户从 Launcher 启动应用 A → 应用 A 启动应用 B → 应用 B 的窗口位于最上层。
- 多 Activity 应用内部:
- 应用内不同 Activity 的窗口按任务栈顺序排列。例如,应用 A 的主 Activity 启动设置 Activity,设置窗口覆盖主窗口。
(3) Launcher 的特殊处理
- Home 键触发:当用户按下 Home 键,AMS 将 Launcher 的 Activity 移至前台,WMS 将其窗口提升到层级顶部。
- 后台保留:Launcher 的窗口可能被保留(不销毁)以加速下次启动,但层级被其他应用窗口覆盖。
2. 窗口与进程的对应关系
WMS 通过 进程标识(PID) 和 窗口令牌(WindowToken) 跟踪窗口与进程的关系。
(1) 窗口的归属
- 每个窗口绑定到进程:通过
ViewRootImpl注册到 WMS 时,携带进程的Binder标识。// ViewRootImpl 向 WMS 添加窗口时,传递进程信息 mWindowSession.addToDisplay(mWindow, mWindowAttributes, ...); - 窗口令牌(WindowToken):标识窗口所属的 Activity 或应用。例如:
- Activity 窗口的 Token 由 AMS 分配。
- 系统窗口的 Token 由 WMS 直接管理。
(2) 进程生命周期的影响
- 进程终止:当应用进程崩溃或被杀死,WMS 移除该进程所有关联的窗口。
- 后台进程窗口:后台应用的窗口可能被标记为不可见或销毁
Surface,但WindowState仍保留(用于快速恢复)。
3. 多应用运行时的典型场景
(1) 场景 1:Launcher 启动应用 A,应用 A 启动应用 B
- 窗口层级:
1. 应用 B 的主窗口(栈顶 Activity) 2. 应用 A 的主窗口(后台暂停) 3. Launcher 窗口(完全隐藏) 4. 系统状态栏/导航栏(始终覆盖应用窗口) - 进程关系:
- 应用 B 的进程在前台,应用 A 和 Launcher 的进程可能在后台存活。
(2) 场景 2:用户从应用 B 返回 Launcher
- 窗口层级:
1. Launcher 窗口(恢复为前台) 2. 应用 B 的主窗口(隐藏或销毁) 3. 应用 A 的主窗口(保持后台) - 进程关系:
- Launcher 的进程恢复前台状态,应用 B 可能进入后台或终止(取决于内存策略)。
(3) 场景 3:分屏模式(Split-Screen)
- 窗口层级:
1. 分屏上部分窗口(应用 C 的 Activity) 2. 分屏下部分窗口(应用 D 的 Activity) 3. 系统状态栏/导航栏 - 进程关系:
- 应用 C 和 D 的进程同时处于前台,WMS 为每个分屏窗口分配独立
WindowState。
- 应用 C 和 D 的进程同时处于前台,WMS 为每个分屏窗口分配独立
4. WMS 的关键管理机制
(1) 窗口添加与移除
addWindow():根据窗口类型、令牌和进程信息创建WindowState。removeWindow():当 Activity 销毁或进程终止时,清理关联窗口。
(2) 层级计算(WindowStack)
- 动态调整 Z-Order:根据窗口类型、任务栈顺序和用户操作(如点击事件)实时排序。
- 输入事件分发:仅前台窗口可接收触摸事件(通过
InputManagerService路由)。
(3) 与 AMS 的协作
- Activity 可见性通知:AMS 通知 WMS 哪些 Activity 应显示/隐藏。
- 任务栈同步:WMS 根据 AMS 提供的任务栈信息调整窗口层级。
5. 调试与验证
- 查看当前窗口层级:
输出示例:adb shell dumpsys windowWindow #0: Window{xxxx u0 com.android.launcher3/...} Window #1: Window{yyyy u0 com.example.appA/...} Window #2: Window{zzzz u0 StatusBar} - 查看进程与窗口关系:
adb shell dumpsys activity processes
6. 总结
- 窗口层级由 WMS 动态管理:基于窗口类型、任务栈状态和用户交互。
- 窗口与进程通过 Token 绑定:WMS 跟踪窗口的归属进程,确保进程终止时清理窗口。
- Launcher 作为普通应用:其窗口优先级在用户返回桌面时提升,但遵循通用层级规则。
- 多任务场景:分屏、画中画等模式需要特殊处理,但核心机制仍由 WMS 统一管理。
通过这一机制,Android 确保了多应用、多 Activity 环境下窗口的正确显示和交互逻辑。
在 Android 系统中,Activity 栈(Task) 和 窗口层级(Window Stack) 是两个不同但密切相关的概念。Activity 栈由 ActivityManagerService (AMS) 管理,而窗口层级由 WindowManagerService (WMS) 控制。以下是它们的关系及具体运行机制:
1. Activity 栈与窗口的映射关系
(1) Activity 栈的结构
- Task(任务栈):AMS 维护的 Activity 回退栈,每个 Task 中的 Activity 按启动顺序排列。
- 栈顶 Activity:用户当前正在交互的 Activity。
- 栈内其他 Activity:可能处于
PAUSED或STOPPED状态,窗口可能被隐藏或销毁。
(2) 每个 Activity 对应一个窗口
- 窗口创建:每个 Activity 在
onCreate()阶段创建PhoneWindow,通过setContentView()加载视图。 - 窗口注册:当 Activity 进入前台(
onResume()),其窗口通过WindowManager注册到 WMS,成为可见窗口。
2. Activity 栈内的窗口管理
(1) 单应用场景(同一 Task 内多个 Activity)
假设应用内部启动流程:Activity A → Activity B → Activity C。
- AMS 的 Activity 栈:
Task Stack: [A, B, C](C 为栈顶) - WMS 的窗口层级:
Window Stack(Z-Order 从高到低): 1. Activity C 的窗口(TYPE_BASE_APPLICATION,前台) 2. Activity B 的窗口(可能被标记为隐藏或已销毁) 3. Activity A 的窗口(可能被标记为隐藏或已销毁) 4. 系统窗口(状态栏、导航栏等)- 关键行为:
- 只有 栈顶 Activity(C) 的窗口处于活跃状态(
VISIBLE)。 - 非栈顶 Activity(B, A)的窗口可能被:
- 保留但隐藏:窗口的
Surface被隐藏(setVisibility(GONE)),但WindowState仍存在。 - 完全销毁:窗口从 WMS 移除(通常在内存紧张时发生)。
- 保留但隐藏:窗口的
- 只有 栈顶 Activity(C) 的窗口处于活跃状态(
- 关键行为:
(2) 窗口的保留与销毁
- 保留场景:
- 配置变更(如屏幕旋转):Activity 重建时,旧窗口可能暂存以便平滑过渡。
- 快速返回:系统可能保留后台窗口的
Surface,以优化用户体验。
- 销毁场景:
- 当 Activity 调用
finish()或系统回收资源时,窗口从 WMS 移除。 - 示例代码:Activity 销毁时调用
WindowManager.removeView(decorView)。
- 当 Activity 调用
3. 多应用场景(涉及 Launcher 和其他应用)
(1) 用户从 Launcher 启动应用
- 初始状态:
- AMS 栈:Launcher 的 Activity 位于栈顶。
- WMS 窗口层级:Launcher 的窗口在前台,覆盖其他系统窗口。
- 启动应用后:
- AMS 栈:新应用的 Activity 压入栈顶,Launcher 进入后台。
- WMS 窗口层级:新应用的窗口覆盖 Launcher 窗口,但 Launcher 窗口可能被保留(隐藏)。
(2) 用户返回桌面(按 Home 键)
- AMS 行为:Launcher 的 Activity 重新压入栈顶,原应用进入后台。
- WMS 行为:
- Launcher 的窗口被提升到前台(
Z-Order最高)。 - 原应用的窗口被隐藏,但可能保留
WindowState(取决于系统策略)。
- Launcher 的窗口被提升到前台(
4. WMS 如何管理 Activity 栈内的窗口
(1) 关键机制
- 窗口令牌(WindowToken):
- 每个 Activity 的窗口通过
IApplicationToken(由 AMS 分配)绑定到 WMS。 - Token 用于标识窗口所属的 Activity 及其 Task。
- 每个 Activity 的窗口通过
- 窗口状态同步:
- AMS 通知 WMS Activity 的生命周期变化(如
onResume()、onPause())。 - WMS 根据这些事件调整窗口的可见性和层级。
- AMS 通知 WMS Activity 的生命周期变化(如
- 输入事件路由:
- 仅栈顶 Activity 的窗口可以接收输入事件(触摸、按键)。
(2) 代码流程示例
- Activity 切换时的窗口更新:
// AMS 通知 WMS 更新窗口 // ActivityRecord.java void setVisible(boolean visible) { mWindowContainer.setVisible(visible); // 通过 WMS 更新窗口状态 } - 窗口的隐藏与显示:
// WMS 处理窗口可见性 // WindowManagerService.java void setWindowVisibility(IBinder token, boolean visible) { WindowState window = findWindowByToken(token); if (window != null) { window.setVisibility(visible ? VISIBLE : GONE); } }
5. 特殊场景分析
(1) 透明 Activity(如 Dialog Theme)
- AMS 栈:透明 Activity(如 B)压入栈顶,原 Activity(A)仍可见。
- WMS 窗口层级:
1. Activity B 的窗口(TYPE_APPLICATION,半透明) 2. Activity A 的窗口(TYPE_BASE_APPLICATION,可见但不可交互) 3. 系统窗口- 用户可与 B 交互,但 A 的窗口仍然渲染(如背景模糊效果)。
(2) 多窗口模式(分屏、自由窗口)
- AMS 栈:每个分屏窗口对应独立 Task。
- WMS 窗口层级:
1. 分屏窗口 1(Task A 的 Activity) 2. 分屏窗口 2(Task B 的 Activity) 3. 系统窗口- 每个分屏窗口的
Z-Order根据其位置动态调整。
- 每个分屏窗口的
6. 总结
- Activity 栈与窗口层级解耦:
- AMS 管理 Activity 的生命周期和任务逻辑。
- WMS 管理窗口的渲染、层级和输入事件。
- 窗口与 Activity 的绑定:
- 每个 Activity 对应一个窗口,但只有栈顶 Activity 的窗口处于活跃状态。
- 非栈顶 Activity 的窗口可能被隐藏或销毁,具体行为由系统和资源策略决定。
- 协作机制:
- AMS 和 WMS 通过 Binder IPC 同步 Activity 和窗口状态。
- 用户看到的最终界面由 WMS 根据 AMS 的任务栈和窗口类型计算出的 Z-Order 决定。
通过这一机制,Android 实现了多 Activity、多应用场景下窗口的高效管理和用户体验的一致性。