• 前言

参考博客

-

  本文中的所有内容大部分来源于网络资料,如有侵权请联系本人修改或删除,请大家多多支持原创!非常感谢!

WindowManagerService

Activity与Window相关概念

  • Activity只负责生命周期和事件处理
  • window只控制视图
  • 一个Activity包含一个Window,如果Activity没有Window,那就相当于Service
  • AMS统一调度所有应用程序的Activity
  • WMS控制所有Window的显示与隐藏以及要显示的位置

Window

  “Window” 表明它是和窗口相关的,”窗口“是一个抽象的概念,从用户的角度来讲,它是一个”界面“;从SurfaceFlinger的角度来看,它是一个Layer,承载着和界面有关的数据和属性;从WMS角度来看,它是一个WindowState,用于管理和界面有关的状态。

  • 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(点击事件由Window->DecorView->View;Activity的setContentView底层是通过Window完成)
  • Window是一个抽象类,具体实现是PhoneWindow
  • 创建Window需要通过WindowManager创建
  • WindowManager是外界访问Window的入口
  • Window具体实现位于WindowManagerService中
  • WindowManager和WindowMangerService的交互是通过IPC完成
  • 定义窗口样式和行为的抽象基类,用于作为顶层的view加到WindowManger中,其实现类是PhoneWindow。
  • 每个Window都需要指定一个Type(应用窗口、子窗口、系统窗口)。Activity对应的窗口是应用窗口;PopupWindow,ContextMenu,OptionMenu是常用的子窗口;像Toast和系统警告提示框(如ANR)就是系统窗口,还有很多应用的悬浮框也属于系统窗口类型。

WindowManager

  用来在应用与window之间的管理接口,管理窗口顺序,消息等

WindowManagerService

  简称WMS,我indowManagerService管理窗口的创建、更新和删除,显示顺序等,是WindowManager这个管理器的实现类。它运行在system_server进程,作为服务端,客户端(应用程序)通过IPC调用和它进行交互。

Token

  Token主要是指窗口令牌(Window Token),是一种特殊的Binder令牌,WMS用它唯一标识系统中的一个窗口。

Window的Type

  • 应用窗口:层级范围是1~99
  • 子窗口: 层级范围是1000~1999
  • 系统窗口:层级范围是2000~2999
  • 各级别Type值在WindowManager中的定义分别为(frameworks/base/core/java/android/view/WindowManager.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

/**
* Start of window types that represent normal application windows.
* 第一个应用窗口
*/
public static final int FIRST_APPLICATION_WINDOW = 1;

/**
* Window type: an application window that serves as the "base" window
* of the overall application; all other application windows will
* appear on top of it.
* In multiuser systems shows only on the owning user's window.
* 所有程序窗口的base窗口,其他应用程序窗口都显示在它上面
*/
public static final int TYPE_BASE_APPLICATION = 1;

/**
* Window type: a normal application window. The {@link #token} must be
* an Activity token identifying who the window belongs to.
* In multiuser systems shows only on the owning user's window.
* 所有程序窗口的Base窗口,只能配合Activity在当前App使用
*/
public static final int TYPE_APPLICATION = 2;

/**
* Window type: special application window that is displayed while the
* application is starting. Not for use by applications themselves;
* this is used by the system to display something until the
* application can show its own windows.
* In multiuser systems shows on all users' windows.
* 目标应用窗口未启动之前的那个窗口
*/
public static final int TYPE_APPLICATION_STARTING = 3;

/**
* Window type: a variation on TYPE_APPLICATION that ensures the window
* manager will wait for this window to be drawn before the app is shown.
* In multiuser systems shows only on the owning user's window.
*/
public static final int TYPE_DRAWN_APPLICATION = 4;

/**
* End of types of application windows.
* 最后一个应用窗口
*/
public static final int LAST_APPLICATION_WINDOW = 99;

/**
* Start of types of sub-windows. The {@link #token} of these windows
* must be set to the window they are attached to. These types of
* windows are kept next to their attached window in Z-order, and their
* coordinate space is relative to their attached window.
* 第一个子窗口
*/
public static final int FIRST_SUB_WINDOW = 1000;

/**
* Window type: a panel on top of an application window. These windows
* appear on top of their attached window.
* 面板窗口,显示于宿主窗口的上层,只能配合Activity在当前App使用
*/
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;

/**
* Window type: window for showing media (such as video). These windows
* are displayed behind their attached window.
* 媒体窗口(如视频),显示于宿主窗口下层
*/
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;

/**
* Window type: a sub-panel on top of an application window. These
* windows are displayed on top their attached window and any
* {@link #TYPE_APPLICATION_PANEL} panels.
* 应用程序窗口的子面板,只能配合Activity在当前APP使用(PopupWindow默认就是这个Type)
*/
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;

/** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout
* of the window happens as that of a top-level window, <em>not</em>
* as a child of its container.
* 对话框窗口,只能配合Activity在当前APP使用
*/
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;

/**
* Window type: window for showing overlays on top of media windows.
* These windows are displayed between TYPE_APPLICATION_MEDIA and the
* application window. They should be translucent to be useful. This
* is a big ugly hack so:
* @hide
*/
@UnsupportedAppUsage
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4;

/**
* Window type: a above sub-panel on top of an application window and it's
* sub-panel windows. These windows are displayed on top of their attached window
* and any {@link #TYPE_APPLICATION_SUB_PANEL} panels.
* @hide
*/
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;

/**
* End of types of sub-windows.
* 最后一个子窗口
*/
public static final int LAST_SUB_WINDOW = 1999;

/**
* Start of system-specific window types. These are not normally
* created by applications.
* 系统窗口,非应用程序创建
*/
public static final int FIRST_SYSTEM_WINDOW = 2000;

/**
* Window type: the status bar. There can be only one status bar
* window; it is placed at the top of the screen, and all other
* windows are shifted down so they are below it.
* In multiuser systems shows on all users' windows.
* 状态栏,只能有一个状态栏,位于屏幕顶端,其他窗口都位于它下方
*/
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;

/**
* Window type: the search bar. There can be only one search bar
* window; it is placed at the top of the screen.
* In multiuser systems shows on all users' windows.
* 搜索栏。只能有一个搜索栏,位于屏幕上方
*/
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;

/**
* Window type: phone. These are non-application windows providing
* user interaction with the phone (in particular incoming calls).
* These windows are normally placed above all applications, but behind
* the status bar.
* In multiuser systems shows on all users' windows.
* 电话窗口,它用于电话交互(特别是呼入),置于所有应用程序之上,状态栏之下,属于悬浮窗(并且给一个Activity的话按下HOME键会出现看不到桌面上的图标异常情况)
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;

/**
* Window type: system window, such as low power alert. These windows
* In multiuser systems shows only on the owning user's window.
* 系统警告提示窗口,出现在应用程序窗口之上,属于悬浮窗,但是会被禁止
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;

/**
* Window type: keyguard window.
* 锁屏窗口
* In multiuser systems shows on all users' windows.
* @removed
*/
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;

/**
* Window type: transient notifications.
* In multiuser systems shows only on the owning user's window.
* 信息窗口,用于显示Toast,不属于悬浮窗,但有悬浮窗的功能,缺点是在Andoid 2.3上无法接受点击事件
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;

/**
* Window type: system overlay windows, which need to be displayed
* on top of everything else. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows only on the owning user's window.
* 系统顶层窗口,显示在其他一切内容之上,此窗口不能获得输入焦点,否则影响锁屏
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;

/**
* Window type: priority phone UI, which needs to be displayed even if
* the keyguard is active. These windows must not take input
* focus, or they will interfere with the keyguard.
* In multiuser systems shows on all users' windows.
* 电话优先,当锁屏时显示,此窗口不能获得输入焦点,否则影响锁屏
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7;

/**
* Window type: panel that slides out from the status bar
* In multiuser systems shows on all users' windows.
* 系统对话框窗口
*/
public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8;

/**
* Window type: dialogs that the keyguard shows
* In multiuser systems shows on all users' windows.
* 锁屏时显示的对话框
*/
public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9;

/**
* Window type: internal system error windows, appear on top of
* everything they can.
* In multiuser systems shows only on the owning user's window.
* 系统内部错误提示,显示在任何窗口之上
* @deprecated for non-system apps. Use {@link #TYPE_APPLICATION_OVERLAY} instead.
*/
@Deprecated
public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10;

/**
* Window type: internal input methods windows, which appear above
* the normal UI. Application windows may be resized or panned to keep
* the input focus visible while this window is displayed.
* 内部输入法窗口,显示于普通UI之上,应用程序可重新布局以免被此窗口覆盖
* In multiuser systems shows only on the owning user's window.
*/
public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11;

/**
* Window type: internal input methods dialog windows, which appear above
* the current input method window.
* In multiuser systems shows only on the owning user's window.
* 内部输入法对话框,显示于当前输入法窗口之上
*/
public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;

/**
* Window type: wallpaper window, placed behind any window that wants
* to sit on top of the wallpaper.
* In multiuser systems shows only on the owning user's window.
* 墙纸窗口
*/
public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13;

/**
* Window type: panel that slides out from over the status bar
* In multiuser systems shows on all users' windows.
* 状态栏的滑动面板
* @removed
*/
public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14;

/**
* Window type: secure system overlay windows, which need to be displayed
* on top of everything else. These windows must not take input
* focus, or they will interfere with the keyguard.
*
* This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the
* system itself is allowed to create these overlays. Applications cannot
* obtain permission to create secure system overlays.
*
* In multiuser systems shows only on the owning user's window.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;

/**
* Window type: the drag-and-drop pseudowindow. There is only one
* drag layer (at most), and it is placed on top of all other windows.
* In multiuser systems shows only on the owning user's window.
* @hide
*/
public static final int TYPE_DRAG = FIRST_SYSTEM_WINDOW+16;

/**
* Window type: panel that slides out from over the status bar
* In multiuser systems shows on all users' windows. These windows
* are displayed on top of the stauts bar and any {@link #TYPE_STATUS_BAR_PANEL}
* windows.
* @hide
*/
public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;

/**
* Window type: (mouse) pointer
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;

/**
* Window type: Navigation bar (when distinct from status bar)
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;

/**
* Window type: The volume level overlay/dialog shown when the user
* changes the system volume.
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;

/**
* Window type: The boot progress dialog, goes on top of everything
* in the world.
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;

/**
* Window type to consume input events when the systemUI bars are hidden.
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22;

/**
* Window type: Navigation bar panel (when navigation bar is distinct from status bar)
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;

/**
* Window type: Display overlay window. Used to simulate secondary display devices.
* In multiuser systems shows on all users' windows.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;

/**
* Window type: Magnification overlay window. Used to highlight the magnified
* portion of a display when accessibility magnification is enabled.
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;

/**
* Window type: Window for Presentation on top of private
* virtual display.
*/
public static final int TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30;

/**
* Window type: Windows in the voice interaction layer.
* @hide
*/
public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31;

/**
* Window type: Windows that are overlaid <em>only</em> by a connected {@link
* android.accessibilityservice.AccessibilityService} for interception of
* user interactions without changing the windows an accessibility service
* can introspect. In particular, an accessibility service can introspect
* only windows that a sighted user can interact with which is they can touch
* these windows or can type into these windows. For example, if there
* is a full screen accessibility overlay that is touchable, the windows
* below it will be introspectable by an accessibility service even though
* they are covered by a touchable window.
*/
public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;

/**
* Window type: Starting window for voice interaction layer.
* @hide
*/
public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;

/**
* Window for displaying a handle used for resizing docked stacks. This window is owned
* by the system process.
* @hide
*/
public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34;

/**
* Window type: like {@link #TYPE_APPLICATION_ATTACHED_DIALOG}, but used
* by Quick Settings Tiles.
* @hide
*/
public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;

/**
* Window type: shows directly above the keyguard. The layer is
* reserved for screenshot animation, region selection and UI.
* In multiuser systems shows only on the owning user's window.
* @hide
*/
public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;

/**
* Window type: Window for Presentation on an external display.
* @see android.app.Presentation
* @hide
*/
public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37;

/**
* Window type: Application overlay windows are displayed above all activity windows
* (types between {@link #FIRST_APPLICATION_WINDOW} and {@link #LAST_APPLICATION_WINDOW})
* but below critical system windows like the status bar or IME.
* <p>
* The system may change the position, size, or visibility of these windows at anytime
* to reduce visual clutter to the user and also manage resources.
* <p>
* Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission.
* <p>
* The system will adjust the importance of processes with this window type to reduce the
* chance of the low-memory-killer killing them.
* <p>
* In multi-user systems shows only on the owning user's screen.
*/
public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;

/**
* Window type: Window for adding accessibility window magnification above other windows.
* This will place the window in the overlay windows.
* @hide
*/
public static final int TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39;

/**
* Window type: the notification shade and keyguard. There can be only one status bar
* window; it is placed at the top of the screen, and all other
* windows are shifted down so they are below it.
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40;

/**
* Window type: used to show the status bar in non conventional parts of the screen (i.e.
* the left or the bottom of the screen).
* In multiuser systems shows on all users' windows.
* @hide
*/
public static final int TYPE_STATUS_BAR_ADDITIONAL = FIRST_SYSTEM_WINDOW + 41;

/**
* End of types of system windows.
* 最后一个系统窗口
*/
public static final int LAST_SYSTEM_WINDOW = 2999;

/**
* @hide
* Used internally when there is no suitable type available.
*/
public static final int INVALID_WINDOW_TYPE = -1;

Activity窗口管理服务WindowManagerService计算Activity窗口大小的过程分析

  在Android系统中,Activity窗口的大小是由WindowManagerService服务来计算的。WindowManagerService服务会根据屏幕及其装饰区的大小来决定Activity窗口的大小。一个Activity窗口只有知道自己的大小之后,才能对它里面的UI元素进行测量、布局以及绘制。

  一般来说,Activity窗口的大小等于整个屏幕的大小,但是它并不占据着整块屏幕。为了理解这一点,我们首先分析一下Activity窗口的区域是如何划分的。Activity窗口的上方一般会有一个状态栏,用来显示3G信号、电量使用等图标。

  从Activity窗口剔除状态栏所占用的区域之后,所得到的区域就称为内容区域(Content Region)。顾名思义,内容区域就是用来显示Activity窗口的内容的。

Activity窗口大小的计算过程

  这个过程可以分为11个步骤

  • Step 1. ViewRoot.performTraversals

  这个函数定义在文件在