基于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详细流程:
这里核心关注添加窗口逻辑的限制条件:
核心逻辑围绕:type
、token
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限制无法弹出,仅有应用级窗口能弹。