android ams wms view,android Gui系统之WMS(1)

SurfaceFlinger 前面说的,就是一个surface的合成。SurfaceFlinger就是一个默默的记录着,它不会对surface的内容有什么改动。

WMS(WindowsManagerService)就是对surface的管理,或者说是一个大管家。它负责协调各方面资源。

ViewRoot就是一个个演员,负责表演(产生surface)。

从IO系统角度而言,WMS至少要干这几件事。

全局窗口管理

全局事件派发

键盘

触摸屏

1.WMS综述

1)WMS将以同AMS等一样的形式,系统server的一部分。

由SystemServer负责启动

知道系统关闭才能停止

发生异常的时候,能够自我恢复

2)SurfaceFlinger 和WMS将有很多交集。

3)有显示需求的图层。可以想见,界面显示是分不同层级的。

4)inputManagerService 当有按键或者触摸事件时,WMS时最好的管理员。

5)AMS 同WMS 也有交互。

6)Bind交互

从WMS窗口的实现来讲,主要包含如下子功能

窗口的添加和删除

启动窗口

窗口动画

窗口大小

窗口层级

事件派发

1.1WMS的启动

services\java\com\android\server\SystemServer.java

76553116_1.gif

private voidstartOtherServices() {

inputManager= newInputManagerService(context);

Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

traceBeginAndSlog("StartWindowManagerService");

wm=WindowManagerService.main(context, inputManager,

mFactoryTestMode!=FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);

ServiceManager.addService(Context.WINDOW_SERVICE, wm);

ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

}

76553116_1.gif

1.2 WMS提供的服务

public class IWindowManagerImpl implements IWindowManager

提供了很多功能,包含屏幕获取,获取窗口大小,启动窗口等

1.3 WMS工作方式

WMS很复杂,以工作方式作为切入点是比较合适的。

WMS,AMS,Activity之间的关系

76553116_2.png

WMS 可以和AMS相互调用,Activity有Window的对象。

publicViewRootImpl(Context context, Display display) {

mContext=context;

mWindowSession= WindowManagerGlobal.getWindowSession();

76553116_1.gif

public staticIWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try{

InputMethodManager imm=InputMethodManager.getInstance();

IWindowManager windowManager=getWindowManagerService();

sWindowSession=windowManager.openSession(newIWindowSessionCallback.Stub() {

@Overridepublic void onAnimatorScaleChanged(floatscale) {

ValueAnimator.setDurationScale(scale);

}

},

imm.getClient(), imm.getInputContext());

}catch(RemoteException e) {

Log.e(TAG,"Failed to open window session", e);

}

}returnsWindowSession;

}

}

76553116_1.gif

可以看到,是windowmanager提供的一个session

当启动一个activity的时候,AMS会把记录放到activityRecord。同时WMS会对activity进行记录,就用WindowState

2.窗口属性

2.1窗口的层级和类型

窗口的类型很多,不过,可以统一划分为3类,Application Window,System Window,Sub Window.

它们全部定义在WindowManager.java

2.1.1 普通窗口

76553116_3.png

2.1.2 Sub Window

76553116_4.png

这一类主要就是Dialog 之类的。

2.1.3 系统窗口

系统窗口非常多,主要由系统状态栏,来电,输入法等。

具体的取值:

Application Window:1-99

SubWindow:100-1999

SystemWindow:2000-2999

当某个进程向WMS申请一个Window的时候,需要告诉系统窗口的类型。如果有3个app在运行中,则前台有3个窗口,这个时候,需要能调整它们的优先级。

对于Window的显示,层级越高,显示越前面。这个显示的动作,由SurfaceFlinger来处理。

76553116_1.gif

if ((mAttrs.type >= FIRST_SUB_WINDOW &&mAttrs.type<=LAST_SUB_WINDOW)) {//The multiplier here is to reserve space for multiple//windows in the same type layer.

mBaseLayer =mPolicy.windowTypeToLayerLw(

attachedWindow.mAttrs.type)*WindowManagerService.TYPE_LAYER_MULTIPLIER+WindowManagerService.TYPE_LAYER_OFFSET;

mSubLayer=mPolicy.subWindowTypeToLayerLw(a.type);

mAttachedWindow=attachedWindow;

......

76553116_1.gif

所有窗口的mBaseLayer可以分几步获得:

@Step1:windowTypeToLayerLw

这个根据不同的窗口类型做了简单的映射。

76553116_5.gif

windowTypeToLayerLw

对于sub window而言,窗口类型取决于父窗口类型。

@Step2. 上一步获得的值*TYPE_LAYER_MULTIPLIER(10000)+TYPE_LAYER_OFFSET(1000)

同一类型的窗口可能由很多。1000.是为了移动一组window而设计的。

@Step3.subWindowTypeToLayerLw 计算子窗口的layer。偏移量在1,或者-2都有可能。所以子窗口现在在父窗口的上面。或者下面,都可能。

2.2窗口属性

windowmanagerprolicy。android显示的同一的规则。手机有StatusBar,而平板有CombinedBar。类似,但是功能不一样。

76553116_1.gif

/*** WindowManagerPolicy implementation for the Android phone UI. This

* introduces a new method suffix, Lp, for an internal lock of the

* PhoneWindowManager. This is used to protect some internal state, and

* can be acquired with either the Lw and Li lock held, so has the restrictions

* of both of those when held.*/

public class PhoneWindowManager implements WindowManagerPolicy

76553116_1.gif

PhoneWindowManager 和call没有关系,它表述andorid phone的UI显示规则。

2.3 layoutParams

1)Type

