Android源码剖析之Framework层进阶版


 本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


上一篇我们主要讲了Ams,篇幅有限,本篇再讲讲Wms,即WindowManagerService,管理窗口的服务。主要负责窗口的创建、删除、状态等与手机交互的事情,与Ams配合使用,在SystemServer中创建,用来保持窗口层级关系方便SurfaceFlinger绘制屏幕,和传递窗口信息给InputManager调用InputDispatcher将输入消息派发到顶层窗口。


Activity、View与Window的区别与联系,View是最底层的显示控件,Activity包含一个DecorView+Window实现类引用PhoneWindow,而Window是一个接口-用来将手势动作转化为Activity可识别的信号。至于什么叫窗口,你看到的就是窗口,这是一个抽象的东西,比如Windows操作系统的多窗口,和Android系统当前应用的单窗口。而窗口由什么组成,两部分,一部分叫状态,另一部分叫界面,哈哈,听起来是不是很简单?也就是说你所有的操作会产生一个状态,这个状态会在界面上得以体现,如后退关闭当前页面。前言介绍有点多,接下来说点重点。


1、前面指的界面是Surface由SurfaceManager来管理,状态由WindowState来管理;布局两种层叠与平铺,显然Android使用层叠式;2、关于布局的方式,对应两种程序实现方式:独立进程式和库共享式。作用是用来屏幕绘制和消息处理,前者独立后者依赖,Windows使用后者,因此Android使用前者,不要问我为什么,就是这么个性!———————————————还是告诉你好了,因为这样一个窗口崩溃系统依然完好。3、应用窗口的大小=屏幕-状态栏,对比苹果的屏幕-菜单栏。4、关于焦点,两种情况,一般情况下最前面的窗口获得焦点,二般情况下系统按键动作由系统获得焦点,支持窗口切换添加动画效果。


跟View的操作差不多,Wms也有几个动作,assignlayer给窗口分配层值越大越靠前(动态的),performlayout根据输入法窗口、状态栏和窗口动画来计算可用的大小、placesurface像draw方法一样将窗口展示在屏幕下(不着急,下下篇就介绍View)。


介绍几个跟Wms关联比较紧密的类

1、WindowManagerPolicy:接口,约束Wms能干什么

2、WindowManager:Activity通过它调用remove和addView,然后由Binder类型的ViewRoot通过IPC传给Wms具体执行

3、SurfaceManager:调动SurfaceFlinger(linux驱动)绘制屏幕,使用芯片的图形加速器引擎完成工作

4、InputManager:获得输入消息,拥有Wms引用;执行时先执行InputMonitor,使用InputWindow保存寻找焦点所需信息

5、WindowState:真正的窗口,记录大小、层值、动画状态;每个窗口均有一个它;WindowToken用来实现IPC交互,一个窗口只有一个,子窗口均指向它;AppWindowToken指App在Wms的token用来最终管理交互。

6、Animation:Dim和Fade,分别是变暗和渐进动画,是窗口用的最多的效果

7、PolicyThread:WindowManagerPolicy类型,主要Wms使用异步操作的一个工具

8、Session:SufaceSession(用于向SurfaceFlinger添加删除窗口)的包装类,显然用来保存渲染的缓存信息,主要有uid、pid等

9、WaterMark:作用一防篡改二加通用背景,保存在/system/etc下,格式是content%

10、VMThread:SystemServer的异步线程

Wms最重要的就是添加和删除窗口,还是要具体讲一下的,先讲添加窗口

创建ViewRoot对象,调用setView方法,通过IPC执行Session中的add方法,然后addWindow;在这一步需要执行一些前置

条件判断比如参数是否合法、窗口是否已存在、将屏幕大小给到InputManager应用输入法墙纸窗口的attr.token和type一致;再

添加窗口相关数据,如新建WindowState(包含session、ViewRoot的W对象、隶属窗口等)加入mWindowMap、传递touch

焦点等;最后执行后置判断将窗口状态变化反映到相关数据中,比如将焦点给予可交互的窗口、计算并重新分配层值。

接着再讲一下删除窗口,与Windows不同,用户不能直接关闭窗口,分两种显性删除直接调用WindowManager的remove方法

隐性删除指执行finish回调隐性删除: 先发送一个消息,通知关闭窗口,removeViewImediate负责删除activity窗口,closeAll负责

删除Activity相关如菜单、对话框窗口,删除自身的Session;然后看是否执行一个动画、尝试把焦点转移到另一个窗口,相当于

反向执行add过程。


接下来讲讲窗口大小,mContainingFrame(整屏)》mContentFrame(窗口实际)》mFrame(屏幕上显示),使用

layoutWindowLv来计算窗口大小,如果是输入法则是可用大小,否则情况有三:1、考虑状态栏2、全屏3、是否排序输入法窗体

大小;输入法窗口仅允许被添加一次、且下面不允许有内容,调用ViewRoot.W的resize方法,一般使用下面方法,防止其获得焦点

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

影响窗口可视状态因素有二:1、动画,2、是否显示

最后SurfaceFlinger对窗口进行重绘,操作Surface窗口,对视图View进行变换,而动画有两种Animation(tranlslate、scale、

rotate、alpha)对View操作进行有限变换和Tween(距离移动)对Surface操作进行变换,主要对界面进行不间断的重绘。

多种情况下Ams会调用Wms如增删appWindowToken、设置窗口可见、动画切换等,少数情况下Wms会调用Ams如暂停App

切换、横竖屏切换、杀死App等。


横竖屏切换主要由三种情况引起:1、ActivityStack执行resumeTopActivityLocked2、Wms执行window操作3、人为旋转

设备。


最后放出来两张图,activity启动过程和停止过程: