WMS 全名是 WindowManagerService,它是客户端 APP 的管理者,处于 SystemServe r 进程,WMS 主要负责管理几件事情
窗口管理
负责 Window 添加、更新、删除,核心管理成员有 DisplayContent
、WindowToken
、WindowState
窗口动画
Window 切换时,可以添加动画,让 Window 切换时更加自然,动画由 WMS 的动画子系统负责,该系统是 WindowAnimator
输入系统的中转
当使用者对视窗触控 or 输入时,都会触发 InputManagerService 会对触摸事件进行处理,将事件通过 WMS 传递到合适的窗口进行处理(这时 WMS 就是 中转站)
Surface 管理
WMS 并不具备 Window 绘制的功能,每个 Window 都有一个 Surface 来绘制,而 WMS 负责 Surface 的分配
WMS 启动 - SystemServer#
WMS 是就是 WindowManagerService,它是系统服务,说到系统服务自然就会想到 SystemServer,那就让我们来看看 WMS 是如何被 SystemServer 唤起的
SystemServer 透过 WMS#main
方法启动
把 WMS 以Context#WINDOW_SERVICE
(window)设定到 ServiceManager 中
把启动的 WMS 对象设定给 AMS 服务
// SystemServer.java
private void run() {
... 省略部分
// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
// WMS 是在 OtherServices 启动
startOtherServices(t);
} catch (Throwable ex) {
... 省略 Log
throw ex;
} /* 省略 finally */
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分
try {
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
// 1. 启动 WMS
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 2. 对 ServiceManager 添加服务 "window"
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();
// 3. 与 AMS 产生关系
t.traceBegin("SetWindowManagerService");
mActivityManagerService.setWindowManager(wm);
t.traceEnd();
} /* 省略 catch */
}
在 WMS 启动后会透过 onInitReady
、displayReady
、systemReady
来完成 WMS 的后续动作(这些方法之后会介绍)
// SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分
try {
// 初始化准备
wm.onInitReady();
... 省略部分
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
wm.systemReady();
} /* 省略 catch */
}
WMS - main 函数#
透过 DisplayThread 中的 Handler#runWithScissors
创建 WMS 对象(也就是创建 WMS 的线程与 SystemServer 线程不同)
Handler#runWithScissors
方法是透过锁来达成同步任务,保证该 Runnable 会先被 DisplayThread 的 Looper 先执行,执行完后才回到 SystemServer 的 Thread
// WindowManagerService.java
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
// @ 查看 main 方法
return main(context, im, showBootMsgs, onlyCore, policy, atm,
new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
SurfaceControl.Builder::new);
}
@VisibleForTesting
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, ... 省略部分參數) {
// 创建新 Thread
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
surfaceControlFactory), 0);
// 执行完 runWithScissors 中的 Runnable 任务后才返回
return sInstance;
}
HandlerThread - 创建 Looper#
// HandlerThread.java
public class HandlerThread extends Thread {
... 省略部分方法
@Override
public void run() {
mTid = Process.myTid();
// 准备该 Thread 专用的 Looper & MessageQueue 对象
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
// 通知所有等待的 Thread,Looper 已经创建完成
notifyAll();
}
Process.setThreadPriority(mPriority);
// Looper 准备好
onLooperPrepared();
// 准备开始运行 Loop 不断循环处理 Message 任务
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) { // 以当前对象作为锁
while (isAlive() && mLooper == null) {
try {
wait(); // 直到 Looper 创建
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
// 在需要时才创建(但线程不安全)
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
}
DisplayThread - 创建 WMS 对象#
WMS 就是在 DisplayThread 类中被启动,DisplayThread 可以说是 WMS 的 MainThread
DisplayThread 可以创建安全 Handler,其主要功能是:处理 低延迟显示 的相关操作,并只能由 WindowManager、DisplayManager、InputManager 执行快速操作
从上面可以看到 DisplayThread 继承于 ServiceThread(而它继承于 HandlerThread),所以 它会在执行 run 方法时自动创建 Looper 对象,鉴于 HandlerThread 创建的 Handler 并不安全,所以 DisplayThread 这里自己创建 Handler(使用类锁)
// DisplayThread.java
public final class DisplayThread extends ServiceThread {
private static DisplayThread sInstance;
private static Handler sHandler;
// 單例模式
private DisplayThread() {
// DisplayThread runs important stuff, but these are not as important as things running in
// AnimationThread. Thus, set the priority to one lower.
super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new DisplayThread();
sInstance.start();
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
sHandler = new Handler(sInstance.getLooper());
}
}
public static DisplayThread get() {
// 类锁
synchronized (DisplayThread.class) {
// 创建 DisplayThread 对象
ensureThreadLocked();
return sInstance;
}
}
// 透过 DisplayThread.class 类锁来达成安全创建
public static Handler getHandler() {
// 类锁
synchronized (DisplayThread.class) {
// 创建 DisplayThread 对象
ensureThreadLocked();
return sHandler;
}
}
}
传递事件给 WMS 有两种方式
直接呼叫 WMS function,即时传送
// WindowManagerService.java
@Override
public boolean isKeyguardLocked() {
// mPolicy 类型 WindowManagerPolicy
return mPolicy.isKeyguardLocked();
}
透过 DisplayThread 的 Looper 将事件丢入 WMS Thread(DisplayThread)中
// WindowManagerService.java
final H mH = new H();
final class H extends android.os.Handler {
...
}
@Override
public void setAnimationScale(int which, float scale) {
if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
"setAnimationScale()")) {
throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
}
scale = fixScale(scale);
switch (which) {
case 0: mWindowAnimationScaleSetting = scale; break;
case 1: mTransitionAnimationScaleSetting = scale; break;
case 2: mAnimatorDurationScaleSetting = scale; break;
}
// Persist setting
mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
}
UiThread 类#
UiThread 与 DisplayThread 差不多,但多添加了一个 dispose
方法,来停止 Looper,并结束该对象(置为 null),在 initPolicy()
、systemReady()
会使用到
// UiThread.java
public final class UiThread extends ServiceThread {
private static final long SLOW_DISPATCH_THRESHOLD_MS = 100;
private static final long SLOW_DELIVERY_THRESHOLD_MS = 200;
private static UiThread sInstance;
private static Handler sHandler;
private UiThread() {
super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
}
@Override
public void run() {
// Make sure UiThread is in the fg stune boost group
Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
super.run();
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new UiThread();
sInstance.start();
final Looper looper = sInstance.getLooper();
looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
looper.setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
sHandler = new Handler(sInstance.getLooper());
}
}
public static UiThread get() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (UiThread.class) {
ensureThreadLocked();
return sHandler;
}
}
/**
* Disposes current ui thread if it's initialized. Should only be used in tests to set up a
* new environment.
*/
@VisibleForTesting
public static void dispose() {
synchronized (UiThread.class) {
if (sInstance == null) {
return;
}
// 执行完 runWithScissors 才会往下执行
getHandler().runWithScissors(sInstance::quit, 0 /* timeout */);
sInstance = null;
}
}
}
AnimationThread 类#
AnimationThread 与 DisplayThread 差不多,但多添加了一个 dispose 方法,来停止 Looper,并结束该对象(置为 null)
// AnimationThread.java
public final class AnimationThread extends ServiceThread {
private static AnimationThread sInstance;
private static Handler sHandler;
private AnimationThread() {
super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
}
private static void ensureThreadLocked() {
if (sInstance == null) {
sInstance = new AnimationThread();
sInstance.start();
sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
public static AnimationThread get() {
synchronized (AnimationThread.class) {
ensureThreadLocked();
return sInstance;
}
}
public static Handler getHandler() {
synchronized (AnimationThread.class) {
ensureThreadLocked();
return sHandler;
}
}
// 使用到 HandlerThread#quit 方法,停止 Looper
@VisibleForTesting
public static void dispose() {
synchronized (AnimationThread.class) {
if (sInstance == null) {
return;
}
getHandler().runWithScissors(() -> sInstance.quit(), 0 /* timeout */);
sInstance = null;
}
}
}
SystemServer - WMS 启动后续#
// SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
... 省略部分
try {
// 初始化准备
wm.onInitReady();
... 省略部分
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
wm.systemReady();
} /* 省略 catch */
}
WMS 创建#
前面有提到 WindowManagerService#main
方法会透过 DisplayThread(Thread)创建 WMS 的实例,在这里就会创建 H 类,而它的 Looper 就是当前 Thread 也就是 DisplayThread
// WindowManagerService.java
// 当没有指定 Looper 就会依现在 Thread 的 Looper
final H mH = new H(); // 也就是 DisplayThread 的 Looper
WindowManagerPolicy mPolicy;
final WindowAnimator mAnimator;
RootWindowContainer mRoot;
final class H extends android.os.Handler {
...
}
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, DisplayWindowSettingsProvider
displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
... 省略部分
// WMS 持有 InputManagerService 引用
mInputManager = inputManager;
...
// 取得 DisplayManagerService 代理
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mPolicy = policy; // SystemServer 传进来的实例是PhoneWindowManager类
// 取得 WMS 代理
mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
// Window 动画
mAnimator = new WindowAnimator(this);
// 所有 Window 的根节点 (RootWindowContainer 对象)
mRoot = new RootWindowContainer(this);
}
WMS#onInitReady
- 初始化 WindowManagerPolicy#
WMS#onInitReady
函数:取得 UiThread (另外一个 Thread) 的 Handler,并初始化 WindowManagerPolicy 实作呼叫 PhoneWindowManager#init 函数)
// WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
WindowManagerPolicy mPolicy; // 实作是 PhoneWindowManager 类
public void onInitReady() {
// @重点分析 initPolicy 函数
initPolicy();
... 省略部分
}
private void initPolicy() {
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
}
}
// ---------------------------------------------
// WindowManagerPolicy.java
public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
... 省略部分
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs);
// ----------------------------------------------
// PhoneWindowManager.java
public class PhoneWindowManager implements WindowManagerPolicy {
... 省略部分
private class PolicyHandler extends Handler {
... 省略部分
}
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
// 省略部分…后面介绍
mHandler = new PolicyHandler(); // 该 Handler 使用 UiThread's Looper
}
}
WMS#displayReady
- 准备显示#
标示 WindowAnimator 初始化完成
重新配置设定,保证 DisplayWindowSettings 设定都有被正常使用
透过 ActivityTaskManager 来更新设置
// WindowManagerService.java
WindowManagerPolicy mPolicy;
final WindowAnimator mAnimator;
// 在 WMS construct 被初始化
RootWindowContainer mRoot;
public void displayReady() {
synchronized (mGlobalLock) { // ActivityTaskManagerService 中的對象
if (mMaxUiWidth > 0) {
mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
}
applyForcedPropertiesForDefaultDisplay();
// 1. 标识初始化完成
mAnimator.ready();
mDisplayReady = true;
// Reconfigure all displays to make sure that forced properties and
// DisplayWindowSettings are applied.
// 2. 重新配置设定,保证 DisplayWindowSettings 设定都有被正常使用
mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
// 硬件是否是可触控屏幕
mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TOUCHSCREEN);
// 硬件是否是假的可触控屏幕
mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_FAKETOUCH);
}
try {
// 3. 透过 ActivityTaskManager 来更新设置
mActivityTaskManager.updateConfiguration(null);
} catch (RemoteException e) {
}
}
WMS#systemReady
- 服务准备完成#
// WindowManagerService.java
public void systemReady() {
mSystemReady = true;
mPolicy.systemReady();
mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
mTaskSnapshotController.systemReady();
mHasWideColorGamutSupport = queryWideColorGamutSupport();
mHasHdrSupport = queryHdrSupport();
mPrimaryDisplayOrientation = queryPrimaryDisplayOrientation();
mPrimaryDisplayPhysicalAddress =
DisplayAddress.fromPhysicalDisplayId(SurfaceControl.getPrimaryPhysicalDisplayId());
UiThread.getHandler().post(mSettingsObserver::loadSettings);
IVrManager vrManager = IVrManager.Stub.asInterface(
ServiceManager.getService(Context.VR_SERVICE));
if (vrManager != null) {
try {
final boolean vrModeEnabled = vrManager.getVrModeState();
synchronized (mGlobalLock) {
vrManager.registerListener(mVrStateCallbacks);
if (vrModeEnabled) {
mVrModeEnabled = vrModeEnabled;
mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
}
}
} catch (RemoteException e) {
// Ignore, we cannot do anything if we failed to register VR mode listener
}
}
}
WMS 重点#
窗口属性 - Layer Type#
Android 支持多种窗口,并且会将窗口分为三类,定义在 WindowManager#LayoutParams中
Application Window:普通 App 应用就是使用以下窗口类型(列出几种举例),区间为 1 ~ 99 之间
Value | 名称 | 说明 |
---|---|---|
1 | FIRST_APPLICATION_WINDOW | 应用类视窗的起始值 |
1 | TYPE_BASE_APPLICATION | 其他应用都可覆盖在该 Window 之上 |
2 | TYPE_APPLICATION | 一般的应用窗口 |
3 | TYPE_APPLICATION_STARTING | 应用程序启动前的画面(用在加载某个画面之前的预前画面) |
4 | TYPE_DRAWN_APPLICATION | 在绘画完成前等待 |
99 | LAST_APPLICATION_WINDOW | 应用视窗的结束值 |
Sub Window:附加在应用之上的视窗,一般称为 子窗口,其值区间为 1000 ~ 1999 之间
Value | 名称 | 说明 |
---|---|---|
1000 | FIRST_SUB_WINDOW | SubWindow 的起始值 |
1000 | TYPE_APPLICATION_PANEL | 该 SubWindow 显示在依附的 App 之上 |
1001 | TYPE_APPLICATION_MEDIA | 显示有关 video 的 SubWindow |
1002 | TYPE_APPLICATION_SUB_PANEL | 显示在依附的 app 之上,也在其他 SubWinow 之上 |
1003 | TYPE_APPLICATION_ATTACHED_DIALOG | Dialog 类型的 Window |
1004 | TYPE_APPLICATION_MEDIA_OVERLAY | 显示在 TYPE_APPLICATION_MEDIA 还有底下的应用视窗之间 |
1005 | TYPE_APPLICATION_ABOVE_SUB_PANEL | 比 TYPE_APPLICATION_SUB_PANEL 更上层的 Window |
1999 | LAST_SUB_WINDOW | SubWindow 的结束值 |
System Window:系统使用的 Window 视窗(以下列出几种),区间为 2000 ~ 2999 之间
Value | 名称 | 说明 |
---|---|---|
2000 | FIRST_SYSTEM_WINDOW | System Window 的起始值 |
2001 | TYPE_STATUS_BAR | Status bar 的 Window |
2002 | TYPE_SEARCH_BAR | 搜寻 Bar 的 Window |
2038 | TYPE_APPLICATION_OVERLAY | 覆盖于其他 Activity 视窗 |
2999 | LAST_SYSTEM_WINDOW | System Window 的结束值 |
WindowState 初始化 - 决定 Base Layer#
从 WindState 构造函数可以知道,Base Laye r 数值可以从WindowManagerPolicy#getWindowLayerLw
方法取得
// WindowManagerPolicyConstants.java
// 保留給多 Window (相同 Layer)
int TYPE_LAYER_MULTIPLIER = 10000;
// 保留給多 Window (相同 Layer),Z 轴偏移量
int TYPE_LAYER_OFFSET = 1000
// ---------------------------------------------------------------
// WindowState.java
final WindowManagerPolicy mPolicy;
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, WindowManager.LayoutParams a,
... 省略部分入參) {
// 复制 `WindowManager.LayoutParams`
mAttrs.copyFrom(a);
...
mPolicy = mWmService.mPolicy;
...
// 判断目前 Window 是否是 SubWindow
if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
// 保留空间给多个相同 Layer 等级的 Window
// @ 查看 getWindowLayerLw 方法
mBaseLayer = mPolicy.getWindowLayerLw(parentWindow) // 1.
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; // 2.
// SubWindow
mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
...
} else {
// @ 查看 getWindowLayerLw 方法
mBaseLayer = mPolicy.getWindowLayerLw(this)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = 0;
...
}
}
WindowManagerPolicy 透过传入的 WindowState
决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)
// WindowManagerPolicy.java
default int getWindowLayerLw(WindowState win) {
return getWindowLayerFromTypeLw(win.getBaseType(), win.canAddInternalSystemWindow());
}
default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow,
false /* roundedCornerOverlay */);
}
default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
boolean roundedCornerOverlay) {
// Always put the rounded corner layer to the top most.
if (roundedCornerOverlay && canAddInternalSystemWindow) {
return getMaxWindowLayer();
}
// 1 ~ 99 之间
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return APPLICATION_LAYER; // APPLICATION_LAYER 是 2
}
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:
case TYPE_DOCK_DIVIDER:
case TYPE_QS_DIALOG:
case TYPE_PHONE:
return 3;
case TYPE_SEARCH_BAR:
return 4;
case TYPE_INPUT_CONSUMER:
return 5;
case TYPE_SYSTEM_DIALOG:
return 6;
case TYPE_TOAST:
// toasts and the plugged-in battery thing
return 7;
case TYPE_PRIORITY_PHONE:
// SIM errors and unlock. Not sure if this really should be in a high layer.
return 8;
case TYPE_SYSTEM_ALERT:
// like the ANR / app crashed dialogs
// Type is deprecated for non-system apps. For system apps, this type should be
// in a higher layer than TYPE_APPLICATION_OVERLAY.
return canAddInternalSystemWindow ? 12 : 9;
case TYPE_APPLICATION_OVERLAY:
return 11;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 14;
case TYPE_STATUS_BAR:
return 15;
... 省略部分 case
default:
Slog.e("WindowManager", "Unknown window type: " + type);
return 3;
}
}
透过传入的WindowState
决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)
WindowManagerPolicy#getSubWindowLayerFromTypeLw
方法:决定子窗口在父窗口中的偏移量
// WindowManagerPolicy.java
default int getSubWindowLayerFromTypeLw(int type) {
switch (type) {
case TYPE_APPLICATION_PANEL:
case TYPE_APPLICATION_ATTACHED_DIALOG:
return APPLICATION_PANEL_SUBLAYER; // 1
case TYPE_APPLICATION_MEDIA:
return APPLICATION_MEDIA_SUBLAYER; // -2
case TYPE_APPLICATION_MEDIA_OVERLAY:
return APPLICATION_MEDIA_OVERLAY_SUBLAYER; // -1
case TYPE_APPLICATION_SUB_PANEL:
return APPLICATION_SUB_PANEL_SUBLAYER; // 2
case TYPE_APPLICATION_ABOVE_SUB_PANEL:
return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER; // 3
}
Slog.e("WindowManager", "Unknown sub-window type: " + type);
return 0;
}
窗口属性 - LayoutParams#
Window 的统一属性设定在 WindowManager#LayoutParams中,并且有分为 type
、Flags
两种设定
Type:上面已经说过,主要有分为 Application Window
、Sub Window
、System Window
三种
Flag:莫认为 0,以下列出几个(有满多的)
Value | Flag | 说明 |
---|---|---|
0x00000001 | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | 只要该窗口可见,就允许锁住屏幕(可配合 FLAG_KEEP_SCREEN_ON 使用) |
0x00000002 | FLAG_DIM_BEHIND | 窗口后的 Window 都变淡 |
0x00000004 | FLAG_BLUR_BEHIND | 窗口后的 Window 变模糊 |
0x00000008 | FLAG_NOT_FOCUSABLE | 该 Window 视窗不可事件,事件会直接传递给后方 Window |
0x00000010 | FLAG_NOT_TOUCHABLE | 该窗口不接受任何事件 |
0x00000080 | FLAG_KEEP_SCREEN_ON | 只要该窗口可见,就保持屏幕亮起 |
System UI 控制:System UI 的设定定义在 View 中,针对每个 View 个别设置
Value | Flag | 说明 |
---|---|---|
0 | SYSTEM_UI_FLAG_VISIBLE | 设定 System UI 可见 |
0x00000002 | SYSTEM_UI_FLAG_HIDE_NAVIGATION | 设定 Navigtion Bar 不可见 |
0x00000004 | SYSTEM_UI_FLAG_FULLSCREEN | 屏幕全屏 |
0x00000100 | SYSTEM_UI_FLAG_LAYOUT_STABLE | 尽量保持 UI 布局的稳定性 |
0x00000400 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 从屏幕(0,0)开始绘制,也就是会从 Status Bar 开始绘制 |
WindowManagerService 简单理解起来是掌管该装置所有的 Window 的上下关系(z 轴的管理)、传输绘制任务到底层
变量 | 说明 | 补充 |
---|---|---|
mPolicy : WindowManagerPolicy | 定义一个窗口策略所须遵循的 通用规范,并提供了 WindowManger 特定的 UI 行为 | WindowManager 是 interface,它的实作是 PhoneWindowManager |
mSessions : ArraySet | 它主要用于进程通信,其他的应用进程的 View 想要和 WMS 通信,都要通过 Session 与 WMS 通信 | 每个应用程序是透过 WindowManagerGlobal 取得 Session |
mWindowMap : WindowHashMap | WindowHashMap 继承 HashMap,用来保存所有 ViewImpl;Key: IBinder、Value: WindowState | Key 其实是 IWindow(ViewRootImpl 的内部类 W)、Value 是保存窗口信息 |
mFinishedStarting : ArrayList | AppWindowToken 的父类是 WindowToken 当 APP 要向 WMS 申请一个新窗口时就要给予这个 token 让 WMS 验证 | 每个 Activity 对应一个 AppWindowToken(一个 AppWindowToken 管理多个 WindowToken 视窗) |
mResizingWindows : ArrayList | 用来存储正在调整大小的视窗 | |
mAnimator : WindowAnimator | 管理 Window 动画 & 特效 | |
mH : H | H 是 Handler 类型,它是属于 DisplayThread Looper | 将消息给 WMS |
mInputManager : InputManagerService | IMS 系统服务,当使用者有输入讯息时,WMS 会给予一个适合的视窗 |