我来分析应用进程的 WindowManager 如何调用到 WindowManagerService.addWindow() 的完整调用链,并绘制时序图。

应用进程 WindowManager 到 WindowManagerService.addWindow() 调用链分析

核心调用流程

sequenceDiagram
    participant App as 应用进程
    participant WMI as WindowManagerImpl
    participant WMG as WindowManagerGlobal
    participant VRI as ViewRootImpl
    participant Session as Session
    participant WMS as WindowManagerService
    
    App->>WMI: 1. addView(view, params)
    Note over WMI: applyTokens(params)
设置window token等 WMI->>WMG: 2. addView(view, params, display, parentWindow, userId) WMG->>WMG: 3. 参数验证和准备 Note over WMG: 检查view不为null
检查params类型
设置硬件加速标志 WMG->>VRI: 4. new ViewRootImpl(context, display) Note over VRI: 创建ViewRootImpl实例 WMG->>WMG: 5. 添加到全局数组 Note over WMG: mViews.add(view)
mRoots.add(root)
mParams.add(wparams) WMG->>VRI: 6. root.setView(view, wparams, panelParentView, userId) VRI->>VRI: 7. setView内部处理 Note over VRI: 设置mView, mAttrs
requestLayout()
创建InputChannel VRI->>Session: 8. mWindowSession.addToDisplayAsUser(...) Note over Session: 通过IWindowSession接口调用 Session->>WMS: 9. mService.addWindow(this, window, attrs, ...) Note over WMS: 最终到达目标方法 WMS->>WMS: 10. addWindow内部逻辑 Note over WMS: 权限检查
创建WindowState
添加到WindowManager

详细代码调用链

1. 应用调用 WindowManagerImpl.addView()

1
2
3
4
5
6
7
// WindowManagerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyTokens(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}

2. WindowManagerGlobal.addView() 处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
// 参数验证...
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;

// 创建ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);

// 添加到全局数组
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);

// 调用ViewRootImpl.setView()
root.setView(view, wparams, panelParentView, userId);
}

3. ViewRootImpl.setView() 核心处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
mWindowAttributes.copyFrom(attrs);

// 请求首次布局
requestLayout();

// 创建InputChannel
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();
}

// 调用Session.addToDisplayAsUser()
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibleTypes(), inputChannel, ...);
}
}
}

4. Session.addToDisplayAsUser() 代理

1
2
3
4
5
6
7
8
// Session.java
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, @InsetsType int requestedVisibleTypes,
InputChannel outInputChannel, ...) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
requestedVisibleTypes, outInputChannel, ...);
}

5. WindowManagerService.addWindow() 最终实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, @InsetsType int requestedVisibleTypes, ...) {

// 权限检查
int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName, appOp);

// 创建WindowState
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);

// 添加到WindowManager
win.mToken.addWindow(win);
displayPolicy.addWindowLw(win, attrs);
}

关键组件说明

WindowManagerGlobal

  • 全局单例,管理所有窗口
  • 维护 mViews、mRoots、mParams 三个数组
  • 负责创建 ViewRootImpl 实例

ViewRootImpl

  • 每个窗口的根视图容器
  • 负责窗口的布局、绘制、输入事件处理
  • 与 WindowManagerService 通信的桥梁

Session

  • WindowManagerService 为每个客户端进程创建的唯一会话
  • 封装了客户端与 WMS 之间的通信
  • 记录客户端进程信息(UID、PID等)

WindowState

  • WindowManagerService 中表示单个窗口的实体
  • 包含窗口的所有状态信息
  • 真正的窗口管理层对象

总结

完整调用链:应用 WindowManagerImplWindowManagerGlobalViewRootImplSessionWindowManagerService.addWindow()