窗口类型,不再说明。

2)Flags

最典型的就是,保持屏幕常亮。这个可以使用FLAG_KEEP_SCREEN_ON。

在activity下使用这个方法就可以:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

FLAG_ALLOW_LOCK_WHILE_SCREEN_ON:只要此窗口可见,即使屏幕点亮,也允许锁屏。 从现实来讲,有这个需求吗? 测验后,实际效果,会半暗屏,但不会上锁。

FLAG_DIM_BEHIND:在窗口后面的东西,都将变暗。 dialog之类的比较常用。一个非常有用的flag,尤其是需要做蒙层的时候。

76553116_5.gif

DimDialog

FLAG_BLUR_BEHIND:高斯模糊,目前已经废弃,对性能的影响巨大,不建议使用。

FLAG_NOT_FOCUSABLE:窗口不处理事件,将会传递到后面的其他窗口。同时FLAG_NOT_TOUCH_MODAL也会被设置。

FLAG_NOT_TOUCHABLE:touch 事件传递到后面的窗口使用。

getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

FLAG_KEEP_SCREEN_ON:最常用,最经典的模式,屏幕常量

FLAG_FULLSCREEN:全屏,没有状态栏。

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

动态调整全屏状态:

76553116_5.gif

full

FLAG_FORCE_NOT_FULLSCREEN:同FLAG_FULLSCREEN相反

FLAG_SECURE:窗口无法被截屏。不安全的应用也无法显示等。

FLAG_SCALED:按用户的要求调整窗口

FLAG_IGNORE_CHEEK_PRESSES: 当屏幕有可能贴着脸时,这一选项可防止面颊对屏幕造成误操作。

FLAG_LAYOUT_INSET_DECOR:只能和FLAG_LAYOUT_IN_SCREEN一起使用,充分考虑各种情况

FLAG_SHOW_WHEN_LOCKED:在锁屏的时候,可以显示该页面,也是非常重要的flag。关于锁屏的问题可以参考 锁屏上显示Activity 这篇博客,此处不再叙述。

FLAG_SHOW_WALLPAPER:当前activity为透明或者半透明的时候,让壁纸作为背景。

WindowManager.LayoutParams lp=getWindow().getAttributes();

lp.alpha= 0.5f;

getWindow().setAttributes(lp);//设置透明度

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);//设置壁纸

FLAG_TURN_SCREEN_ON:把屏幕点亮

FLAG_DISMISS_KEYGUARD:解锁。是指普通锁屏,但是安全锁(图案或者密码锁屏界面)是无效的。 在电话界面,可以直接解锁,而不需进入锁屏界面。

FLAG_HARDWARE_ACCELERATED:硬件加速,具体取决于硬件条件。

3)systemUiVisibilty

这个flag,定义在View中,

这里先明确,这些flag起作用,首先这个view必须是可见的。而window的flag是全局的。

View.SYSTEM_UI_FLAG_VISIBLE:显示状态栏 View.INVISIBLE 对应属性,隐藏状态栏。

View.SYSTEM_UI_FLAG_FULLSCREEN 和上节讲到的FLAG_FULLSCREEN具有相同的效果,具体的细微差距,请参考http://www.360doc.com/content/15/0204/18/20385871_446270224.shtml 这篇文章。此处不做详细讨论。

根据经验,View可以是临时的,而FLAG_FULLSCREEN 可以是长期的。

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 可以是navigationbar隐藏。

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN activity全屏显示,但是statusbar不会隐藏,会把activity上面的部分,覆盖。

View.SYSTEM_UI_FLAG_IMMERSIVE ,在5.1上测试的结果同SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 类似,activity全屏,但statusbar仍然存在。半透明的状态,但是状态栏点击会有反映。

View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 在statusbar隐藏后,过几秒会自动出现。

这里还要注意getWindow().getDecorView().setSystemUiVisibility();同setContentView(layout.activity_wall_layout);的顺序问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值