Android窗口管理(2)——消息传递

本文内容参考:Android 核心分析(13) —–Android GWES之Android窗口管理
上一篇文章主要讲述了窗口的基本结构,那么在这样的结构下,系统如何管理窗口,如何下发事件,如何获取窗口状态?这篇博客将对这部分的内容进行介绍。
Android在窗口管理上采用了最为经典的C/S模式,Client端是各个Activity中的window,而Service端就是系统持有的窗口管理器Window Manager。

总体结构

Window是*的窗口概念,而Activity中的DecorView则是窗口中的*View,创建Activity时,DecorView会attach到Activity的窗口中,同时也被加入到WindowManager中,WindowManager使用WindowState与该View相对应。
Android窗口管理(2)——消息传递
两者之间通过建立session会话进行通信,而这里的session采用的还是Android中最重要的IPC方式——AIDL。Activity在建立窗口后需要将该窗口注册到WindowManager中,这个过程涉及到在Activity本地创建一个WindowManager的代理,Activity通过这个代理和远程WindowManager进行会话,会话的通道是IWindowSession,本质上就是一个AIDL通信过程。Android窗口管理(2)——消息传递
会话是双向的,为了将消息发送给对应的Window,WindowManager通过IWindow接口将对应的消息发送给Window端对应的处理函数。

Client端——Activity

首先来看一下Client端,通过我的上一篇博客Android窗口管理(1)——窗口基本架构我们知道了Activity端的窗口结构,并且知道了Window,PhoneWindow都不是很重要的概念,实际真正干事的还是ViewRootAndroid窗口管理(2)——消息传递
Activity在创建的时候会调用onAttach()创建PhoneWindow这个类,并在handleResumeActivity时将窗口加入到WindowManager中,不过加入的实际上并不是窗口,而是DecorView。所以其实在客户端的核心概念只有ViewRootDecorView以及ViewGroup。其中后面两者主要还是View的概念,真正完成与WindowManager进行通信的还是ViewRoot这个家伙。

ViewRoot

ViewRoot的真正实现类是ViewRootImplViewRoot通过与WindowManager进行通信完成addView以及消息下发。Android窗口管理(2)——消息传递
ViewRoot通过IWindowSession将窗口加入到WindowManager中。
Android窗口管理(2)——消息传递
WindowManager通过IWindow接口下发事件到Activity
所以ViewRoot其实本质上是一个Handler,用于接收消息并处理消息。
Activity利用getSystemService来获取WindowManagerImpl实例,而这个实例实际上就是WindowManager在客户端本地的代理:

wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE);

之后再调用addView接口通过WindowManagerImpl将窗口添加到WindowManager中。在addView的过程中,WindowManagerImpl会建立起View,Layout,ViewRoot之间的对应关系,然后利用IWindowSession传递给WindowManager
Android窗口管理(2)——消息传递

Server端——WindowManager

WindowManager是服务端管理窗口的组件,它管理的是各个应用的*窗口,也即DecorView。将所有的窗口归置到一个统一的系统服务WindowManagerService管理是Android系统的设计思想,这样的机制并不难理解,系统总要有一个总管各个窗口的管家嘛,总不能任其自生自灭。WindowManagerService的主要工作包括:
Window Service大体上实现了如下的功能:,

(1)Z-ordered的维护函数
(2)输入法管理
(3)AddWindow/RemoveWindow
(4)Layerout
(5)Token管理,AppToken
(6)活动窗口管理(FocusWindow)
(7)活动应用管理(FocusAPP)
(8)转场动画
(9)系统消息收集线程
(10)系统消息分发线程

在服务端窗口对象叫作WindowState,Server端维护一个mWindow,其实就是一个按Z-order排序的窗口数组。mWindowMap用于记录<Client:Binder,WindowState对象>
WindowState通过本地的client实例维护IWindow实例,同时利用该实例访问窗口。

FocusWindow活动窗口如何计算

原理其实很简单,首先找到前台应用,然后根据mWindow找到Z-order顺序中第一位次的窗口,该窗口就是活动窗口。

为什么要提出Token这个概念

Token在本质上就是一个标示符,应用程序使用改标示符来找到该应用的窗口。AppToken:<Token:IBinder,allWindows>。通过Token就可以管理该应用的所有窗口。

WindowManager消息与分发

下面再来说一下WindowManager的系统消息收集与分发过程。WindowManagerService在内部维护了一个KeyQ的消息队列,同时还有两个线程:

1.InputDeviceReader
2.InputDispatcherThread

InputDeviceReader使用Native函数readEvent从driver中读取RawEvent并放到KeyQ队列中。
InputDispatherThread负责从KeyQ队列中读取事件,并在WindowManager找到对应的窗口,利用该窗口的IWindow接口下发事件。

上一篇:《Java安全编码标准》一第 1 章 概  述


下一篇:数论之 素因子分解,素数筛选法,欧拉函数和扩展欧几里得算法 (整理)