`
1025250620
  • 浏览: 229801 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android 窗口管理

 
阅读更多

 

一、概述

在Android系统中,从设计的角度来看,窗口管理系统是基于C/S模式的。整个窗口系统分为服务端和客户端两大部分,客户端负责请求创建窗口和使用窗口,服务端完成窗口的维护,窗口显示等。

 

 

 

在Client端,并不是直接和WindowManagerService交互,而是直接和本地对象WindowManager交互,然后由WindowManager完成和WindowManagerService的交互。对于Android应用来说这个交互是透明的,应用不能感知到WindowManagerService的存在

 

 

 

二、窗口的定义

在android的应用框架中,窗口主要分为两种:

第一种是应用窗口:一个activity有一个主窗口,弹出的对话框也有一个窗口,Menu菜单也是一个窗口。在同一个activity中,主窗口、对话框、Menu窗口之间通过该activity关联起来。和应用相关的窗口表示类是PhoneWindow和Window,PhoneWindow继承于Window,针对手机屏幕做了一些优化工作。PhoneWindow只是一个窗口封装类,里面核心的是mDecorView这个变量,mDecorView是一个顶层的View,窗口的添加就是通过调用getDecorView()获取到mDecorView并且调用WindowManager.addView()把该View添加到WindowManager中。

第二种是公共界面的窗口:如最近运行对话框、关机对话框、状态栏下拉栏、锁屏界面等。这些窗口都是系统级别的窗口,不从属于任何应用,和activity没有任何关系。这种窗口没有任何窗口类来封装,直接调用WindowManager.addView()来把一个view添加到WindowManager中。

在应用初始化的时候,会首先生成一个Activity对象,此时该activity还没有属于他的一个窗口。紧接着通过调用attach()函数,在attach()函数里面该activity会调用PolicyManager.makeNewWindow()创建一个新的PhoneWindow,然后在activity的onCreate()生命周期里,一般应用都会调用setContentView()设置该activity的显示界面。在setContentView()里,框架会自动生成一个布局,该布局文件包含了如标题栏、ActionBar等元素,最重要的是包含了应用的contentView。这个布局对应的就是PhoneWindow里面的mDecorView。最后在activity将要显示出来之前,通过getWindow().getDecorView()获取到DecorView,并通过WindowManager.addView()把DecorView添加到WindowManager中。

 

 

 

Activity添加客户端窗口时序图

 

 

 

 

三、 窗口管理

Android的窗关管理是基于C/S模式的,并且使用独立进程的方式实现。窗口管理的服务端WindowManagerService运行在独立的进程system_server里,当应用程序需要创建窗口时,通过进程通信的方式请求WindowManagerService创建窗口,由WindowManagerService向应用程序传递和窗口相关的交互消息。所有程序的窗口都在服务端管理,窗口的显示和控制都在WindowManagerService里处理。

WindowManagerService主要完成了以下几部分功能:

1.      窗口的添加和删除

2.      窗口的显示和隐藏控制

3.      Z-order顺序管理

4.      焦点窗口和焦点应用的管理

5.      输入法窗口管理和墙纸窗口管理

6.      转场动画

7.      系统消息收集和分发

 

服务端的实现代码是在/framework/base/services/java/com/android/server/wm/里,核心的几个类是:

WindowManagerService.java

WindowState.java

WindowToken.java

AppWindowToken.java

Session.java

InputManager.java

InputMonitor.java

 

类解释:

WindowManagerService负责完成窗口的管理工作;

WindowState和客户端窗口一一对应,应用调用WindowManager.addView()时,最终会在WindowManagerService添加一个WindowState与之一一对应。

WindowToken是一个句柄,保存了所有具有同一个token的WindowState。应用请求WindowManagerService添加窗口的时候,提供了一个token,该token标识了被添加窗口的归属,WindowManagerService为该token生成一个WindowToken对象,所有token相同的WindowState被关联到同一个WindowToken。如输入法添加窗口时,会传递一个mCurrToken,墙纸服务添加窗口时,会传递一个newConn.mToken。

AppWindowToken继承于WindowToken,专门用于标识一个Activity。AppWindowToken里的token实际上就是指向了一个Activity。ActivityManagerService通知应用启动的时候,在服务端生成一个token用于标识该Activity,并且把该token传递到应用客户端,客户端的Activity在申请添加窗口时,以该token作为标识传递到WindowManagerService。同一个Activity中的主窗口、对话框窗口、菜单窗口都关联到同一个AppWindowToken。

Session表示一个客户端和服务端的交互会话。一般来说不同的应用通过不同的会话来和WindowManagerService交互,但是处于同一个进程的不同应用通过同一个Session来交互。

InputManager和InputMonitor负责上层的消息分发功能。

 

WindowManagerService内部的几个重要成员变量:

ArrayList<WindowState>         mWindows

HashMap<IBinder, WindowState>         mWindowMap

ArrayList<WindowToken>        mTokenList

ArrayList<AppWindowToken>         mAppTokens

 

mWindows保存了系统中所有的WindowState;

mWindowMap保存了每个WindowState和客户端窗口的映射关系,客户端应用请求窗口操作时,通过mWindowMap查询到对应的WindowState;

mTokenList保存了所有的WindowToken

mAppTokens保存了所有的AppWindowToken

 

 

 

 

窗口管理服务端主要类图

 

 

一个Activity从启动到添加窗口的整个流程如下:

ActivityManagerService在接收到启动Activity请求时,首先生成一个token作为该Activity的唯一标识。然后调用WindowManagerService向其添加一个AppWindowToken,此AppWindowToken封装了Activity的token。接着AMS启动应用客户端进程并把token传递到该进程,在客户端进程里完成Activity的初始化。在Activity的attach()函数中,Activity完成PhoneWindow的创建,并且把token传递给PhoneWindow。在Activity调用WindowManager.addView()时,在WindowManager内部会把token和该View关联,真正向WindowManagerService申请创建窗口的时候,再把token传递给WindowManagerService。WindowManagerService接收到创建窗口的请求的时候,通过mTokenMap查询对应该token的AppWindowToken,如果为空则抛出异常,否则创建一个WindowState并完成初始化工作和其他数据结构的调整工作。在这个过程中,token贯穿了服务端的AMS、WMS和客户端的Activity、Window。

 

Activity启动过程中创建窗口的时序图

 

 

 

 

四、            WMS中服务端和客户端的交互接口和数据结构

应用请求创建窗口时,和应用直接交互的是WindowManager对象。WindowManager只是一个接口,调用addView()创建窗口时正真交互的是WindowManagerImpl对象。WindowManagerImpl管理单个应用的所有本地窗口。应用调用addView()创建窗口时,WindowManagerImpl会生成一个ViewRoot对象与之相对应,并且把相应的参数LayoutParams保存起来。

addView()的执行流程如下:

(1)    检查所添加的窗口是否已经添加过,不允许重复添加;

(2)    如果所添加窗口为子窗口类型,找到其父窗口,并保存在内部变量中;

(3)    创建一个新的ViewRoot,并保存对应的View(DecorView)和LayoutParams;

(4)    调用ViewRoot的setView()方法,完成真正意义上的添加工作。

 

ViewRoot本质上是一个Handler,并且实现了ViewParent接口。ViewRoot的主要功能是:

1.      负责分发消息事件,如Key、Motion事件等;

2.      负责和WMS的交互,分发WMS的交互命令;

3.      作为DecorView的parent,对DecorView进行draw、measure、layout等操作;

 

在addView()的第3、4步完成之后,ViewRoot就全权接管了和WMS的交互工作,DecorView不需要做任何交互动作。ViewRoot和WMS之间的双向对话,主要是通过以下两个数据结构进行的:

IWindowSession

IWindow

这两个数据结构都是标准的aidl接口,用于进程之间的同步通信。IWindowSession负责ViewRoot到WMS的单向请求,IWindow则用于WMS回调ViewRoot。在ViewRoot对象内部,存在着一个IWindowSession的静态成员和一个IWindow的非静态成员,所以一个进程里只有一个IWindowSession对象,但是可以有多个IWindow对象。

Window、WindowManager、DecorView、ViewRoot、IWindowSession、IWindowSession、WindowState、WindowManagerService之间的关系可用下图来表示:

 

 

 

 

 

在ViewRoot的构造函数中,调用getWindowSession()初始化静态成员sWindowSession和非静态成员mWindow。在第4步调用setView()方法时,ViewRoot会调用sWindowSession.add()方法,把IWindow添加到WMS中,WMS就会生成一个WindowState与之一一对应,并且把IWindow对象保存到WindowState内部作为回调的接口。之后所有WMS的命令,都会通过直接访问IWindow接口,以消息的形式分发到ViewRoot,ViewRoot来完成相应的处理,或对DecorView进行操作,或完成后通过sWindowSession报告给WMS。

 

 

一个窗口从添加到显示可用以下时序图表示:

 

 

 

 

 窗口添加过程时序图

 

 

 

 

到此为止,整个窗口管理系统整体架构可表示如下:

 

 

 

窗口管理系统整体架构图

 

 

 

五、            WindowState和Surface

 

从Client端调用WindowManager的addView()方法到WMS完成WindowState的初始化,在这整个过程中,只是完成了一个窗口数据结构的创建,也就是说,到现在为止,Client端的窗口和Server端的窗口已经建立了一种相对固定的连接关系,并且Client端和Server端之间能够正常通信,WMS能够透明的对Client端的窗口进行操作,同时WMS也能够接收Client端窗口的命令,对WindowState进行相应的调整。

一个WindowState想要显示在屏幕上,必须申请一个显示缓存,这个显示缓存的管理和维护是在底层图形模块实现的,在java层有一个操作的封装对象Surface。WindowState申请到Surface对象之后,会将此Surface对象的相关数据拷贝到Client端的ViewRoot中,ViewRoot中也维护了一个Surface对象,实际上这两个对象是指向同一块显示缓存。ViewRoot有了这块显示缓存的引用之后,即可以通过lockCanvas来获取绘画画布,绘制完毕之后通过unlockAndPostCanvas来将绘制内容刷新到显示缓存中。也就是说,Client端窗口和Server端窗口共用一个Surface,Client负责绘制Surface的内容,Server负责控制Surface在屏幕上的大小位置等。

ViewRoot通过IWindowSession的relayout()接口来向WMS发送请求命令,包括窗口的显示和隐藏,窗口的布局信息如位置大小,同时还会接收WMS的处理结果。WMS会根据屏幕大小和Client请求的布局参数来决定窗口最终的布局信息,同时也会根据Client请求的显示隐藏命令来返回一个有效的或者无效的Surface对象。通常一个窗口的显示过程为:

1.      Client请求显示窗口,并且传递布局参数;

2.      WMS根据布局参数,申请一个Surface对象并返回给Client;

3.      Client对Surface进行绘画操作,完成后告诉WMS;

4.      WMS将Surface显示在屏幕上,并且进行层级等相应调整;

 

 

 

 

窗口显示过程时序图

 

 

 

一个横跨Activity、View、ViewRoot、IWindowSession、IWindow、WindowState、WindowManagerService、Surface的整体概念如下如所示:

 

窗口管理系统完整架构图

分享到:
评论
1 楼 sfshine 2014-11-18  
非常好非常好

相关推荐

    Android 核心分析(13) -----Android GWES之Android窗口管理.doc

    Android窗口管理遵循C/S(客户端/服务器)模式。Window在Android中代表顶级窗口,而DecorView作为Window的顶级视图,是Activity的主要视图组件,它会自动附加到Activity的主窗口上。当Activity创建其主窗口并将其...

    liuying1992#open-source-project#01Android窗口管理框架:Android窗口管理框架概述1

    从上图可以看出,Android的显示系统分为3层:UI框架层:负责管理窗口中View组件的布局与绘制以及响应用户输入事件WindowManagerService

    android 360浮动窗口

    总结起来,实现“360浮动窗口”涉及以下几个关键点:理解Android窗口管理,创建自定义ViewGroup,编写悬浮服务,处理触摸事件和手势识别,以及权限管理和屏幕旋转适配。通过这些知识点的综合运用,我们可以创建出...

    android实例--窗口抖动demo

    首先,我们需要理解Android窗口管理的基本概念。 Android窗口(Window)是应用程序与用户交互的容器,它承载了Activity、Dialog等UI组件。窗口抖动涉及到Android的动画系统,包括属性动画(Property Animation)和...

    Android代码-仿UC浏览器多窗口管理界面

    multiwindow multiwindow ui apply in android 安卓多窗口管理界面,仿UC浏览器多窗口管理界面 使用 viewpager fragment 实现 效果图1: 效果图2:

    Android多窗口系统的研究、设计与实现.pdf

    在深入理解Android窗口管理机制的基础上,论文提出了整体UI系统、APP、Activity和Window子系统的多层次设计方案。 在整体UI系统层面,设计需要考虑到如何在有限的屏幕空间内合理地分配和切换多个窗口,保持界面的...

    Android平台下双屏切换显示的设计

    它在Android窗口管理系统中扮演着承上启下的角色,由Java语言编写的Surface类和C++语言编写的SurfaceComposerClient类共同组成。 当创建Surface对象时,会同时创建一个对应的SurfaceComposerClient对象。Surface类...

    安卓Android源码——窗口抖动(源码).zip

    首先,我们需要理解Android窗口管理器(Window Manager)的工作原理。窗口管理器是Android系统中的关键组件,负责布局、显示和管理应用程序的窗口。它接收来自应用的窗口更新请求,并将这些请求转换为显示设备可以...

    随意调节你的activity的大小,activity 自定义窗口大小

    总之,实现Activity自定义窗口大小涉及到对Android窗口管理、布局设计、触摸事件处理等多个方面的深入理解和实践。通过以上步骤,你可以在应用中创建一个可自由调整大小的Activity,为用户提供更加个性化的交互体验...

    Android内核剖析

    2. Android窗口管理系统 窗口管理系统是用户界面的重要组成部分,负责管理应用程序窗口的创建、销毁以及窗口间的切换和布局。在Android中,这个系统主要通过Window Manager Service来实现,它能够管理不同应用窗口间...

    Android 窗口类型

    ### Android窗口类型详解 在Android开发中,理解窗口(Window)的概念及其管理方式至关重要。窗口是用户界面的基本组成部分,每一个应用程序界面背后都有一个或多个窗口支撑。本文将深入探讨Android中的三种主要...

    [经典文档]Android核心分析

    核心分析之十三 ----- Android GWES之Android窗口管理 核心分析之十四 ----- Android GWES之输入系统 核心分析之十五 ----- Android 输入系统之输入路径详解 核心分析之十六 ----- Android 电话系统-概述篇 核心...

    行业分类-设备装置-一种应用于Android平台的显示窗口的方法和装置.zip

    综上所述,该技术方案可能涉及到Android窗口管理、自定义UI设计、硬件加速、触摸事件处理以及多窗口模式等多个方面,旨在提升Android应用在显示窗口方面的性能和用户体验。通过深入理解和应用这些知识点,开发者可以...

    Android核心分析-050417421

    4.窗口管理:Android窗口管理的基本架构原理、GWES之基本原理篇、GWES之消息系统。 5.输入系统:Android输入系统之输入路径详解。 6.电话系统:Android电话系统概述篇、rilD、RIL-Java、GSMCallTacker。 7.应用...

    Android 提高篇 机制 分析

    #### 十三、AndroidGWES之Android窗口管理 对GWES中的窗口管理进行更详细的解析,介绍其实现细节。 #### 十四、AndroidGWES之输入系统 分析GWES中的输入系统,包括输入事件的捕获、分发机制等。 #### 十五、...

    深入理解Android卷 III 的SampleWindow

    在这一卷中,第四章的SampleWindow是一个关键的概念,它为我们揭示了Android窗口管理的奥秘。SampleWindow是一个示例窗口类,展示了如何在Android框架层实现窗口功能。 首先,我们来探讨SampleWindow的核心概念。在...

    Android底层架构研究

    AndroidGWES之Android窗口管理** 窗口管理是GWES的一个重要方面,它涉及到窗口的创建、销毁、布局调整和焦点处理。WindowManagerService是窗口管理的核心组件,负责所有窗口的生命周期管理。 ### **13. Android...

    android的核心分析

    #### AndroidGWES之Android窗口管理 进一步深入窗口管理的具体实现细节,包括如何创建窗口、设置属性、更新布局等。 #### AndroidGWES之输入系统 输入系统处理用户的输入事件,如触摸、按键等,确保应用程序能够...

Global site tag (gtag.js) - Google Analytics