Android Framework底层原理——WMS机制

快速了解WMS机制

WMS是什么

  • 开发中各种UI显示异常的bug都可以在WMS体系中找到对应的解决办法和对应原理。
    • 因为WMS管理着所有的窗口,包括创建、删除和修改,以及将某个窗口设置为焦点窗口。
  • WMS(WindowManagerService)相关概念
    • Window:它是一个抽象类,具体实现类为 PhoneWindow ,它对 View 进行管理。Window是View的容器,View是Window的具体表现内容;
    • WindowManager:是一个接口类,继承自接口 ViewManager ,从它的名称就知道它是用来管理 Window 的,它的实现类为 WindowManagerImpl;
    • WMS:是窗口的管理者,它负责窗口的启动、添加和删除。另外窗口的大小和层级也是由它进行管理的;

应用于那些场景

  • Activity页面渲染
    • Activity 启动后就可以看到我们写的 Layout 布局界面,Activity 从 setContentView() 加载布局到Window上,这个过程就涉及到WMS。
  • Dialog弹窗渲染
    • 创建Dialog后,会去创建Window窗口,然后通过addView形式将视图添加到窗口上。这个过程就涉及到WMS。
  • 可以解决那些问题
    • 如果你的定位是做界面开发,那么界面怎么来的?如何显示的?如何布局?如何渲染……要明白这些问题,WMS就是你必须掌握的内容。

WMS主要功能

  • 主要功能

    • Surface管理。为所有窗口分配Surface,客户端向WMS添加一个窗口的过程,其实就是WMS为其分配一块Surface的过程,一块块Surface在WMS的管理下有序的排布在屏幕上。Window的本质就是Surface。
    • 管理窗口的显示顺序、尺寸、位置, 最终都会反馈SurfaceFlinger。
    • 窗口动画, 包括进入,退出动画
    • 输入系统中转站:WMS是派发系统按键和触摸消息的最佳人选,当接收到一个触摸事件,它需要寻找一个最合适的窗口来处理消息,而WMS是窗口的管理者,系统中所有的窗口状态和信息都在其掌握之中,完成这一工作不在话下。
  • 主要功能图

Android Framework底层原理——WMS机制_第1张图片

