Android 窗口添加/删除流程 笔记

理解这两个流程,是掌握WMS工作原理的基础。为了方便理解,我们可以把它们想象成一个"入住"和"退房"的过程:应用进程是"房客",WMS是"酒店前台",SurfaceFlinger是"客房部"。

🏨 窗口添加流程:"办理入住"

一个窗口从创建到显示在屏幕上,需要经过"房客"发起请求和"酒店前台"登记分配房间两大阶段。

1. 客户端侧(房客发起请求)

这一阶段主要发生在应用进程,目标是准备好"入住手续"并跨进程通知WMS。

  1. 发起者 :通常始于Activity.onResume()之后,或者手动调用WindowManager.addView()(如创建悬浮窗)。
  2. 创建ViewRootImplWindowManagerImpl将工作委托给单例的WindowManagerGlobal,后者创建ViewRootImpl对象。ViewRootImpl是应用进程与WMS通信的桥梁,也是View树开始绘制的起点。
  3. 建立通信会话ViewRootImpl在构造时会通过WindowManagerGlobal.getWindowSession(),经过一系列Binder调用,在WMS所在进程(system_server)中为当前应用进程获取或创建一个Session对象。这个Session代表了该应用与WMS之间用于窗口操作的会话通道。
  4. 发起添加请求ViewRootImpl.setView()方法中,会调用mWindowSession.addToDisplay(),将添加窗口的请求通过Binder发送给WMS。这里传递的关键参数包括:代表应用窗口回调的mWindow(一个IWindow.Stub Binder对象)和窗口布局参数WindowManager.LayoutParams

2. WMS侧(酒店前台登记)

WMS接收到请求后,开始进行核心的处理和登记工作,主要入口是WindowManagerService.addWindow()方法。

这个过程非常关键,我们可以通过一个时序图来直观地看到主要步骤的流转:

sequenceDiagram participant App as 应用进程 participant WMS as WindowManagerService participant SF as SurfaceFlinger App->>WMS: 1. addWindow() (通过Session) activate WMS WMS->>WMS: 2. 前置校验 (权限、Token、参数) WMS->>WMS: 3. 创建WindowState
(存入mWindowMap) WMS->>WMS: 4. 关联Token (WindowToken/AppWindowToken) WMS->>SF: 5. 创建SurfaceSession
(进程级连接) WMS-->>App: 返回添加结果 deactivate WMS Note over App,SF: 应用收到结果后,开始绘制UI App->>WMS: 6. relayoutWindow() activate WMS WMS->>SF: 7. 分配Surface (创建图层) SF-->>WMS: 返回Surface对象 WMS-->>App: 返回Surface及窗口位置信息 deactivate WMS Note over App: 应用将UI内容绘制到Surface App->>WMS: 8. finishDrawingWindow() activate WMS WMS->>WMS: 9. performLayoutAndPlaceSurfacesLocked()
(计算最终Z轴顺序、位置) WMS->>SF: 10. 提交事务(Transaction)
设置图层属性 deactivate WMS

让我们结合时序图,详细分解WMS侧的每一个核心步骤:

  • 步骤1-2:前置校验与准备addWindow()执行一系列严格的检查,包括:

    • 权限:检查调用者是否有权限添加指定类型的窗口(如系统窗口需要特殊权限)。
    • Token验证 :对于应用窗口,需要验证传入的Token是否对应一个有效的、正在启动的Activity(AppWindowToken)。对于子窗口,需要验证其父窗口是否存在。
    • 重复检查 :确保同一个窗口(通过IWindow标识)没有被重复添加。
  • 步骤3:创建"房间登记表"------WindowState :校验通过后,WMS会为这个新窗口创建一个WindowState对象。这是窗口在WMS中的灵魂 ,它记录了窗口的所有状态:大小、位置、包名、对应的SessionIWindow代理等。这个对象会被加入全局的mWindowMap中进行管理。

  • 步骤4:关联"房客组"------WindowToken :将新创建的WindowState与一个WindowToken(或其子类AppWindowToken)关联。WindowToken代表一组相关窗口(例如一个Activity和它弹出的所有对话框),这有助于WMS对它们进行统一管理。

  • 步骤5-7:申请"房间钥匙"------Surface :窗口需要一块画布才能绘制内容。WMS并不直接绘制,而是通过relayoutWindow()流程,向SurfaceFlinger申请一块Surface。这个过程会建立一个SurfaceSession连接,并由SurfaceFlinger创建对应的图层(Layer),最终将Surface的句柄返回给应用进程。

  • 步骤8-10:最终"入住" :应用进程拿到Surface后,就可以将UI绘制上去。绘制完成后,通过finishDrawingWindow()通知WMS。WMS的核心布局函数performLayoutAndPlaceSurfacesLocked()会被触发,它会综合所有窗口的状态,计算每个窗口最终的Z轴顺序(层叠关系)、位置和大小,并将这些结果通过SurfaceControl.Transaction提交给SurfaceFlinger,最终由SurfaceFlinger合成并显示到屏幕上。

🧹 窗口删除流程:"办理退房"

窗口的删除通常由两种原因触发:用户主动操作(如finish() Activity)或系统因资源紧张而回收。

1. 显式删除(用户主动退房)

  • 触发点 :调用WindowManager.removeView()ViewManager.removeView(),或Activity正常结束(finish())。
  • 流程
    • 应用层WindowManagerImpl.removeView()同样委托给WindowManagerGlobal,找到对应的ViewRootImpl,发起跨进程删除请求。
    • WMS处理 :调用WindowManagerService.removeWindow()。WMS会从mWindowMap中移除对应的WindowState,并销毁与之关联的Surface,释放图形内存。同时,与该窗口关联的InputChannel也会被断开,确保不再接收输入事件。
    • 收尾 :触发performLayoutAndPlaceSurfacesLocked(),重新计算剩余窗口的布局和焦点。

2. 隐式删除(系统强制退房)

  • 触发点 :当系统内存不足,AMS(ActivityManagerService)决定终止一个进程时,它会回调WMS的removeAppToken()方法。
  • 流程
    • WMS找到与该应用AppWindowToken关联的所有WindowState
    • 批量清理:一次性移除所有这些窗口,执行上述的资源释放和重排流程。这确保了即使应用进程被异常杀死,其窗口也不会残留在屏幕上,防止内存泄漏。

窗口的添加与删除,是WMS作为窗口管理核心的最基本操作。它通过与AMS协作管理窗口生命周期,通过与SurfaceFlinger协作管理窗口的绘制表面,通过与IMS协作管理窗口的输入事件通道,完美地诠释了它在上次讲解中提到的"四大核心职责"。

相关推荐
城东米粉儿2 小时前
Android Window 窗口动画原理
android
城东米粉儿2 小时前
Android Window Z轴顺序计算与窗口组织 笔记
android
城东米粉儿2 小时前
Android ActivityManagerService 笔记
android
shalou29012 小时前
mysql-connector-java 和 mysql-connector-j的区别
android·java·mysql
aaajj2 小时前
【Android】手机蜘蛛魔术的简易app例子
android
qw102482 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
小飞学编程...2 小时前
【Java相关八股文(一)】
android·java·开发语言
QCzblack2 小时前
第五周作业
android
c***03232 小时前
Mysql之主从复制
android·数据库·mysql