前言
在 Android 系统中,WindowToken(窗口令牌) 和 WindowState(窗口状态)是两个重要的类,用于管理窗口视图的显示和布局。
WindowToken用于标识窗口中的视图层级,而WindowState用于管理窗口的状态和属性。这两个类在 Android 系统中起着重要的作用,帮助确保应用程序界面正确地显示和布局,只有认识了这两个类我们才能更好的理解WindowManagerService这个服务。
一、WindowToken(窗口令牌)
1、介绍
- WindowToken主要用于标识Android系统中窗口中的特定视图层级,它代表了窗口中的一个视图层级的令牌。
- 在 Android 中,窗口是视图层级的容器,用于组织和管理应用程序界面中的不同元素。每个窗口都有一个关联的 WindowToken,用于标识该窗口中的视图层级。
- WindowToken 通常与窗口管理器一起使用,用于跟踪窗口的属性和状态,并确保正确地显示和管理窗口。
- 例如,当应用程序中有多个窗口(例如活动、对话框、弹出窗口等)时,每个窗口都有自己的 WindowToken,用于标识其包含的视图层级。
2、WindowToken这个类如下所示。
frameworks/base/services/core/java/com/android/server/wm/WindowToken.java
class WindowToken extends WindowContainer<WindowState> {
final IBinder token;
final int windowType;
final Bundle mOptions;
private final boolean mFromClientToken;
private boolean mClientVisible;
protected WindowToken(WindowManagerService service, IBinder _token, int type,
boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens) {
this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
false /* roundedCornerOverlay */, false /* fromClientToken */, null /* options */);
}
protected WindowToken(WindowManagerService service, IBinder _token, int type,
boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,
boolean roundedCornerOverlay, boolean fromClientToken, @Nullable Bundle options) {
super(service);
token = _token;
windowType = type;
mOptions = options;
mPersistOnEmpty = persistOnEmpty;
mOwnerCanManageAppTokens = ownerCanManageAppTokens;
mRoundedCornerOverlay = roundedCornerOverlay;
mFromClientToken = fromClientToken;
if (dc != null) {
dc.addWindowToken(token, this);
}
}
static class Builder {
private final WindowManagerService mService;
private final IBinder mToken;
@WindowType
private final int mType;
private boolean mPersistOnEmpty;
private DisplayContent mDisplayContent;
private boolean mOwnerCanManageAppTokens;
private boolean mRoundedCornerOverlay;
private boolean mFromClientToken;
@Nullable
private Bundle mOptions;
Builder(WindowManagerService service, IBinder token, int type) {
mService = service;
mToken = token;
mType = type;
}
/** @see WindowToken#mPersistOnEmpty */
Builder setPersistOnEmpty(boolean persistOnEmpty) {
mPersistOnEmpty = persistOnEmpty;
return this;
}
/** Sets the {@link DisplayContent} to be associated. */
Builder setDisplayContent(DisplayContent dc) {
mDisplayContent = dc;
return this;
}
/** @see WindowToken#mOwnerCanManageAppTokens */
Builder setOwnerCanManageAppTokens(boolean ownerCanManageAppTokens) {
mOwnerCanManageAppTokens = ownerCanManageAppTokens;
return this;
}
/** @see WindowToken#mRoundedCornerOverlay */
Builder setRoundedCornerOverlay(boolean roundedCornerOverlay) {
mRoundedCornerOverlay = roundedCornerOverlay;
return this;
}
/** @see WindowToken#mFromClientToken */
Builder setFromClientToken(boolean fromClientToken) {
mFromClientToken = fromClientToken;
return this;
}
/** @see WindowToken#mOptions */
Builder setOptions(Bundle options) {
mOptions = options;
return this;
}
WindowToken build() {
return new WindowToken(mService, mToken, mType, mPersistOnEmpty, mDisplayContent,
mOwnerCanManageAppTokens, mRoundedCornerOverlay, mFromClientToken, mOptions);
}
}
}
- WindowToken将属于同一个应用的组件窗口组织在一起。
所谓的应用组件可以是 Activity、InputMethod、Wallpaper以及Dream。在WMS对窗口的管理过程中,用 WindowToken指代一个应用组件。例如在进行窗口ZOrder排序时,属于同一个 WindowToken的窗口会被安排在一起,而且在其中定义的一些属性将会影响所有属于此WindowToken的窗口。这些都表明了属于同一个WindowToken的窗口之间的紧密联系。
- WindowToken具有令牌的作用,是对应用组件的行为进行规范管理的一个手段。
WindowToken由应用组件或其管理者负责向WMS声明并持有。结合Android 12系统源码_窗口管理(三)WindowManagerService对窗口的管理过程我们可以知道,应用组件在需要新的窗口时,必须提供WindowToken以表明自己的身份,并且窗口的类型必须与所持有的WindowToken类型一致。
3、既然应用组件在创建一个窗口时必须指定一个有效的WindowToken才行,那么 WindowToken究竟该如何声明呢?来看一下WMS的addWindowToken方法。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@Override
public void addWindowToken(@NonNull IBinder binder, int type, int displayId,
@Nullable Bundle options) {
//需要声明Token的调用者拥有MANAGE_APP_TOKENS的权限,否则直接抛出异常
if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
synchronized (mGlobalLock) {
final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
if (dc == null) {
ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add token: %s"
+ " for non-exiting displayId=%d", binder, displayId);
return;
}
WindowToken token = dc.getWindowToken(binder);
if (token != null) {
ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add binder token: %s"
+ " for already created window token: %s"
+ " displayId=%d", binder, token, displayId);
return;
}
if (type == TYPE_WALLPAPER) {//如果是壁纸类型,则创建壁纸窗口令牌
new WallpaperWindowToken(this, binder, true, dc,
true /* ownerCanManageAppTokens */, options);
} else {
//创建通用的窗口令牌
new WindowToken.Builder(this, binder, type)
.setDisplayContent(dc)
.setPersistOnEmpty(true)
.setOwnerCanManageAppTokens(true)
.setOptions(options)
.build();
}
}
}
}
二、WindowState(窗口状态)
1、介绍
- WindowState 是一个表示窗口状态的类。它用于跟踪窗口的属性和状态,以确保窗口正确地显示和布局。
- WindowState 包含了窗口的各种属性,如位置、大小、可见性等。通过管理这些属性,系统可以管理窗口的显示和布局。
- WindowState 还可以包含其他与窗口相关的信息,如焦点状态、输入事件处理等。
- 与 WindowToken 不同,WindowState 更专注于管理窗口的状态和属性,而不是标识窗口中的特定视图层级。