【源码解析】FloatWindow弹窗梳理

553 阅读4分钟

基于Android 13 梳理floatwindow弹窗相关信息。

一、应用窗口管理

1.1 应用View与系统WindowState映射关系:

1.2 核心类UML

1)核心类介绍:

  • Window: 抽象类,定义窗口概念。
  • PhoneWindow: Window的唯一实现类,Window是view的管理者同时也是view的载体。主要作用:提供DecorView模板、抽离Activity中窗口视图相关逻辑。
  • WindowManager: 接口,它实现ViewManager,整体定义Window组织管理。
  • WindowManagerImpl: WindowManager实现类,功能实现交给单例WindowManagerGlobal处理。
  • WindowManagerGlobal: App全局单例,负责缓存各窗口对应的view、viewRootImpl、params,初始化ISession。
  • ViewRootImpl: window和view连接桥梁,负责与WMS通信添加window,负责管理和绘制view树。
  • IWindowSession:App与WMS bind ipc的会话接口。
  • IWindow: WMS与App bind ipc的会话接口
  • WindowManagerService: 窗口管理的系统服务。
  • Display: 表示设备屏幕的抽象,它包含有关显示屏的信息。
  • DisplayContent: 用来管理一个逻辑屏上的所有窗口,有几个屏幕就会有几个 DisplayContent,使用 displayId 来区分。
  • WindowContainer: 窗口容器基类。
  • WindowToken: 应用组织标识:将属于同一应用的窗口组织在一起,令牌作用,身份标识。同时是WindowState容器。
  • WindowState: WMS中对窗口的封装类,它与window一一对应。
  • WindowManager.LayoutParams: 窗口布局参数。

二、窗口布局参数说明

2.1 type: 表示窗口类型

window类型特点层级范围(Z-order)典型window代表
system window独立存在2000(FIRST_APPLICATION_WINDOW)~2999(LAST_APPLICATION_WINDOW)Toast 、警告提示window、键盘window等
sub window需要依附于父window,不能独立存在1000(FIRST_SUB_WINDOW)~1999(LAST_SUB_WINDOW)popupWindow
application window属于应用的窗口1(FIRST_APPLICATION_WINDOW)~99(LAST_APPLICATION_WINDOW)对应的就是activity、dialog的window,它俩都是新建PhoneWindow

注:Z-Order越大,window越靠近用户,也就显示越高,高度高的window会覆盖高度低的window。

典型类型:

类型说明
TYPE_APPLICATION_OVERLAY用于在应用程序的顶部显示的悬浮窗口
TYPE_TOAST用于显示 Toast 的窗口类型
TYPE_SYSTEM_ALERT用于显示系统警告窗口
......

注:Android 8.0开始 ,SYSTEM_ALERT_WINDOW 从普通权限提升为敏感权限

2.2 flag: 控制窗口的显示

类型说明
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON当 Window 可见时允许锁屏
FLAG_KEEP_SCREEN_ON只要 Window 可见时屏幕就会一直亮着
FLAG_LAYOUT_IN_SCREEN允许 Window 占满整个屏幕
......

2.3 token:窗口标识

ActivityRecord初始化时会new一个token与之对应,activity.attach传入该token,setWindowManager的时候传入该token,最终由Window的AppToken接收,在WindowManagerGlobal的addView方法中,执行adjustLayoutParamsForSubWindow,将WindowManager.LayoutParams wp,wp.token赋值appToken,并在之后的流程中,WindowManager.LayoutParams wp作为参数传入WMS的addWindow方法对应attrs.token。因此:Activity的token,Window中的token,连传入addWindow的attrs.token,都是同一个token,都是ActivityRecord构造函数中创建的Token对象,token标识主要是保证一致性。

1)token和windowState映射关系

Activity-Window-WindowState 靠WindowToken保持一致性。

2)获取活跃task核心时序

3)token数据结构流转关系

mRootWindowCotainer是WMS中窗口管理的根容器,根据源码分析:在AMS服务初始化时,进行的与WMS关联:

由上可得出围绕token相关的类关系UML:

总结token的数据结构组织关系:

二、FloatWindow弹窗流程分析

2.1 弹窗主线时序

2.2 添加窗口核心逻辑分析

WMS#addWindow详细流程:

这里核心关注添加窗口逻辑的限制条件:

核心逻辑围绕:typetoken

1)对type的权限校验:

SYSTEM_APPLICATION_OVERLAY、INTERNAL_SYSTEM_WINDOW、SYSTEM_ALERT_WINDOW

2)对token的归属校验:

attrs.token = null为系统窗口 ,在DisplayContainer复用同一个key=null的WindowToken。token不为null的只能是application/sub window,受权限限制,后台应用无法前台弹出application/sub window。

按framework正常实现逻辑看,添加窗口限制总结:

窗口类型能弹出的条件
system window系统应用:具有系统权限:INTERNAL_SYSTEM_WINDOW、SYSTEM_APPLICATION_OVERLAY
三方应用:用户授权 SYSTEM_ALERT_WINDOW
application/sub window依赖于活跃的activity,窗口归于activity 对应的WindowToken组同一管理,展示范围限制在activity内

windowToken校验,目前system window分组受type限制无法弹出,仅有应用级窗口能弹。