WMS 全名是 WindowManagerService,它是客户端 APP 的管理者,处于 SystemServe r 进程,WMS 主要负责管理几件事情
窗口管理
负责 Window 添加、更新、删除,核心管理成员有 DisplayContent
、WindowToken
、WindowState
窗口动画
Window 切换时,可以添加动画,让 Window 切换时更加自然,动画由 WMS 的动画子系统负责,该系统是 WindowAnimator
输入系统的中转
当使用者对视窗触控 or 输入时,都会触发 InputManagerService 会对触摸事件进行处理,将事件通过 WMS 传递到合适的窗口进行处理(这时 WMS 就是 中转站)
Surface 管理
WMS 并不具备 Window 绘制的功能,每个 Window 都有一个 Surface 来绘制,而 WMS 负责 Surface 的分配
WMS 启动 - SystemServer#
WMS 是就是 WindowManagerService,它是系统服务,说到系统服务自然就会想到 SystemServer,那就让我们来看看 WMS 是如何被 SystemServer 唤起的
SystemServer 透过 WMS#main
方法启动
把 WMS 以Context#WINDOW_SERVICE
(window)设定到 ServiceManager 中
把启动的 WMS 对象设定给 AMS 服务
在 WMS 启动后会透过 onInitReady
、displayReady
、systemReady
来完成 WMS 的后续动作(这些方法之后会介绍)
WMS - main 函数#
透过 DisplayThread 中的 Handler#runWithScissors
创建 WMS 对象(也就是创建 WMS 的线程与 SystemServer 线程不同)
Handler#runWithScissors
方法是透过锁来达成同步任务,保证该 Runnable 会先被 DisplayThread 的 Looper 先执行,执行完后才回到 SystemServer 的 Thread
HandlerThread - 创建 Looper#
DisplayThread - 创建 WMS 对象#
WMS 就是在 DisplayThread 类中被启动,DisplayThread 可以说是 WMS 的 MainThread
DisplayThread 可以创建安全 Handler,其主要功能是:处理 低延迟显示 的相关操作,并只能由 WindowManager、DisplayManager、InputManager 执行快速操作
从上面可以看到 DisplayThread 继承于 ServiceThread(而它继承于 HandlerThread),所以 它会在执行 run 方法时自动创建 Looper 对象,鉴于 HandlerThread 创建的 Handler 并不安全,所以 DisplayThread 这里自己创建 Handler(使用类锁)
传递事件给 WMS 有两种方式
直接呼叫 WMS function,即时传送
透过 DisplayThread 的 Looper 将事件丢入 WMS Thread(DisplayThread)中
UiThread 类#
UiThread 与 DisplayThread 差不多,但多添加了一个 dispose
方法,来停止 Looper,并结束该对象(置为 null),在 initPolicy()
、systemReady()
会使用到
AnimationThread 类#
AnimationThread 与 DisplayThread 差不多,但多添加了一个 dispose 方法,来停止 Looper,并结束该对象(置为 null)
SystemServer - WMS 启动后续#
WMS 创建#
前面有提到 WindowManagerService#main
方法会透过 DisplayThread(Thread)创建 WMS 的实例,在这里就会创建 H 类,而它的 Looper 就是当前 Thread 也就是 DisplayThread
WMS#onInitReady
- 初始化 WindowManagerPolicy#
WMS#onInitReady
函数:取得 UiThread (另外一个 Thread) 的 Handler,并初始化 WindowManagerPolicy 实作呼叫 PhoneWindowManager#init 函数)
WMS#displayReady
- 准备显示#
标示 WindowAnimator 初始化完成
重新配置设定,保证 DisplayWindowSettings 设定都有被正常使用
透过 ActivityTaskManager 来更新设置
WMS#systemReady
- 服务准备完成#
WMS 重点#
窗口属性 - Layer Type#
Android 支持多种窗口,并且会将窗口分为三类,定义在 WindowManager#LayoutParams中
Application Window:普通 App 应用就是使用以下窗口类型(列出几种举例),区间为 1 ~ 99 之间
Value | 名称 | 说明 |
---|---|---|
1 | FIRST_APPLICATION_WINDOW | 应用类视窗的起始值 |
1 | TYPE_BASE_APPLICATION | 其他应用都可覆盖在该 Window 之上 |
2 | TYPE_APPLICATION | 一般的应用窗口 |
3 | TYPE_APPLICATION_STARTING | 应用程序启动前的画面(用在加载某个画面之前的预前画面) |
4 | TYPE_DRAWN_APPLICATION | 在绘画完成前等待 |
99 | LAST_APPLICATION_WINDOW | 应用视窗的结束值 |
Sub Window:附加在应用之上的视窗,一般称为 子窗口,其值区间为 1000 ~ 1999 之间
Value | 名称 | 说明 |
---|---|---|
1000 | FIRST_SUB_WINDOW | SubWindow 的起始值 |
1000 | TYPE_APPLICATION_PANEL | 该 SubWindow 显示在依附的 App 之上 |
1001 | TYPE_APPLICATION_MEDIA | 显示有关 video 的 SubWindow |
1002 | TYPE_APPLICATION_SUB_PANEL | 显示在依附的 app 之上,也在其他 SubWinow 之上 |
1003 | TYPE_APPLICATION_ATTACHED_DIALOG | Dialog 类型的 Window |
1004 | TYPE_APPLICATION_MEDIA_OVERLAY | 显示在 TYPE_APPLICATION_MEDIA 还有底下的应用视窗之间 |
1005 | TYPE_APPLICATION_ABOVE_SUB_PANEL | 比 TYPE_APPLICATION_SUB_PANEL 更上层的 Window |
1999 | LAST_SUB_WINDOW | SubWindow 的结束值 |
System Window:系统使用的 Window 视窗(以下列出几种),区间为 2000 ~ 2999 之间
Value | 名称 | 说明 |
---|---|---|
2000 | FIRST_SYSTEM_WINDOW | System Window 的起始值 |
2001 | TYPE_STATUS_BAR | Status bar 的 Window |
2002 | TYPE_SEARCH_BAR | 搜寻 Bar 的 Window |
2038 | TYPE_APPLICATION_OVERLAY | 覆盖于其他 Activity 视窗 |
2999 | LAST_SYSTEM_WINDOW | System Window 的结束值 |
WindowState 初始化 - 决定 Base Layer#
从 WindState 构造函数可以知道,Base Laye r 数值可以从WindowManagerPolicy#getWindowLayerLw
方法取得
WindowManagerPolicy 透过传入的 WindowState
决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)
透过传入的WindowState
决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)
WindowManagerPolicy#getSubWindowLayerFromTypeLw
方法:决定子窗口在父窗口中的偏移量
窗口属性 - LayoutParams#
Window 的统一属性设定在 WindowManager#LayoutParams中,并且有分为 type
、Flags
两种设定
Type:上面已经说过,主要有分为 Application Window
、Sub Window
、System Window
三种
Flag:莫认为 0,以下列出几个(有满多的)
Value | Flag | 说明 |
---|---|---|
0x00000001 | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | 只要该窗口可见,就允许锁住屏幕(可配合 FLAG_KEEP_SCREEN_ON 使用) |
0x00000002 | FLAG_DIM_BEHIND | 窗口后的 Window 都变淡 |
0x00000004 | FLAG_BLUR_BEHIND | 窗口后的 Window 变模糊 |
0x00000008 | FLAG_NOT_FOCUSABLE | 该 Window 视窗不可事件,事件会直接传递给后方 Window |
0x00000010 | FLAG_NOT_TOUCHABLE | 该窗口不接受任何事件 |
0x00000080 | FLAG_KEEP_SCREEN_ON | 只要该窗口可见,就保持屏幕亮起 |
System UI 控制:System UI 的设定定义在 View 中,针对每个 View 个别设置
Value | Flag | 说明 |
---|---|---|
0 | SYSTEM_UI_FLAG_VISIBLE | 设定 System UI 可见 |
0x00000002 | SYSTEM_UI_FLAG_HIDE_NAVIGATION | 设定 Navigtion Bar 不可见 |
0x00000004 | SYSTEM_UI_FLAG_FULLSCREEN | 屏幕全屏 |
0x00000100 | SYSTEM_UI_FLAG_LAYOUT_STABLE | 尽量保持 UI 布局的稳定性 |
0x00000400 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 从屏幕(0,0)开始绘制,也就是会从 Status Bar 开始绘制 |
WindowManagerService 简单理解起来是掌管该装置所有的 Window 的上下关系(z 轴的管理)、传输绘制任务到底层
变量 | 说明 | 补充 |
---|---|---|
mPolicy : WindowManagerPolicy | 定义一个窗口策略所须遵循的 通用规范,并提供了 WindowManger 特定的 UI 行为 | WindowManager 是 interface,它的实作是 PhoneWindowManager |
mSessions : ArraySet | 它主要用于进程通信,其他的应用进程的 View 想要和 WMS 通信,都要通过 Session 与 WMS 通信 | 每个应用程序是透过 WindowManagerGlobal 取得 Session |
mWindowMap : WindowHashMap | WindowHashMap 继承 HashMap,用来保存所有 ViewImpl;Key: IBinder、Value: WindowState | Key 其实是 IWindow(ViewRootImpl 的内部类 W)、Value 是保存窗口信息 |
mFinishedStarting : ArrayList | AppWindowToken 的父类是 WindowToken 当 APP 要向 WMS 申请一个新窗口时就要给予这个 token 让 WMS 验证 | 每个 Activity 对应一个 AppWindowToken(一个 AppWindowToken 管理多个 WindowToken 视窗) |
mResizingWindows : ArrayList | 用来存储正在调整大小的视窗 | |
mAnimator : WindowAnimator | 管理 Window 动画 & 特效 | |
mH : H | H 是 Handler 类型,它是属于 DisplayThread Looper | 将消息给 WMS |
mInputManager : InputManagerService | IMS 系统服务,当使用者有输入讯息时,WMS 会给予一个适合的视窗 |