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

    xiaoxiao2025-10-01  7

    本文内容参考: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相对应。 两者之间通过建立session会话进行通信,而这里的session采用的还是Android中最重要的IPC方式——AIDL。Activity在建立窗口后需要将该窗口注册到WindowManager中,这个过程涉及到在Activity本地创建一个WindowManager的代理,Activity通过这个代理和远程WindowManager进行会话,会话的通道是IWindowSession,本质上就是一个AIDL通信过程。 会话是双向的,为了将消息发送给对应的Window,WindowManager通过IWindow接口将对应的消息发送给Window端对应的处理函数。

    Client端——Activity

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

    ViewRoot

    ViewRoot的真正实现类是ViewRootImpl。ViewRoot通过与WindowManager进行通信完成addView以及消息下发。ViewRoot通过IWindowSession将窗口加入到WindowManager中。 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。

    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接口下发事件。

    最新回复(0)