Framework 窗口添加流程分析2之 addWindow 流程
以下是 WindowManagerService.addWindow() 方法的一些大致流程:
- 添加窗口的权限检查
- Display、DisplayContent 的检查及创建
- 处理一些要窗口类型的判断及 WindowToken 的判断创建
- 创建 WindowState ,传入 wms、IWindow、WindowToken、parentWindow、LayoutParams等参数
- 在 DisplayPolicy 处理窗口的一些策略,如焦点处理,保存状态栏、导航栏实例等
- 注册一个输入通道 InputChannel,以便可以处理输入事件
- win.attach() :维护当前 wms 的 Sessions 列表,并未 Session 创建 SurfaceSession,用于与 Surface Flinger 的连接,可以从中创建一个或多个 Surface 实例,而这些 Surface 实例将被合成到屏幕上
- win.mToken.addWindow(win) : WindowToken 容器的关系维护,参考 WindowContainer.addChild()
- 处理窗口过渡动画的添加
- 处理屏幕显示边界计算
- 输入相关的处理
- 更新屏幕旋转方向以及一些显示器相关的配置
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState) {
int[] appOp = new int[1];
// 添加窗口的权限检查,主要交给 WindowManagerPolicy 处理,实现类是 PhoneWindowManager
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
return res;
}
boolean reportNewConfig = false;
WindowState parentWindow = null;
long origId;
final int callingUid = Binder.getCallingUid();
final int type = attrs.type;
synchronized (mGlobalLock) {
// frameworks/base/services/java/com/android/server/SystemServer.java
// SystemServer 在 startOtherServices() 中创建 wms, 依次调用 wm.onInitReady()、wm.displayReady()、wm.systemReady(), 其中在 wm.displayReady() 后 mDisplayReady 置为 true
if (!mDisplayReady) {
throw new IllegalStateException("Display has not been initialialized");
}
// 获取 DisplayContent
final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
if (displayContent == null) {
// 创建失败
Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
+ displayId + ". Aborting.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
if (!displayContent.hasAccess(session.mUid)) {
Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
+ "does not have access: " + displayId + ". Aborting.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
// 判断是否添加过该窗口, mWindowMap 保存已添加过的窗口
if (mWindowMap.containsKey(client.asBinder()<