android WMS 详解

📅 2026/8/15 17:43:43
android WMS 详解
Android WMSWindow Manager Service详解WMSWindow Manager Service是 Android 系统的核心服务之一负责窗口的管理、布局、动画、层级排序以及输入事件的分发。它是连接应用层View 系统与底层显示系统SurfaceFlinger的桥梁。一、WMS 的定位与职责┌─────────────────────────────────────────────────────────┐ │ 应用层 (App) │ │ Activity / Dialog / PopupWindow │ ├─────────────────────────────────────────────────────────┤ │ 窗口管理层 │ │ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │ │ AMS │◄──►│ WMS │◄──►│ InputManager │ │ │ └─────────┘ └────┬────┘ └─────────────────┘ │ ├─────────────────────────┼───────────────────────────────┤ │ 显示层 │ │ SurfaceFlinger / HWComposer │ ├─────────────────────────┼───────────────────────────────┤ │ HAL 层 │ │ Gralloc / Display HAL │ └─────────────────────────┴───────────────────────────────┘核心职责职责说明窗口管理维护所有窗口的添加、移除、更新Z-Order 排序决定窗口的层级顺序谁在上谁在下布局计算计算每个窗口的位置和大小动画系统管理窗口的进入、退出、切换动画输入分发将触摸/按键事件路由到正确的窗口屏幕旋转处理方向变化时的窗口重排多窗口/分屏管理 Freeform、Split-Screen 等模式二、WMS 的启动与初始化WMS 在SystemServer中启动java// SystemServer.java private void startOtherServices() { // 1. 创建 WMS 实例 WindowManagerService wm WindowManagerService.main( context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); // 2. 注册到 ServiceManager ServiceManager.addService(Context.WINDOW_SERVICE, wm, false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); // 3. 初始化显示 wm.displayReady(); // 4. 系统准备就绪 wm.systemReady(); }关键初始化对象WindowManagerPolicy策略接口PhoneWindowManager 是默认实现定义系统 UI 行为DisplayContent代表一个物理或虚拟显示设备RootWindowContainer管理所有 DisplayContentWindowAnimator负责窗口动画InputManagerService输入事件管理三、核心架构与类关系核心类层次RootWindowContainer └── DisplayContent (每个屏幕一个) └── TaskDisplayArea └── Task └── ActivityRecord └── WindowToken └── WindowState (对应一个窗口)关键类详解表格类名作用WindowState代表一个具体的窗口包含窗口的所有状态信息WindowToken窗口的令牌将一组 WindowState 绑定到一个应用组件DisplayContent代表一个显示设备管理该屏幕上的所有窗口DisplayPolicy定义屏幕策略状态栏、导航栏位置等WindowContainer所有窗口容器的基类实现树形结构SurfaceControl与 SurfaceFlinger 通信的句柄四、窗口类型与层级Android 窗口分为三大类通过type参数指定1. 应用窗口 (1-99)javaTYPE_BASE_APPLICATION 1 // Activity 主窗口 TYPE_APPLICATION 2 // 普通应用窗口 TYPE_APPLICATION_STARTING 3 // 启动窗口冷启动时的白屏/黑屏 TYPE_DRAWN_APPLICATION 4 // 已绘制完成的窗口2. 子窗口 (1000-1999)javaTYPE_APPLICATION_PANEL 1000 // Panel如 PopupWindow TYPE_APPLICATION_MEDIA 1001 // 媒体覆盖层 TYPE_APPLICATION_SUB_PANEL 1002 // 子面板 TYPE_APPLICATION_ABOVE_SUB_PANEL 10033. 系统窗口 (2000-2999)javaTYPE_STATUS_BAR 2000 // 状态栏 TYPE_SEARCH_BAR 2001 // 搜索栏 TYPE_NOTIFICATION_SHADE 2014 // 通知面板 TYPE_NAVIGATION_BAR 2019 // 导航栏 TYPE_INPUT_METHOD 2011 // 输入法 TYPE_VOLUME_OVERLAY 2024 // 音量条 TYPE_SYSTEM_ALERT 2015 // 系统警告需要权限 TYPE_TOAST 2005 // Toast TYPE_PHONE 2002 // 悬浮窗需要权限Z-Order 规则窗口层级由mBaseLayer和mSubLayer决定mBaseLayer由窗口类型决定类型值越大层级越高mSubLayer子窗口相对父窗口的偏移┌─────────────────────────────┐ ← 最上层 (TYPE_SYSTEM_ALERT) │ 系统弹窗/悬浮窗 │ ├─────────────────────────────┤ │ 输入法窗口 │ ├─────────────────────────────┤ │ 应用窗口 (Activity) │ ├─────────────────────────────┤ │ 壁纸窗口 │ ├─────────────────────────────┤ │ 底层系统窗口 │ └─────────────────────────────┘ ← 最下层五、窗口添加流程当应用调用WindowManager.addView()时完整的调用链如下ViewManager.addView() └── WindowManagerImpl.addView() └── WindowManagerGlobal.addView() └── ViewRootImpl.setView() └── IWindowSession.addToDisplay() [跨进程] └── WindowManagerService.addWindow()WMS.addWindow() 核心逻辑javapublic int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, InputChannel outInputChannel) { // 1. 权限检查 int res mPolicy.checkAddPermission(attrs, appOp); // 2. 获取或创建 WindowToken WindowToken token displayContent.getWindowToken( attrs.token); if (token null) { // 创建新的 WindowToken token new WindowToken(this, attrs.token, type, ...); } // 3. 创建 WindowState final WindowState win new WindowState(this, session, client, token, parentWindow, attrs, viewVisibility, ...); // 4. 调整窗口参数 mPolicy.adjustWindowParamsLw(win, win.mAttrs, ...); // 5. 将 WindowState 加入 WindowToken win.mToken.addWindow(win); // 6. 将 WindowToken 加入 DisplayContent displayContent.addWindow(win); // 7. 创建 SurfaceControl win.createSurfaceControl(); // 8. 分配输入通道 win.openInputChannel(outInputChannel); // 9. 触发布局 assignWindowLayers(displayContent); displayContent.getDisplayPolicy().addWindowLw(win, attrs); // 10. 通知 SurfaceFlinger win.applyToken(); return ADD_OKAY; }六、窗口布局与测量relayoutWindowrelayoutWindow是 WMS 中最核心的方法之一负责计算窗口大小和创建 Surface。ViewRootImpl.relayoutWindow() └── IWindowSession.relayout() └── WMS.relayoutWindow()核心流程javapublic int relayoutWindow(Session session, IWindow client, LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame, DisplayCutout outCutout, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl) { WindowState win windowForClientLocked(session, client, false); // 1. 更新窗口属性 if (attrs ! null) { win.setAttrs(attrs); } // 2. 计算窗口大小 win.computeFrameLw(); // 3. 如果 Surface 不存在创建新的 SurfaceControl if (win.mHasSurface !win.mSurfaceController.getSurfaceControl().isValid()) { win.createSurfaceControl(); } // 4. 将 SurfaceControl 返回给应用 outSurfaceControl.copyFrom(win.mSurfaceController.getSurfaceControl()); // 5. 计算 insets win.getContentInsets(outContentInsets); win.getVisibleInsets(outVisibleInsets); // 6. 触发布局 mWindowPlacerLocked.performSurfacePlacement(); return win.mRelayoutResult; }Surface 创建时序WMS.relayoutWindow() └── WindowState.createSurfaceControl() └── WindowSurfaceController.createSurfaceLocked() └── new SurfaceControl.Builder(mSurfaceSession) └── SurfaceFlinger.createLayer() └── 分配 GraphicBuffer七、窗口动画系统Android 窗口动画分为三个层级1. 应用层动画View Animationjavaview.startAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in));只影响单个 View不涉及 WMS2. 窗口动画Window Animationjava// WindowManager.LayoutParams params.windowAnimations R.style.MyWindowAnimation;由WindowStateAnimator处理在WindowAnimator中统一调度3. 过渡动画Transition AnimationAndroid 12 引入的WindowAnimationTransition由TransitionController管理java// Transition 类型 TRANSIT_OPEN // 窗口打开 TRANSIT_CLOSE // 窗口关闭 TRANSIT_TO_FRONT // 窗口移到前台 TRANSIT_TO_BACK // 窗口移到后台动画执行流程WindowAnimator.animate() └── WindowStateAnimator.stepAnimationLocked() └── 计算动画变换矩阵 └── SurfaceControl.setMatrix() └── SurfaceFlinger 合成时应用变换八、输入事件分发WMS 在输入事件中扮演路由角色plainInputDispatcher (Native) └── WMS 注册 InputMonitor └── 根据窗口层级找到目标 WindowState └── 通过 InputChannel 发送给对应进程 └── ViewRootImpl.dispatchInputEvent() └── DecorView.dispatchTouchEvent()事件分发关键逻辑java// InputDispatcher.cpp int32_t InputDispatcher::findTouchedWindowTargetsLocked(...) { // 1. 从顶层向下遍历窗口 // 2. 找到包含触摸点的最上层窗口 // 3. 检查窗口是否可接收事件FLAG_NOT_TOUCHABLE 等 // 4. 将事件分发给目标窗口 }WMS 中的输入相关配置Flag说明FLAG_NOT_FOCUSABLE窗口不可获取焦点FLAG_NOT_TOUCHABLE窗口不可触摸FLAG_NOT_TOUCH_MODAL窗口只接收自身区域的触摸FLAG_WATCH_OUTSIDE_TOUCH接收窗口外部的触摸事件FLAG_SPLIT_TOUCH支持多点分屏触摸九、WMS 与 SurfaceFlinger 的关系┌─────────────┐ SurfaceControl ┌─────────────────┐ │ WMS │ ◄──────────────────────► │ SurfaceFlinger │ │ (逻辑管理) │ transaction │ (合成显示) │ └──────┬──────┘ └─────────────────┘ │ │ 创建/配置 Surface ▼ ┌─────────────┐ │ WindowState │ │ SurfaceControl│ └─────────────┘ │ │ 应用绘制 ▼ ┌─────────────┐ │ Surface │ │ (GraphicBuffer)│ └─────────────┘SurfaceTransactionWMS 通过SurfaceControl.Transaction与 SurfaceFlinger 通信javaSurfaceControl.Transaction t new SurfaceControl.Transaction(); t.setLayer(surfaceControl, layer); // 设置层级 t.setPosition(surfaceControl, x, y); // 设置位置 t.setMatrix(surfaceControl, matrix); // 设置变换 t.setCrop(surfaceControl, crop); // 设置裁剪 t.setAlpha(surfaceControl, alpha); // 设置透明度 t.apply(); // 提交事务十、WMS 与 AMS 的协作WMS 和 AMS 紧密协作管理 Activity 生命周期和窗口状态Activity 启动时的窗口流程plainAMS.startActivity() └── ActivityTaskManager.startActivity() └── ActivityStarter.execute() └── ActivityStack.startActivityLocked() └── WMS.addAppToken() // 添加 AppWindowToken └── 创建启动窗口 (StartingWindow) └── Activity 绘制完成 └── WMS.reportStartingWindowDrawn() └── 移除启动窗口关键协作点表格场景AMS 操作WMS 操作Activity 启动创建 ActivityRecord创建 AppWindowToken StartingWindowActivity 暂停onPause()窗口变为不可见降低层级Activity 恢复onResume()窗口移到前台提升层级Activity 销毁移除 ActivityRecord移除 WindowToken 及所有 WindowState屏幕旋转通知 Activity 重建重新计算所有窗口尺寸十一、多窗口模式Android 7.0 支持多窗口WMS 负责管理分屏模式Split-Screen┌─────────────────────────────┐ │ Task 1 (上半屏) │ │ (Activity A) │ ├─────────────────────────────┤ ← Divider │ Task 2 (下半屏) │ │ (Activity B) │ └─────────────────────────────┘自由窗口模式Freeform┌─────────────────────────────────────┐ │ ┌─────────┐ │ │ │ Freeform│ │ │ │ Window │ │ │ └─────────┘ │ │ ┌─────────┐ │ │ │ Freeform│ │ │ │ Window │ │ │ └─────────┘ │ └─────────────────────────────────────┘多窗口实现原理Task代表一个任务栈包含多个 ActivityTaskFragmentTask 的细分单元WindowContainer树形结构管理所有容器十二、WMS 的线程模型┌─────────────────────────────────────┐ │ Main Thread (SystemServer) │ │ - 处理 IPC 调用 │ │ - 窗口状态变更 │ ├─────────────────────────────────────┤ │ Animation Thread │ │ - 执行窗口动画 │ │ - 计算变换矩阵 │ ├─────────────────────────────────────┤ │ SurfaceAnimation Thread │ │ - 与 SurfaceFlinger 同步动画 │ ├─────────────────────────────────────┤ │ Input Thread (Native) │ │ - 读取输入设备 │ │ - 分发输入事件 │ └─────────────────────────────────────┘十三、常见问题与调试1. 查看窗口层级bashadb shell dumpsys window windows2. 查看 SurfaceFlinger 信息bashadb shell dumpsys SurfaceFlinger3. 查看动画状态bashadb shell dumpsys window animator4. 常见窗口问题问题原因解决方向窗口无法获取焦点FLAG_NOT_FOCUSABLE检查 Window 属性触摸事件不响应FLAG_NOT_TOUCHABLE检查 touchable 标志窗口被遮挡Z-Order 过低调整窗口类型或层级黑屏/白屏Surface 未创建检查 relayoutWindow动画卡顿SurfaceFlinger 掉帧检查 GPU 负载十四、Android 版本演进版本WMS 重大变化Android 4.1引入 Project ButterVSync 同步Android 5.0引入 SurfaceFlinger 的 HWC2多显示支持Android 7.0多窗口模式Split-Screen, FreeformAndroid 8.0画中画PIP模式Android 10折叠屏支持多 resumeAndroid 11窗口注入限制气泡通知Android 12引入 SplashScreen APITransition 动画重构Android 13进一步模块化改进多任务处理总结WMS 是 Android 显示系统的调度中心核心要点窗口是树形结构从 RootWindowContainer 到 WindowState 的层级管理Surface 是绘制载体WMS 管理 Surface 的创建和配置实际绘制由应用完成Z-Order 决定可见性层级高的窗口遮挡层级低的窗口relayout 是核心流程计算大小、创建 Surface、触发布局与 AMS 紧密协作Activity 生命周期驱动窗口状态变化