Window是什么

  • Window是什么?
    • 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(点击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
    • Window是一个抽象类,具体实现是PhoneWindow。这个可以看Activity#attach方法源码
    • 创建Window需要通过WindowManager创建,WindowManager是外界访问Window的入口,Window具体实现位于WindowManagerService中
    • WindowManager和WindowManagerService的交互是通过IPC完成
  • Window和View关系
    • Window和View通过ViewRootImpl建立联系,iew是视图的呈现方式,但是不能单独存在,必须依附在Window这个抽象的概念上。
    • WMS把所有的用户消息发给View/ViewGroup,但是在View/ViewGroup处理消息的过程中,有一些操作是公共的, Window把这些公共行为抽象出来, 这就是Window。
  • Activity、View、Window三者之间的关系
    • 在Activity启动过程其中的attach()方法中初始化了PhoneWindow,而PhoneWindow是Window的唯一实现类。
    • 然后Activity通过setContentView将View设置到了PhoneWindow上,而View通过WindowManager的addView()、removeView()、updateViewLayout()对View进行管理。

WMS整体框架

  • WMS整体框架

Android Framework底层原理——WMS机制_第2张图片

  • WMS简单类图

Android Framework底层原理——WMS机制_第3张图片

WMS核心流程

WMS启动流程

  • WMS启动流程

Android Framework底层原理——WMS机制_第4张图片

WMS流程分析

Window添加View

  • 先看一个简单的案例。在主屏幕上添加一个TextView并展示,并且这个TextView独占一个窗口。
TextView mview = new TextView(context);
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
wmParams.width = 800;
wmParams.height = 800;
mWindowManager.addView(mview, wmParams);
  • 对Window添加View的流程步骤分析
    • WindowManager.addView添加窗口之前,TextView的onDraw不会被调用,也就说View必须被添加到窗口中,才会被绘制。只有申请了依附窗口,View才会有可以绘制的目标内存。
    • 当APP通过WindowManagerService的代理向其添加窗口的时候,WindowManagerService除了自己进行登记整理,还需要向SurfaceFlinger服务申请一块Surface画布,其实主要是画布背后所对应的一块内存,只有这一块内存申请成功之后,APP端才有绘图的目标,并且这块内存是APP端同SurfaceFlinger服务端共享的,这就省去了绘图资源的拷贝。
    • APP端是可以通过unLockCanvasAndPost直接同SurfaceFlinger通信进行重绘的,就是说图形的绘制同WMS没有关系,WMS只是负责窗口的管理,并不负责窗口的绘制。

WMS核心职责

  • 窗口管理:
    • WMS是窗口的管理者,负责窗口的启动,添加和删除,另外窗口的大小也时有 WMS 管理的,管理窗口的核心成员有 DisplayContent,WindowToken 和 WindowState
  • 窗口动画:
    • 窗口间进行切换时,使用窗口动画可以更好看一些,窗口动画由 WMS 动画子系统来负责,动画的管理系统为 WindowAnimator
  • 输入系统的中转站:
    • 通过对窗口触摸而产生的触摸事件,InputManagerServer(IMS) 会对触摸事件进行处理,他会寻找一个最合适的窗口来处理触摸反馈信息,WMS 是窗口的管理者,因此理所当然的就成为了输入系统的中转站。
  • Surface管理:
    • 窗口并不具备绘制的功能,因此每个窗口都需要有一个块 Surface 来供自己绘制,为每个窗口分配 Surface 是由 WMS 来完成的。

WMS是如何启动

  • WMS 是在 SystemServer 内部启动的
    • Android 系统在启动的时候,会启动两个重要的进程,一个是 Aygote 进程,两一个是由 Zygote 进程 fork 出来的 system_server 进程,SystemServer 会启动我们在系统中所需要的一系列 Service。
  • 在SystemServer#startOtherServices方法中
    • 核心1:SystemServer#WindowManagerService.main,传入了 IMS,因为 WMS 是 IMS 的中转站。观察 WindowManagerService.main 方法可以知道他是运行在 SystemServer 的 run 方法中,换句话说就是运行在 system_server 线程中。
    • 核心2:SystemServer#ServiceManager.addService,将 WMS 和 IMS 注册到 ServerManager 里面,这样客户端想要使用 WMS 就需要先去 ServiceManager 中查询信息,然后与 WMS 所在的进程建立通信,这样客户端就可以使用 WMS 。

WMS构造方法

  • 在WindowManagerService#main方法中

    • 通过 DisplayThread 的 getHandler 方法获取到了 DisplayThread 的 Handler 实例。用来处理需要低延时显示的相关操作,runWithScissors 表达式中创建了 WMS 对象。
  • 在WindowManagerService#WindowManagerService()构造方法中

    • 初始化 WindowManagerPolicy ,它用来定义一个窗口测量所需要遵循的规范。
    • 创建了 WindowAnimator,它用于管理所有的窗口动画。
    • 创建 RootWindowContainer 对象,根窗口容器。
    • 获取 DisplayManager 服务。
    • 获取 AMS,并持有他的引用。
  • WMS的启动中WMS创建完成后会调用 wm.onInitReady 方法

    • 和 WMS 的 main 方法类似,WindowManagerPolicy (简称 WMP) 是一个接口,init 的具体实现在 PhoneWindowManager(PWM) 中
    • init 方法运行在 android.ui线程中。因此他的线程优先级要高于 android.display 线程,必须等 init 方法执行完成后,android.display线程才会被唤醒从而继续执行下面的代码。

WMS窗口管理

  • Window 的操作有两大部分,一部分是 WindowManager 来处理,一部分是 WMS 来处理
  • 先看第一部分WindowManager处理逻辑
    • WindowManager 中,通过 WindowManagerGlobal 创建 ViewRootImpl ,也就是 View 的根。
    • 在 ViewRootImpl 中完成对 View 的绘制等操作,然后通过 IPC 获取到 Session,最终通过 WMS 来进行处理。
  • 再看第二部分WMS处理逻辑
    • 主要分析是ViewRootImpl#setView()到WindowManagerService.addWindow()的这个过程,涉及到跨进程通信。
    • 1.ViewRootImpl#setView()过程。mWindowSession是IWindowSession对象。在创建ViewRootImpl对象时被实例化。
    • 2.WindowManagerGlobal#getWindowSession()过程。getWindowManagerService()通过AIDL返回WindowManagerService实例。之后调用WindowManagerService#openSession()。
    • 3.WindowManagerService#openSession()过程。返回一个Session对象。也就是说在ViewRootImpl#setView()中调用的是mWindowSession.addToDisplay,其实就是Session#addToDisplay()。
    • 4.Session#addToDisplay()过程。mService是个WindowManagerService对象,也就是说最后调用的是WindowManagerService#addWindow()
    • 5.WindowManagerService#addWindow()过程。mWindowMap是个Map实例,将WindowManager添加进WindowManagerService统一管理。至此,整个添加视图操作解析完毕。
  • 注意WMS并不关心View的具体内容
    • WMS只关心各个应用显示的界面大小,层级值等,这些数据到包含在 WindowManager.LayoutParams 中。

一些源码分析

addView源码分析

  • Window的addView源码分析?
    • WindowManager是一个接口,真正实现类是WindowManagerImpl,并最终以代理模式交给WindowManagerGlobal实现。
    • addView:
      1.创建ViewRootImpl;
      2.将ViewRoot、DecorView、布局参数保存到WM的内部列表中;
      3.ViewRoot.setView()建立ViewRoot和DecorView的联系。
    • setView:
      1.进行View绘制三大流程;
      2.会通过WindowSession完成Window的添加过程(一次IPC调用)
    • requestLayout:内部调用scheduleTraversals(), 底层通过mChoreographer去监听下一帧的刷新信号。
    • mWindowSession.addToDisplay: 执行WindowManagerService的addWindow
    • addWindow: 检查参数等设置;检查Token;将Token、Window保存到WMS中;将WindowState保存到Session中。

remove源码与解析

  • Window的remove源码与解析
    • WindowManager中提供了两种删除接口:removeView异步删除、removeViewImmediate同步删除(不建议使用)
    • 调用WMGlobal的removeView
    • 调用到WMGlobal的removeViewLocked进行真正的移除
    • 执行ViewRoot的die方法():
      1-同步方法直接调用doDie
      2-异步方法直接发送Message
    • doDie(): 调用dispatchDetachedFromWindow()和WindowManagerGlobal.getInstance().doRemoveView(this)
    • dispatchDetachedFromWindow:
      1.回调onDetachedFromeWindow;
      2.垃圾回收相关操作;
      3.通过Session的remove()在WMS中删除Window;
      4.通过Choreographer移除监听器

Android Framework底层原理手册:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战
  12. ……
    Android Framework底层原理——WMS机制_第5张图片

你可能感兴趣的:(Framework,Android,移动开发,android,ui,zygote,binder,android-studio)