WindowManagerService(WMS)是 Android 窗口系统的核心。它管理系统中所有窗口的添加、删除、层级、焦点和动画,是 Surface 分配和 Input 事件分发的中枢。本文基于 Android 11 (API 30) AOSP 源码,深入分析 WMS 的核心架构、窗口容器层级、窗口添加流程、Z-Order 管理、Input 焦点机制和 SurfaceFlinger 交互。
一、WMS 在系统架构中的定位 WMS 运行在 system_server 进程中,作为系统服务注册在 ServiceManager 中。它在 startOtherServices() 阶段被启动,晚于 AMS(因为 WMS 的一些初始化依赖 AMS 已就绪)。
应用进程 system_server ┌──────────────┐ ┌─────────────────────────────┐ │ View │ │ WindowManagerService (WMS) │ │ ViewRootImpl│ Binder IPC │ ├── WindowManagerPolicy │ │ IWindow │◄────────────►│ │ (PhoneWindowManager) │ │ IWindowSession│ │ ├── RootWindowContainer │ │ │ │ │ ├── DisplayContent │ │ │ │ │ │ ├── Task │ │ │ │ │ │ │ └── WindowState│ │ │ │ ├── WindowAnimator │ │ │ │ ├── InputManagerService │ │ │ │ └── SurfaceAnimationRunner │ └──────────────┘ └──────────┬──────────────────┘ │ ┌──────────▼──────────────────┐ │ SurfaceFlinger │ │ (native service) │ │ 负责 Surface 合成与显示 │ └─────────────────────────────┘
AOSP 核心路径:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/wm/WindowState.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
二、WMS 的启动流程 2.1 SystemServer 中启动 WMS private void startOtherServices () { inputManager = new InputManagerService (context); wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager (), mActivityManagerService.mActivityTaskManager); ServiceManager.addService(Context.WINDOW_SERVICE, wm, false , DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); mActivityManagerService.setWindowManager(wm); wm.onInitReady(); }
2.2 WMS.main 和构造函数 public static WindowManagerService main (Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) { return new WindowManagerService (context, inputManager, showBootMsgs, onlyCore, policy, atm); } private WindowManagerService (Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) { mContext = context; mPolicy = policy; mAtmService = atm; mInputManager = inputManager; mH = new H (mHandlerThread.getLooper()); mAnimator = new WindowAnimator (this ); mRoot = new RootWindowContainer (this ); mSurfaceControlFactory = new SurfaceControl .Builder()::build; Watchdog.getInstance().addMonitor(this ); mChoreographer = Choreographer.getSfInstance(); }
三、窗口容器层级体系(WindowContainer Hierarchy) Android 10+ 重构了窗口管理层级,引入了统一的 WindowContainer 体系。这是 WMS 最核心的数据结构设计。
3.1 WindowContainer 类继承树 class WindowContainer <E extends WindowContainer > extends ConfigurationContainer <E> implements Comparable <WindowContainer>, Animatable, SurfaceFreezer.Freezable { protected final WindowList<E> mChildren = new WindowList <E>(); private WindowContainer mParent; SurfaceControl mSurfaceControl; WindowToken mOwner; }
3.2 完整的容器层级树 从 Android 10 开始,完整的窗口容器层级如下:
RootWindowContainer └── DisplayContent (每个物理/虚拟屏幕) └── DisplayArea (Android 11+ 引入的显示区域,替代部分 Stack 功能) ├── TaskDisplayArea (容纳应用任务窗口) │ └── Task (即之前的 ActivityStack) │ └── ActivityRecord (即之前的 AppWindowToken) │ └── WindowState (每个实际的窗口 Surface) ├── ImeContainer (输入法容器) │ └── WindowToken │ └── WindowState (输入法窗口) ├── StatusBar (状态栏,Wallpaper 等) └── NavBar (导航栏)
3.3 WindowState——窗口的基本单位 每一个 View 对应的 Window 在 WMS 端都有一个对应的 WindowState 对象:
class WindowState extends WindowContainer <WindowState> implements WindowManagerPolicy .WindowState { final int mOwnerUid; final int mOwnerPid; final int mBaseLayer; final int mSubLayer; final WindowManager.LayoutParams mAttrs; final Session mSession; final IWindow mClient; WindowToken mToken; SurfaceControl mSurfaceControl; boolean mHasSurface; int mViewVisibility; boolean mRelayoutCalled; }
3.4 WindowToken——应用窗口的组织者 class WindowToken extends WindowContainer <WindowState> { final IBinder token; final int windowType; final boolean mPersistOnEmpty; boolean mRoundedCornerOverlay; }
3.5 DisplayContent——多屏幕支持 class DisplayContent extends WindowContainer <DisplayContent.DisplayChildWindowContainer> { final int mDisplayId; final Display mDisplay; final DisplayPolicy mDisplayPolicy; DisplayInfo mDisplayInfo; DisplayArea.Tokens mImeInputTargetContainer; DisplayArea.Tokens mImeControlTargetContainer; }
四、窗口添加流程(addWindow 全链路追踪) 窗口添加是 WMS 最核心、最复杂的操作。这里以 WindowManager.addView 为入口,追踪全链路。
4.1 应用端:WindowManager.addView → ViewRootImpl public void addView (View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; ViewRootImpl root; synchronized (mLock) { root = new ViewRootImpl (view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); root.setView(view, wparams, panelParentView); } }
4.2 ViewRootImpl.setView——创建 IWindow Session public void setView (View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this ) { if (mView == null ) { mView = view; mWindowSession = WindowManagerGlobal.getWindowSession(); int res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mWinFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets); if (mInputChannel != null ) { mInputEventReceiver = new WindowInputEventReceiver (mInputChannel, Looper.myLooper()); } } } }
4.3 WMS 端:Session.addToDisplay → WMS.addWindow Session 是每个应用进程在 WMS 端的代理(代表),继承自 IWindowSession.Stub:
class Session extends IWindowSession .Stub implements IBinder .DeathRecipient { final WindowManagerService mService; @Override public int addToDisplay (IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState) { return mService.addWindow(this , window, seq, attrs, viewVisibility, displayId, outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel, outInsetsState); } }
4.4 WMS.addWindow——核心逻辑 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 res = mPolicy.checkAddPermission(attrs, session.mUid); final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); WindowToken token = displayContent.getWindowToken( hasParent ? parentWindow.mAttrs.token : attrs.token); if (token == null ) { token = new WindowToken (this , binder, type, false , displayContent, session.mCanAddInternalSystemWindow); } final WindowState win = new WindowState (this , session, client, token, parentWindow, appOp[0 ], seq, attrs, viewVisibility, session.mUid, session.mCanAddInternalSystemWindow); mPolicy.adjustWindowParamsLw(win, win.mAttrs); win.attach(); if (type == TYPE_INPUT_METHOD || type == TYPE_INPUT_METHOD_DIALOG) { displayContent.computeImeTarget(true ); } win.openInputChannel(outInputChannel); win.setHasSurface(true ); mWindowPlacerLocked.performSurfacePlacement(); return res; }
4.5 WindowState.attach——插入容器树 void attach () { if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken); mSession.windowAddedLocked(mAttrs.packageName); if (mAttrs.type >= FIRST_APPLICATION_WINDOW && mAttrs.type <= LAST_APPLICATION_WINDOW) { mActivityRecord.addWindow(this ); } else if (mAttrs.type == TYPE_INPUT_METHOD || mAttrs.type == TYPE_INPUT_METHOD_DIALOG) { mDisplayContent.addImeWindow(this ); } else { mDisplayContent.addSystemWindow(this ); } }
五、Z-Order 管理与层级排序 WMS 使用 Z-Order 来确定窗口的绘制顺序和输入事件分发顺序。
5.1 层级计算 static final int TYPE_LAYER_MULTIPLIER = 10000 ;static final int TYPE_LAYER_OFFSET = 1000 ;int getBaseTypeLayer () { }
5.2 子层级排序 在同一个 WindowToken(如同一 Activity)内部,子窗口有子层级:
static final int APPLICATION_MEDIA_SUBLAYER = -2 ; static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1 ; static final int APPLICATION_PANEL_SUBLAYER = 1 ; static final int APPLICATION_SUB_PANEL_SUBLAYER = 2 ; static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3 ;
5.3 全局 Z-Order 排序 WMS 通过 WindowContainer.assignChildOrder 和 WindowContainer.compareTo 实现容器的全局排序。排序规则:
先比较基础层(type layer)
再比较子层(sub layer)
最后按添加时间排序(同层级时后添加的在上层)
6.1 窗口焦点(Window Focus) 窗口焦点决定了哪个窗口可以接收按键事件。焦点窗口由 WMS 的 mCurrentFocus 字段追踪。
boolean updateFocusedWindowLocked (int mode, boolean updateInputWindows) { WindowState newFocus = findFocusedWindowIfNeeded(mode); if (mCurrentFocus != newFocus) { if (mCurrentFocus != null ) { mCurrentFocus.reportFocusChanged(false ); } if (newFocus != null ) { newFocus.reportFocusChanged(true ); } mCurrentFocus = newFocus; } return true ; }
Input 焦点是通过 InputDispatcher 分发的触摸/按键事件的窗口。WMS 向 InputManagerService 提供窗口信息,由 InputDispatcher 在 native 层进行实际的分发决策。关键方法:
void updateInputWindowsLw (boolean force) { mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag); mInputManagerService.setInputWindows( mUpdateInputForAllWindowsConsumer.getInputWindowHandles(), mDisplayId); }
七、SurfaceControl 与 SurfaceFlinger 的交互 7.1 SurfaceControl 的创建 每个 WindowState 在显示前需要分配一个 Surface,这是通过 SurfaceControl 实现的。SurfaceControl 是 Java 层对 native Surface 的封装:
public SurfaceControl (SurfaceSession session, String name, int w, int h, int format, int flags, SurfaceControl parent, SparseIntArray metadata) { mNativeObject = nativeCreate(session, name, w, h, format, flags, parent != null ? parent.mNativeObject : 0 , metadata); }
7.2 WindowSurfaceController——窗口的 Surface 管理 class WindowSurfaceController { SurfaceControl mSurfaceControl; final WindowStateAnimator mAnimator; void createSurfaceControl () { mSurfaceControl = mAnimator.createSurfaceLocked( mAnimator.mWin.mAttrs.type, mAnimator.mWin.getOwningUid()); } void setPositionAndLayer (float x, float y, int layer) { if (mSurfaceControl != null ) { mSurfaceControl.setPosition(x, y); mSurfaceControl.setLayer(layer); } } }
7.3 SurfaceFlinger 合成流程 WMS 不直接渲染任何内容,它只管理 Surface 的布局和属性。实际的合成工作由 SurfaceFlinger 在 native 层完成:
WMS 通过 WindowSurfacePlacer.performSurfacePlacement() 遍历所有窗口,计算每个窗口的 frame、layer 和可见性。
调用 SurfaceControl.setPosition/setLayer/setMatrix/setCrop 等方法更新 native 层属性。
SurfaceFlinger 在下一个 vsync 周期读取所有 Surface 的属性并进行合成。
合成结果通过 Hardware Composer(HWC)或 GPU(GLES)交给显示驱动。
AOSP SurfaceFlinger 路径:frameworks/native/services/surfaceflinger/
八、IME 窗口管理 IME(输入法)窗口是一种特殊窗口,WMS 对其有专门的管理逻辑。
WindowState mInputMethodWindow; WindowState mInputMethodTarget; void computeImeTarget (boolean updateImeTarget) { mInputMethodTarget = findImeInputTarget(); if (mInputMethodTarget != null ) { mInputMethodWindow.adjustForImeIfNeeded(mInputMethodTarget); } }
九、屏幕旋转处理 当设备旋转时,WMS 通过 DisplayRotation 和 WindowManagerPolicy 协作处理。
boolean updateRotationUnchecked (boolean alwaysSendConfiguration) { final int rotation = mPolicy.rotationForOrientationLw( mService.getLastOrientation(), mRotation); if (rotation != mRotation) { mRotation = rotation; mDisplayContent.updateRotationUnchecked(); } return changed; }
旋转涉及的关键步骤:
传感器检测到设备方向变化,报告给 WindowOrientationListener。
PhoneWindowManager.rotationForOrientationLw() 决定目标旋转角度。
WMS 更新 DisplayContent 的旋转信息。
通过 WMS → AMS → ActivityThread 通知 App 进程 Configuration 改变。
Activity 选择处理 onConfigurationChanged(声明了 configChanges)或重建自身。
SurfaceFlinger 在合成时应用旋转矩阵到 Display 输出。
十、核心面试题 Q1:ViewRootImpl、Window、WindowManager、WMS 之间的关系是什么?
每个 Activity 对应一个 PhoneWindow(Window 的唯一实现类),它作为顶层视图树的容器。当调用 WindowManager.addView(decorView) 时,会创建一个 ViewRootImpl 对象。ViewRootImpl 持有 IWindowSession(即 Session 的 Binder 代理),通过它向 WMS 发起 addWindow 请求。WMS 端创建对应的 WindowState 并分配 Surface。ViewRootImpl 是 App 端视图树和 WMS 之间的桥梁,它同时也是 View 绘制的入口(performTraversals)。
Q2:Dialog 的窗口和 Activity 的窗口在 WMS 中如何组织?
Dialog 窗口是 Activity 窗口的子窗口(sub-window)。在 WindowManager.LayoutParams 中,Dialog 的 token 被设置为宿主 Activity 的 Window token。WMS 在添加 Dialog 窗口时,根据 token 找到父窗口,将 Dialog 的 WindowState 作为父窗口的子窗口管理,因此 Dialog 有更高的 sub-layer,总是显示在 Activity 之上。Dialog 关闭时不会触发 Activity 的生命周期变化,因为 WMS 只是移除了一个子窗口。
Q3:WMS 是如何与 InputManagerService 交互来完成事件分发的?
WMS 通过 InputMonitor.updateInputWindowsLw() 收集所有当前可接收输入的窗口,并传递给 InputManagerService。IMS 将这些窗口信息发送到 native 层的 InputDispatcher。InputDispatcher 收到触摸事件后,根据窗口的 Z-Order(从高到低)和触摸坐标找到目标窗口,然后通过 InputChannel(每个窗口特有的 Unix Domain Socket 对)将事件发送到对应的 App 进程。
Q4:为什么 Android 需要 WMS 管理窗口,而不是像传统 Linux GUI 那样由 X11/Wayland 管理?
Android 选择了自主的窗口系统,原因包括:(1) 移动设备的资源受限性,需要轻量级的窗口管理,传统 X11 协议过于复杂和重量级;(2) 需要与 Android 的 Activity 生命周期深度绑定——Activity 的暂停/恢复必须与窗口的显示/隐藏同步;(3) 安全性——每个应用窗口的 Surface 是隔离的,配合 Binder 权限检查可以防止恶意应用截取其他应用的渲染内容;(4) 统一的动画系统——WMS 与 Choreographer 协作,确保所有窗口动画与 vsync 对齐。
AOSP 核心路径参考:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/WindowState.java
frameworks/base/services/core/java/com/android/server/wm/WindowToken.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
frameworks/base/services/core/java/com/android/server/wm/DisplayArea.java
frameworks/base/services/core/java/com/android/server/wm/Session.java
frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
frameworks/base/core/java/android/view/ViewRootImpl.java
frameworks/base/core/java/android/view/WindowManagerGlobal.java
frameworks/base/core/java/android/view/SurfaceControl.java
frameworks/native/services/surfaceflinger/