android Gui系统之WMS(1)----window flags & view flags
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
private void startOtherServices() {
inputManager = new InputManagerService(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);
}
1.2 WMS提供的服务
public class IWindowManagerImpl implements IWindowManager
提供了很多功能,包含屏幕获取,获取窗口大小,启动窗口等
1.3 WMS工作方式
WMS很复杂,以工作方式作为切入点是比较合适的。
WMS,AMS,Activity之间的关系
WMS 可以和AMS相互调用,Activity有Window的对象。
public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
Log.e(TAG, "Failed to open window session", e);
}
}
return sWindowSession;
}
}
可以看到,是windowmanager提供的一个session
当启动一个activity的时候,AMS会把记录放到activityRecord。同时WMS会对activity进行记录,就用WindowState
2.窗口属性
2.1窗口的层级和类型
窗口的类型很多,不过,可以统一划分为3类,Application Window,System Window,Sub Window.
它们全部定义在WindowManager.java
2.1.1 普通窗口
2.1.2 Sub Window
这一类主要就是Dialog 之类的。
2.1.3 系统窗口
系统窗口非常多,主要由系统状态栏,来电,输入法等。
具体的取值:
Application Window:1-99
SubWindow:100-1999
SystemWindow:2000-2999
当某个进程向WMS申请一个Window的时候,需要告诉系统窗口的类型。如果有3个app在运行中,则前台有3个窗口,这个时候,需要能调整它们的优先级。
对于Window的显示,层级越高,显示越前面。这个显示的动作,由SurfaceFlinger来处理。
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;
......
所有窗口的mBaseLayer可以分几步获得:
@Step1:windowTypeToLayerLw
这个根据不同的窗口类型做了简单的映射。
@Override
public int windowTypeToLayerLw(int type) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return 2;
}
switch (type) {
case TYPE_PRIVATE_PRESENTATION:
return 2;
case TYPE_WALLPAPER:
// wallpaper is at the bottom, though the window manager may move it.
return 2;
case TYPE_PHONE:
return 3;
case TYPE_SEARCH_BAR:
case TYPE_VOICE_INTERACTION_STARTING:
return 4;
case TYPE_VOICE_INTERACTION:
// voice interaction layer is almost immediately above apps.
return 5;
case TYPE_INPUT_CONSUMER:
return 6;
case TYPE_SYSTEM_DIALOG:
return 7;
case TYPE_TOAST:
// toasts and the plugged-in battery thing
return 8;
case TYPE_PRIORITY_PHONE:
// SIM errors and unlock. Not sure if this really should be in a high layer.
return 9;
case TYPE_DREAM:
// used for Dreams (screensavers with TYPE_DREAM windows)
return 10;
case TYPE_SYSTEM_ALERT:
// like the ANR / app crashed dialogs
return 11;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
return 12;
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
case TYPE_KEYGUARD_SCRIM:
// the safety window that shows behind keyguard while keyguard is starting
return 14;
case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
case TYPE_STATUS_BAR:
return 16;
case TYPE_STATUS_BAR_PANEL:
return 17;
case TYPE_KEYGUARD_DIALOG:
return 18;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
return 19;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
return 20;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
return 21;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
return 22;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
return 23;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
return 24;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
return 25;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
return 26;
case TYPE_ACCESSIBILITY_OVERLAY:
// overlay put by accessibility services to intercept user interaction
return 27;
case TYPE_SECURE_SYSTEM_OVERLAY:
return 28;
case TYPE_BOOT_PROGRESS:
return 29;
case TYPE_POINTER:
// the (mouse) pointer layer
return 30;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
}
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。类似,但是功能不一样。
/**
* 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
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,尤其是需要做蒙层的时候。
public class DimDialog extends Dialog {
private static final float DIMDIALOG_TRANTANT = 0.3f;
private static final float DIMDIALOG_BG_TRANTANT = 0.8f;
public DimDialog(Context context) {
super(context);
setAttributes();
} private void setAttributes() {
WindowManager.LayoutParams lp=getWindow().getAttributes();
lp.alpha=DIMDIALOG_TRANTANT;
lp.dimAmount = DIMDIALOG_BG_TRANTANT;
getWindow().setAttributes(lp);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
} public DimDialog(Context context, int themeResId) {
super(context, themeResId);
setAttributes();
} protected DimDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
setAttributes();
}
}
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);
动态调整全屏状态:
private void full(boolean enable) {
if (enable) {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
getWindow().setAttributes(lp);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
} else {
WindowManager.LayoutParams attr = getWindow().getAttributes();
attr.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setAttributes(attr);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
}
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);的顺序问题。
android Gui系统之WMS(1)----window flags & view flags的更多相关文章
- android Gui系统之WMS(2)----窗口的添加
Android系统很多,但是最常用的就两类,一类是有系统进场管理的,系统窗口.还有一类就是由应用程序产生的,应用窗口. 1.系统窗口的添加流程 1.1 addStatusBarWindow Phone ...
- 图解Android - Android GUI 系统 (2) - 窗口管理 (View, Canvas, Window Manager)
Android 的窗口管理系统 (View, Canvas, WindowManager) 在图解Android - Zygote 和 System Server 启动分析一 文里,我们已经知道And ...
- 图解Android - Android GUI 系统 (5) - Android的Event Input System
Android的用户输入处理 Android的用户输入系统获取用户按键(或模拟按键)输入,分发给特定的模块(Framework或应用程序)进行处理,它涉及到以下一些模块: Input Reader: ...
- 图解Android - System Service 概论 和 Android GUI 系统
通过 图解Android - Binder 和 Service 一文中,我们已经分析了Binder 和 Service的工作原理.接下来,我们来简要分析Android 系统里面都有哪些重要的Servi ...
- 图解Android - Android GUI 系统 (1) - 概论
Android的GUI系统是Android最重要也最复杂的系统之一.它包括以下部分: 窗口和图形系统 - Window and View Manager System. 显示合成系统 - Surfac ...
- Android GUI系统
图解Android - Android GUI 系统 (1) - 概论 图解Android - Android GUI 系统 (2) - 窗口管理系统 图解Android - Android GUI ...
- android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论
GUI 是任何系统都很重要的一块. android GUI大体分为4大块. 1)SurfaceFlinger 2)WMS 3)View机制 4)InputMethod 这块内容非常之多,但是理解后,可 ...
- android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论【转】
转自:https://www.cnblogs.com/deman/p/5584198.html 阅读目录 1.OpenGL & OpenGL ES 2.Android的硬件接口HAL 3.An ...
- android Gui系统之SurfaceFlinger(3)---SurfaceFlinger
7.SurfaceFlinger SurfaceFlinger在前面的篇幅了,多有涉及. SurfaceFlinger是GUI刷新UI的核心,所以任何关于SurfaceFlinger的改进都会对and ...
随机推荐
- 使用nodejs+express(4.x+)实现文件上传
最简单的做法是通过“connect-multiparty”中间件实现上传. 通过在项目中npm install connect-multiparty进行安装. 用法: var multipart = ...
- [小工具]CSS内嵌样式自动提取器
逐行分析,将内联样式提取出来,并自动编号代替的一个小工具软件 注:style=""(此处必须是标准的双引号!) http://files.cnblogs.com/quejuwen/ ...
- 炉石传说 C# 设计文档(序)
经过3个月的开发,有很多感触. 以前一直以为技术是开发成败的第一因素,现在发现,等到你代码写的时间够长,经验够丰富,什么功能都能随手完成,对于业务的分析能力变成了第一位. 炉石山寨版的BS版本用到的H ...
- 基于.Net Framework 4.0 Web API开发(3):ASP.NET Web APIs 异常的统一处理Attribute 和统一写Log 的Attribute的实现
概述: ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是项目,总有异常发生,本节就来谈谈API的异常 ...
- 【Java每日一题】20161107
package Nov2016; import java.util.List; public class Ques1107 { public static void main(String[] arg ...
- 项目总结笔记系列 wsTax KT Session1
项目总结笔记 1.专有名词解释: SMO, Separate Management Office. UAT, User Accept Test. GSLB, Global Server Load B ...
- ActiveMQ消息队列介绍
ActiveMQ是一个开源兼容Java Message Service (JMS) 1.1面向消息的中件间. 来自Apache Software Foundation. ActiveMQ提供松耦合 ...
- 对datatable操作,查询
#region DataTable筛选,排序返回符合条件行组成的新DataTable或直接用DefaultView按条件返回 /// <summary> /// DataTable筛选,排 ...
- Date类型 方法
Date 方法函数 Date.parse():可以获得该日期的毫秒数 var now=Date.parse('May 25,2005')//1085414400000 Date.UTC():也可以获得 ...
- HTML5 学习笔记(五)——WebSocket与消息推送
B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链 ...