企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
俗话说,一个好汉三个帮!WMS的强大是由很多重要的成员互相协调工作而实现的。了解WMS的构成将会为我们深入探索WMS打下良好的基础,进而分析它的启动过程,这是再合适不过了。 #### 1.WMS的诞生 和其他的系统服务一样,WMS的启动位于SystemServer.java中ServerThread类的run()函数内。 **SystemServer.java::ServerThread.run()** ``` Public void run() { ...... WindowManagerService wm = null; ...... try { ...... // **①创建WMS实例** /* 通过WindowManagerService的静态函数main()创建WindowManagerService的实例。 注意main()函数的两个参数wmHandler和uiHandler。这两个Handler分别运行于由 ServerThread所创建的两个名为“WindowManager”和“UI”的两个HandlerThread中 */ wm =WindowManagerService.main(context, power, display, inputManager, uiHandler,wmHandler, factoryTest !=SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); // 添加到ServiceManager中去 ServiceManager.addService(Context.WINDOW_SERVICE,wm); ...... catch(RuntimeException e) { ...... } ...... try { //**②初始化显示信息** wm.displayReady(); } catch(Throwable e) {......} ...... try { // ③通知WMS,系统的初始化工作完成 wm.systemReady(); } catch(Throwable e) {......} ...... } ``` 由此可以看出,WMS的创建分为三个阶段: - 创建WMS的实例。 - 初始化显示信息。 - 处理systemReady通知。 接下来,将通过以上三个阶段分析WMS从无到有的过程。 看一下WMS的main()函数的实现: **WindowManagerService.java::WindowManagerSrevice.main()** ``` public static WindowManagerService main(finalContext context, finalPowerManagerService pm, final DisplayManagerService dm, finalInputManagerService im, finalHandler uiHandler, final Handler wmHandler, finalboolean haveInputMethods, final boolean showBootMsgs, finalboolean onlyCore) { finalWindowManagerService[] holder = new WindowManagerService[1]; // 通过由SystemServer为WMS创建的Handler新建一个WindowManagerService对象 // 此Handler运行在一个名为WindowManager的HandlerThread中 wmHandler.runWithScissors(newRunnable() { @Override publicvoid run() { holder[0]= new WindowManagerService(context, pm, dm, im, uiHandler,haveInputMethods, showBootMsgs, onlyCore); } }, 0); returnholder[0]; } ``` * * * * * **注意** Handler类在Android 4.2中新增了一个API:runWithScissors()。这个函数将会在Handler所在的线程中执行传入的Runnable对象,同时阻塞调用线程的执行,直到Runnable对象的run()函数执行完毕。 * * * * * WindowManagerService.main()函数在ServerThread专为WMS创建的线程“WindowManager”上创建了一个WindowManagerService的新实例。WMS中所有需要的Looper对象,例如Handler、Choreographer等,将会运行在“WindowManager”线程中。 接下来看一下其构造函数,看一下WMS定义了哪些重要的组件。 **WindowManagerService.java::WindowManagerService.WindowManagerService()** ``` private WindowManagerService(Context context,PowerManagerService pm, DisplayManagerService displayManager, InputManagerService inputManager, Handler uiHandler, booleanhaveInputMethods, boolean showBootMsgs, boolean onlyCore) ...... mDisplayManager= (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mDisplayManager.registerDisplayListener(this,null); Display[]displays = mDisplayManager.getDisplays(); /* 初始化DisplayContent列表。DisplayContent是Android4.2为支持多屏幕输出所引入的一个 概念。一个DisplayContent指代一块屏幕,屏幕可以是手机自身的屏幕,也可以是基于Wi-FiDisplay 技术的虚拟屏幕[3]*/ for(Display display : displays) { createDisplayContentLocked(display); } ..... /* 保存InputManagerService。输入事件最终要分发给具有焦点的窗口,而WMS是窗口管理者, 所以WMS是输入系统中的重要一环。关于输入系统的内容将在第5章中深入探讨*/ mInputManager= inputManager; // 这个看起来其貌不扬的mAnimator,事实上具有非常重要的作用。它管理着所有窗口的动画 mAnimator= new WindowAnimator(this, context, mPolicy); // 在“UI“线程中将对另一个重要成员mPolicy,也就是WindowManagerPolicy进行初始化 initPolicy(uiHandler); // 将自己加入到Watchdog中 Watchdog.getInstance().addMonitor(this); ...... } ``` 第二步,displayReady()函数的调用主要是初始化显示尺寸的信息。其内容比较琐碎,这里就先不介绍了。不过值得注意的一点是,再displayReady()完成后,WMS会要求ActivityManagerService进行第一次Configuration的更新。 第三步,在systemReady()函数中,WMS本身将不会再做任何操作了,直接调用mPolicy的systemReady()函数。 #### 2.WMS的重要成员 总结一下在WMS的启动过程中所创建的重要成员,参考图4-3。 :-: ![](http://img.blog.csdn.net/20150814130437567?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图 4-3 WMS的重要成员 以下是对图4-3中重要成员的简单介绍: - mInputManager,InputManagerService(输入系统服务)的实例。用于管理每个窗口的输入事件通道(InputChannel)以及向通道上派发事件。关于输入系统的详细内容将在本书第5章详细探讨。 - mChoreographer,Choreographer的实例,在SampleWindow的例子中已经见过了。Choreographer的意思是编舞指导。它拥有从显示子系统获取VSYNC同步事件的能力,从而可以在合适的时机通知渲染动作,避免在渲染的过程中因为发生屏幕重绘而导致的画面撕裂。从这个意义上来讲,Choreographer的确是指导Android翩翩起舞的大师。WMS使用Choreographer负责驱动所有的窗口动画、屏幕旋转动画、墙纸动画的渲染。 - mAnimator,WindowAnimator的实例。它是所有窗口动画的总管(窗口动画是一个WindowStateAnimator的对象)。在Choreographer的驱动下,逐个渲染所有的动画。 - mPolicy,WindowPolicyManager的一个实现。目前它只有PhoneWindowManager一个实现类。mPolicy定义了很多窗口相关的策略,可以说是WMS的首席顾问!每当WMS要做什么事情的时候,都需要向这个顾问请教应当如何做。例如,告诉WMS某一个类型的Window的ZOrder的值是多少,帮助WMS矫正不合理的窗口属性,会为WMS监听屏幕旋转的状态,还会预处理一些系统按键事件(例如HOME、BACK键等的默认行为就是在这里实现的),等等。所以,mPolicy可谓是WMS中最重要的一个成员了。 - mDisplayContents,一个DisplayContent类型的列表。Android4.2支持基于Wi-fi Display的多屏幕输出,而一个DisplayContent描述了一块可以绘制窗口的屏幕。每个DisplayContent都用一个整型变量作为其ID,其中手机默认屏幕的ID由Display.DEFAULT\_DISPLAY常量指定。DisplayContent的管理是由DisplayManagerService完成的,在本章不会去探讨DisplayContent的实现细节,而是关注DisplayContent对窗口管理与布局的影响。 下面的几个成员的初始化并没有出现在构造函数中,不过它们的重要性一点也不亚于上面几个。 - mTokenMap,一个HashMap,保存了所有的显示令牌(类型为WindowToken),用于窗口管理。在SampleWindow例子中曾经提到过,一个窗口必须隶属于某一个显示令牌。在那个例子中所添加的令牌就被放进了这个HashMap中。从这个成员中还衍生出几个辅助的显示令牌的子集,例如mAppTokens保存了所有属于Activity的显示令牌(WindowToken的子类AppWindowToken),mExitingTokens则保存了正在退出过程中的显示令牌等。其中mAppTokens列表是有序的,它与AMS中的mHistory列表的顺序保持一致,反映了系统中Activity的顺序。 - mWindowMap,也是一个HashMap,保存了所有窗口的状态信息(类型为WindowState),用于窗口管理。在SampleWindow例子中,使用IWindowSession.add()所添加的窗口的状态将会被保存在mWindowMap中。与mTokenMap一样,mWindowMap一样有衍生出的子集。例如mPendingRemove保存了那些退出动画播放完成并即将被移除的窗口,mLosingFocus则保存了那些失去了输入焦点的窗口。在DisplayContent中,也有一个windows列表,这个列表存储了显示在此DisplayContent中的窗口,并且它是有序的。窗口在这个列表中的位置决定了其最终显示时的Z序。 - mSessions,一个List,元素类型为Session。Session其实是SampleWindow例子中的IWindowSession的Bn端。也就是说,mSessions这个列表保存了当前所有想向WMS寻求窗口管理服务的客户端。注意Session是进程唯一的。 - mRotation,只是一个int型变量。它保存了当前手机的旋转状态。 WMS定义的成员一定不止这些,但是它们是WMS每一种功能最核心的变量。读者在这里可以线对它们有一个感性的认识。在本章后续的内容里将会详细分析它们在WMS的各种工作中所发挥的核心作用。