WindowManagerService(WMS)是Android中很重要的一个服务,主要的职责是与ActivityManagerService(AMS)交互以管理Window,与InputManagerService(IMS)交互以派发事件。分析WMS,先从下面的类图开始吧,看看相关的类都有哪些,主要的类包括WindowManagerService、WindowManagerImpl、PhoneWindowManager、WindowManagerGlobal、ViewRootImpl等。
WMS是在SystemServer中启动的,下面的时序图展示了WMS及AMS、IMS的启动过程,以及它们是如何建立联系的。
addView是一个常用的方法,流程图如下。从WindowManagerImpl开始,经WindowManagerGlobal、ViewRootImpl、Session,最后到WindowManagerService结束。在WMS的addWindow中,首先要检查权限,然后通过WindowToken、WindowState完成。
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进行合成。
WindowState是Android中的事实Window,WindowManager真正管理的是WindowState而不是Window。WindowState在WindowManagerService中创建,从上面的addView的时序图中可以看出。创建WindowState之后,还需要设置上文提到的Window Layer,通过InputChannel与IMS取得联系,将Session中维护的Window个数加1,最后通过WindowToken将这个WindowState添加到WindowContainer中。
WindowToken是个容器,将相关的WindowState收集到一起,同样是在WindowManagerService中创建。真正的token是IBinder类型的成员变量token,用于IPC。WindowToken有个子类AppWindowToken,用于Application和Activity。
Session是个客户端对象,每个进程只有一个,与WindowManagerService进行交互。Session对应的interface为IWindowSession,在WindowManagerGlobal中实例化。
View或Window真正地是在一个Surface上进行描画的,Surface即一个Buffer,由辅助类SurfaceControl进行控制,上文提到的Window Layer的设置就是由SurfaceControl与Native层进行交互的。