【Android】图文解密Android(安卓)WindowManagerService
文章目录
- 1、简介
- 2、启动
- 3、addView
- 4、Layer
- 5、WindowState
- 6、WindowToken
- 7、Session
- 8、Surface
1、简介
WindowManagerService(WMS)是Android中很重要的一个服务,主要的职责是与ActivityManagerService(AMS)交互以管理Window,与InputManagerService(IMS)交互以派发事件。分析WMS,先从下面的类图开始吧,看看相关的类都有哪些,主要的类包括WindowManagerService、WindowManagerImpl、PhoneWindowManager、WindowManagerGlobal、ViewRootImpl等。
2、启动
WMS是在SystemServer中启动的,下面的时序图展示了WMS及AMS、IMS的启动过程,以及它们是如何建立联系的。
3、addView
addView是一个常用的方法,流程图如下。从WindowManagerImpl开始,经WindowManagerGlobal、ViewRootImpl、Session,最后到WindowManagerService结束。在WMS的addWindow中,首先要检查权限,然后通过WindowToken、WindowState完成。
4、Layer
Window有三种类型,Application Window、Sub Window和System Window,这些Window有不同的Type,用int表示, Application Window从1到99,Sub Window从1000到1999,System Window从2000到2999,它们在WindowManager中定义,代码如下所示。
public static final int FIRST_APPLICATION_WINDOW = 1; public static final int TYPE_BASE_APPLICATION = 1; public static final int TYPE_APPLICATION = 2; public static final int TYPE_APPLICATION_STARTING = 3; public static final int TYPE_DRAWN_APPLICATION = 4; public static final int LAST_APPLICATION_WINDOW = 99; public static final int FIRST_SUB_WINDOW = 1000; public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW; public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1; public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2; public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3; public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4; public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5; public static final int LAST_SUB_WINDOW = 1999; public static final int FIRST_SYSTEM_WINDOW = 2000; public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3; public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6; public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7; public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8; public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9; public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10; public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11; public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12; public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13; public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14; public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15; public static final int TYPE_DRAG = FIRST_SYSTEM_WINDOW+16; public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17; public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18; public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19; public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20; public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21; public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22; public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23; public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24; public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26; public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27; public static final int TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30; public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31; public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32; public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33; public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34; public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35; public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36; public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37; public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38; public static final int LAST_SYSTEM_WINDOW = 2999;
Window都有自己的Layer,即z-order,表示在屏幕上显示的层级顺序。Application Window都属于Application Layer,值为2,其它的则不同,它们在WindowManagerPolicy可以找到,代码如下。
int APPLICATION_LAYER = 2; int APPLICATION_MEDIA_SUBLAYER = -2; int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; int APPLICATION_PANEL_SUBLAYER = 1; int APPLICATION_SUB_PANEL_SUBLAYER = 2; int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3; default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) { if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { return APPLICATION_LAYER; } switch (type) { case TYPE_WALLPAPER: // wallpaper is at the bottom, though the window manager may move it. return 1; case TYPE_PRESENTATION: case TYPE_PRIVATE_PRESENTATION: return APPLICATION_LAYER; case TYPE_DOCK_DIVIDER: return APPLICATION_LAYER; case TYPE_QS_DIALOG: return APPLICATION_LAYER; 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_SYSTEM_ALERT: // like the ANR / app crashed dialogs return canAddInternalSystemWindow ? 11 : 10; case TYPE_APPLICATION_OVERLAY: return 12; case TYPE_DREAM: // used for Dreams (screensavers with TYPE_DREAM windows) return 13; case TYPE_INPUT_METHOD: // on-screen keyboards and other such input method user interfaces go here. return 14; case TYPE_INPUT_METHOD_DIALOG: // on-screen keyboards and other such input method user interfaces go here. return 15; case TYPE_STATUS_BAR_SUB_PANEL: return 17; case TYPE_STATUS_BAR: return 18; case TYPE_STATUS_BAR_PANEL: return 19; case TYPE_KEYGUARD_DIALOG: return 20; case TYPE_VOLUME_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume return 21; case TYPE_SYSTEM_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume return canAddInternalSystemWindow ? 22 : 11; case TYPE_NAVIGATION_BAR: // the navigation bar, if available, shows atop most things return 23; case TYPE_NAVIGATION_BAR_PANEL: // some panels (e.g. search) need to show on top of the navigation bar return 24; case TYPE_SCREENSHOT: // screenshot selection layer shouldn't go above system error, but it should cover // navigation bars at the very least. return 25; case TYPE_SYSTEM_ERROR: // system-level error dialogs return canAddInternalSystemWindow ? 26 : 10; case TYPE_MAGNIFICATION_OVERLAY: // used to highlight the magnified portion of a display return 27; case TYPE_DISPLAY_OVERLAY: // used to simulate secondary display devices return 28; case TYPE_DRAG: // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows return 29; case TYPE_ACCESSIBILITY_OVERLAY: // overlay put by accessibility services to intercept user interaction return 30; case TYPE_SECURE_SYSTEM_OVERLAY: return 31; case TYPE_BOOT_PROGRESS: return 32; case TYPE_POINTER: // the (mouse) pointer layer return 33; default: Slog.e("WindowManager", "Unknown window type: " + type); return APPLICATION_LAYER; } } default int getSubWindowLayerFromTypeLw(int type) { switch (type) { case TYPE_APPLICATION_PANEL: case TYPE_APPLICATION_ATTACHED_DIALOG: return APPLICATION_PANEL_SUBLAYER; case TYPE_APPLICATION_MEDIA: return APPLICATION_MEDIA_SUBLAYER; case TYPE_APPLICATION_MEDIA_OVERLAY: return APPLICATION_MEDIA_OVERLAY_SUBLAYER; case TYPE_APPLICATION_SUB_PANEL: return APPLICATION_SUB_PANEL_SUBLAYER; case TYPE_APPLICATION_ABOVE_SUB_PANEL: return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER; } Slog.e("WindowManager", "Unknown sub-window type: " + type); return 0; }
Window的Layer,上面只是从1开始逐个递增1,在转换为z-order时,还要进行转换,首先乘10000,然后偏移1000,同类的Window逐个递增5,这些值在WindowManagerService中定义,代码如下所示。
/** How much to multiply the policy's type layer, to reserve room * for multiple windows of the same type and Z-ordering adjustment * with TYPE_LAYER_OFFSET. */ static final int TYPE_LAYER_MULTIPLIER = 10000; /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above * or below others in the same layer. */ static final int TYPE_LAYER_OFFSET = 1000; /** How much to increment the layer for each window, to reserve room * for effect surfaces between them. */ static final int WINDOW_LAYER_MULTIPLIER = 5;
Java层与Native层的Layer设置是通过SurfaceControl的setLayer完成的,在Native层由SurfaceComposer进行合成。
5、WindowState
WindowState是Android中的事实Window,WindowManager真正管理的是WindowState而不是Window。WindowState在WindowManagerService中创建,从上面的addView的时序图中可以看出。创建WindowState之后,还需要设置上文提到的Window Layer,通过InputChannel与IMS取得联系,将Session中维护的Window个数加1,最后通过WindowToken将这个WindowState添加到WindowContainer中。
6、WindowToken
WindowToken是个容器,将相关的WindowState收集到一起,同样是在WindowManagerService中创建。真正的token是IBinder类型的成员变量token,用于IPC。WindowToken有个子类AppWindowToken,用于Application和Activity。
7、Session
Session是个客户端对象,每个进程只有一个,与WindowManagerService进行交互。Session对应的interface为IWindowSession,在WindowManagerGlobal中实例化。
8、Surface
View或Window真正地是在一个Surface上进行描画的,Surface即一个Buffer,由辅助类SurfaceControl进行控制,上文提到的Window Layer的设置就是由SurfaceControl与Native层进行交互的。
更多相关文章
- .Net 转战 Android(安卓)4.4 日常笔记(10)--PullToRefresh下拉刷新
- 【android】与pc机进行UDP通信
- Android使用ADB启动应用程序
- Android(安卓)SDK下载和更新失败的解决方法!!!
- Android: 自定义Tab样式
- android 显示特殊符号
- Android(安卓)Custom Dialog错误Unable to add window -- token
- Android正确关闭线程
- ubuntu 下 配置 Android(安卓)NDK开发环境