ANDROID窗口管理服务实现机制和架构分析
一、功能
窗口管理是ANDROID框架一个重要部分,主要包括如下功能:
(1)Z-ordered的维护
(2)窗口的创建、销毁
(3)窗口的绘制、布局
(4)Token管理,AppToken
(5)活动窗口管理(FocusWindow)
(6)活动应用管理(FocusAPP)
(7)输入法管理
(8)系统消息收集与分发
这些功能主要由一个窗口管理服务和相应的客户端来实现的,客户端通过BINDER机制与服务实现交互。
窗口管理服务端负责主要的窗口管理功能,由一个WindowManagerService服务及相关的类来组成。客户端则负责与窗口管理服务交互,并对应用和其它服务提供窗口管理接口,包括提供窗口视图的添加、移出和更新等接口函数,客户端的功能通过WindowManager接口及其实现WindowManagerImpl和相关类来完成,WindowManager提供的接口函数包括如下几个:
1、 public
voidaddView(View view, ViewGroup.LayoutParams params);
用来在窗口实例对应的窗口上添加一个视图。
2、public
void removeView(View view) ;
用来从窗口实例对应的窗口上移出一个视图。
3、public
void updateViewLayout(View view,ViewGroup.LayoutParams params);
用来更新窗口上的视图的布局。
4、 public
DisplaygetDefaultDisplay();
每个窗口管理实例需要绑定到特定的显示对象上,并在此显示对象上创建和显示新的窗口。
该函数返回一个窗口管理实例管理和使用的显示对象。
窗口为了能在另外的显示器上显示,需要先调用Context.createDisplayContext创建一个显示对象使用的独立的Context,然后使用该Context调用Context.getSystemService(Context.WINDOW_SERVICE)函数获得该显示对象对应的窗口管理实例。也可以直接创建一个Presentation对象,Presentation对象会自动创建显示对象需要的窗口管理实例和Context对象。
二、类图
窗口管理的整个类图如下:
整个类图包括客户端和服务端两大部分。
服务端的主要类有WindowManagerService、Session、WindowState、WindowToken、AppWindowToken、DisplayContent等主要类。
WindowManagerService服务是一个系统服务类,是整个窗口管理机制实现的核心。
Session对象也是一个服务端的桩对象,用来为客户端提供交互接口(IWindowSession),包括窗口的创建、销毁、布局等接口。每个与窗口管理服务交互的进程通常都需要打开一个Session对象来实现交互,用来保证一个Session会话期间窗口状态的一致。
Session对象在一个进程新建第一个视图时使用窗口管理服务的的openSession接口函数创建,第一个视图新建期间也创建一个SurfaceSession对象用来实现视图的绘制操作。SurfaceSession对象用来与SurfaceFliger服务建立连接,实现视图及包含的子视图在显示硬件上的实际输出工作。
服务端创建的窗口类型包括三大类型的窗口:包括三种类型的应用窗口、五种类型的子窗口(必须依附于其它窗口的窗口类型,31种系统窗口(系统创建的窗口,应用不能使用)。
应用窗口类型:
TYPE_BASE_APPLICATION
基窗口,作为所有其它应用窗口的基窗口,所有其它应用窗口需要在该类型的窗口上面呈现。
TYPE_APPLICATION
普通应用窗口,通常与一个ACTIVITY对应,该类型的应用窗口必须有一个Activity
token来标示它所属的Activity。TYPE_APPLICATION_STARTING
应用启动窗口,该类型窗口在应用启动时显示。该类型窗口由系统使用,用来在应用能够显示本身窗口之前显示一些其它内容。
子窗口类型:
TYPE_APPLICATION_PANEL
PANEL类型窗口,用来在它所依附的应用窗口上面显示一个PANEL。
TYPE_APPLICATION_MEDIA
MEDIA窗口,这种类型的子窗口在它所依附应用窗口的后面显示,用来显示媒体内容,如视频。
TYPE_APPLICATION_SUB_PANEL
子PANEL窗口,该类型的窗口在它所依附的应用窗口和任意的PANEL窗口的上面显示。
TYPE_APPLICATION_ATTACHED_DIALOG
依附对话框窗口,用来在一个应用窗口上显示一个对话框。
TYPE_APPLICATION_MEDIA_OVERLAY
媒体覆盖窗口,用来在媒体窗口上显示一些覆盖物,该类型窗口在应用窗口和媒体窗口之间显示,因此它应该是透明的。
系统窗口类型包括:TYPE_STATUS_BAR、TYPE_SEARCH_BAR、TYPE_PHONE、TYPE_SYSTEM_ALERT、TYPE_KEYGUARD、TYPE_TOAST、TYPE_SYSTEM_OVERLAY、TYPE_PRIORITY_PHONE、TYPE_SYSTEM_DIALOG、TYPE_KEYGUARD_DIALOG、TYPE_SYSTEM_ERROR、TYPE_INPUT_METHOD、TYPE_INPUT_METHOD_DIALOG、TYPE_WALLPAPER、TYPE_STATUS_BAR_PANEL、TYPE_SECURE_SYSTEM_OVERLAY、TYPE_DRAG、TYPE_STATUS_BAR_SUB_PANEL、TYPE_POINTER、TYPE_NAVIGATION_BAR、TYPE_VOLUME_OVERLAY、TYPE_BOOT_PROGRESS、TYPE_HIDDEN_NAV_CONSUMER、TYPE_DREAM、TYPE_NAVIGATION_BAR_PANEL、TYPE_UNIVERSE_BACKGROUND、TYPE_DISPLAY_OVERLAY、TYPE_MAGNIFICATION_OVERLAY、TYPE_RECENTS_OVERLAY、TYPE_KEYGUARD_SCRIM、TYPE_PRIVATE_PRESENTATION。
窗口管理服务内部使用WindowState窗口状态对象来维护每一种类型的窗口状态,并使用WindowToken对象来唯一标示每个窗口,因此每个窗口必须对应一个WindowToken对象和一个WindowState对象,每个窗口对应的WindowToken对象根据客户端传送的窗口布局参数中的token值来实例化和定位。
在窗口管理服务的addWindow函数中,使用attrs.token作为参数实例化一个WindowToken对象,并使用token作为键值保存到窗口管理服务的一个HashMap变量中。
<span style="color:#000066;"> mTokenMap.put(attrs.token, WindoToken); </span>
每个WindowState窗口状态对象也根据传进来的客户端对象(为一个IWindow.Stub对象)作为键值放到mWindowMap中,实现WindowState窗口状态对象与客户端对象的绑定。
<span style="color:#000066;"> mWindowMap.put(client.asBinder(), win); finalArrayList<WindowState> mWindows;mWindowMap.put(client.asBinder(), win);
</span>
attrs
.token参数是窗口布局参数中LayoutParams的一个binder对象,在客户端新建窗口(addView)时赋值,主窗口类型对应ACTIVITY的AppToken,子窗口类型对应主视图的WindowToken。
<span style="color:#000066;"> public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable { public int type; public IBinder token = null; }
</span>
窗口管理系统支持多用户以及在多个显示器进行输出,不同的用户可以显示不同的内容,不同的显示器也可以显示不同的内容,而且每一个窗口还可以依附有子窗口。因此每一个WindowState对象维护一个独立的DisplayContent对象用来指示对应的窗口所依附的显示单元,每个DisplayContent对象内部也维护一个WindowState类型的WindowList窗口列表,用来存储该显示单元要显示的窗口列表。DisplayContent对象还通过StackBox、TaskStack及Task等对象或对象数组来管理该显示单元上要显示的应用活动窗口。
AppWindowToken对象是WindowToken类的特例,用来作为应用窗口类型的标示。应用类型的窗口对应的WindowToken对象的appWindowToken属性必须指向一个AppWindowToken对象。AppWindowToken对象内部还包含一个与客户端的应用窗口交互的IApplicationToken接口,实现与Activity的交互。
窗口管理系统中的ViewServer类提供了窗口的远端控制功能。InputMonitor类提供了输入焦点窗口的监视和输入提交到相应窗口的功能。
窗口管理系统还提供了一个WindowManagerPolicy类,
窗口管理服务通过WindowManagerPolicy类实现窗口管理需要的所有UI方面的特定行为和操作(如窗口布局、特定的窗口类型、按键提交等)。
窗口管理服务还通过IActivityManager、DisplayManager、DisplayManagerService、InputManagerService、IInputMethodManager等接口和对象与活动管理服务、显示管理服务、输入管理服务、输入法管理服务交互。
客户端主要包含四个类 : ViewRootImpl、WindowManagerImpl、VIEW、Surface。
ViewRootImpl是视图处理类,是客户端视图的处理类,客户端的视图通过该类与窗口管理服务交互,因此ViewRootImpl是一个中介类。
ViewRootImpl内部包含一个从IWindow.Stub派生的内部类(ViewRootImpl.W),窗口管理服务通过该对象可以与客户端反向通讯。
客户端与窗口服务打开的会话保存在一个IWindowSession类型的变量中,客户端使用该变量向窗口管理服务端的Session对象发送请求,窗口管理服务中的窗口状态对象使用IWindow接口向客户端回送应答,借助ViewRootImpl的这两个Binder对象实现了客户端与窗口管理服务端的双向交互。
ViewRootImpl对象还维护一个View对象和一个View对象关联的View.AttachInfo类型的对象,ViewRootImpl通过这两个对象实现视图的绘制等功能。
ViewRootImpl还与Surface类关联。
WindowManagerImpl是客户端WindowManager管理接口的实现,WindowManagerImpl内部维护一个单例的WindowManagerGlobal对象,WindowManagerImpl通过该对象转发客户端的窗口管理请求。WindowManagerGlobal对象内部维护一个ViewRootImpl实例数组和一个View视图对象数组,每次客户端添加一个视图时都新创建一个ViewRootImpl对象,并把要添加的视图和新创建的ViewRootImpl对象添加到相应数组中,并调用新创建的ViewRootImpl对象的setView函数。
View类是视图的基类,实现视图的基本功能,如绘制等。View.AttachInfo是View类的内部类,用来维护视图的相关信息。视图的主视图通过ViewRootImpl对象与窗口管理服务交互,添加绑定到特定的显示桌面和窗口,ViewRootImpl也实现了ViewParent接口,因此也作为主视图的父视图使用。
Surface类用来提供视图复合输出的显示画布。
下面是一个打开一个窗口的序列图:
1)客户端在创建窗口时首先调用getWindowManager获得本地窗口管理对象,并调用其addView函数,在这里还为窗口的布局参数赋值,如窗口标题、包名字、token值、flag值等;
2)WindowManagerImpl是WindowManage的具体实现,因此窗口管理接口的addView函数实际调用WindowManagerImpl的addView函数;
4)WindowManagerImpl的addView函数首先查看要添加的视图是否已经存在,若不存在则实例化一个ViewRootImpl对象,并把view和ViewRootImpl对象及布局参数保存到本地数组中,接着调用ViewRootImpl对象的setView函数;
5)ViewRootImpl对象的setView函数先请求进行窗口的布局(调用requestLayout,在客户端完成一些处理后,也最终通过IWindowSession向窗口管理服务端的Session对象发送relayout布局请求),然后根据窗口属性是否支持输入实例化一个InputChannel,然后通过服务端远程代理对象IWindowSession向服务端Session对象发送新建窗口的请求(调用其addToDisplay接口);最后还要调用assignParent函数设置视图的父视图为ViewRootImpl对象本身;
6)服务端的Session对象收到addToDisplay请求后,就调用窗口管理服务的addWindow函数来完成新建窗口的任务,完成实际创建窗口的工作。addWindow中首先实例化一个WindowState对象代表新建的窗口,接着使用客户端窗口的Binder对象(ViewRootImpl.W对象)为键值把WindowState对象放入mWindowMap中,并根据Z-ORDER放入WindowState所维护的窗口列表数组中,还要调用WindowState对象的attach函数与Session完成绑定,并在SurfaceSession没有创建时完成创建;然后新建或获得WindowToken,并使用传进来的客户端窗口布局参数中的token值把WindowToken放入mTokenMap中,建立两者的映射关系;最后根据窗口能否能够接收键值更新焦点窗口。
版权所有,请转载时清楚注明链接和出处,谢谢!
ANDROID窗口管理服务实现机制和架构分析的更多相关文章
- ANDROID窗体管理服务实现机制和架构分析
一.功能 窗体管理是ANDROID框架一个重要部分,主要包含例如以下功能: )Z-ordered的维护 )窗体的创建.销毁 )窗体的绘制.布局 )Token管理,AppToken )活动窗体管理 ...
- Android窗口管理服务WindowManagerService计算窗口Z轴位置的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8570428 通过前面几篇文章的学习,我们知道了 ...
- Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8577789 在Android系统中,Activ ...
- Android窗口管理服务WindowManagerService显示窗口动画的原理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8611754 在前一文中,我们分析了Activi ...
- Android窗口管理服务WindowManagerService切换Activity窗口(App Transition)的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8596449 在Android系统中,同一时刻只 ...
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...
- Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8526644 在Android系统中,输入法窗口 ...
- Android窗口管理服务WindowManagerService的简要介绍和学习计划
在前一个系列文章中,我们从个体的角度来分析了Android应用程序窗口的实现框架.事实上,如果我们从整体的角度来看,Android应用程序窗口的 实现要更复杂,因为它们的类型和作用不同,且会相互影响. ...
- Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析
来自http://blog.csdn.net/luoshengyang/article/details/8479101 在Android系统中,Activity窗口的大小是由WindowManager ...
随机推荐
- 用户创建,删除and并发注册and系统登陆的API研究(学习汇总网上资料)
一.系统登陆链接实现 比如有一个外围支持系统,用户需要在外围系统登录之后点个link就可以登录到Oracle ERP系统中,那么我们需要先把外围系统的用户创建在Oracle ERP中,并且分配职责给他 ...
- AP模块NOTE修改API
--创建 AP_NOTES_PUB.Create_Note ( p_api_version IN NUMBER , p_init_msg_list IN VARCHAR2 := FND_API.G_F ...
- RxJava操作符(04-过滤操作)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656494 本文出自:[openXu的博客] 目录: Debounce Distinct ...
- springmvc文件上传和拦截器
文件上传 用到这两个包 配置视图解析器:springmvc配置文件配置 <!-- id必须要是"multipartResolver" --> <bean id=& ...
- 【NPR】铅笔画
写在前面 今天打算写一篇跟Unity基本无关的文章.起因是我上个星期不知怎么的搜到了一个网站 ,里面实现的效果感觉挺好的,后来发现是2012年的NPAR会议的最佳论文.看了下文章,觉得不是很难,就想着 ...
- 今天我点亮了CSDN博客专家殊荣
很久以前,看着csdn博客学习第一篇博客时,我依旧记得,是一个名叫蒋老夫子的博客专家,文章写的非常认真.内心很崇拜.在想,若干年后,在哪个地方?以什么样的一种状态,也得到此殊荣,华为有句口号,叫勇敢做 ...
- 剑指Offer——动态规划算法
剑指Offer--动态规划算法 什么是动态规划? 和分治法一样,动态规划(dynamic programming)是通过组合子问题而解决整个问题的解. 分治法是将问题划分成一些独立的子问题,递归地求解 ...
- 5. React 组件的协同使用 组件嵌套和Mixin
组件是React的核心,构建大型项目时多个组件之间需要进行协同使用.可以从横向和纵向两个角度来实现组件的协同使用,纵向的协同使用就是组件嵌套,横向的协同使用就是Mixin(抽取公共方法 ...
- Linux内核2.6的进程调度
Linux是多任务抢占操作系统,多任务就是指多个进程间通过分时切换来并发执行.非抢占的系统是对每个进程而言,除非时间片用完或主动放弃否则不会被剥夺CPU,主动放弃包括调用一些调度的系统调用( ...
- 如何在Cocos2D游戏中实现A*寻路算法(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...