热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android系统服务——WMS与AMS

“可以毫不夸张的说,Android的framework层主要是由WMS、AMS还有View所构成,这三个模块穿插交互在整个framework中,掌握了它们之间的关系和每一个逻辑步骤,你对

“可以毫不夸张的说,Android的framework层主要是由WMS、AMS还有View所构成,这三个模块穿插交互在整个framework中,掌握了它们之间的关系和每一个逻辑步骤,你对framework的了解至少有百分之五十”。这是《Android源码与设计模式》作者的原话,最近学习WMS和AMS相关知识,的确非常复杂,这篇文章是在学习之初的初步整理,虽然内容不够细致,但对其也算有个宏观的了解。难点是其中具体的代码逻辑,也都在相应框架下给出了参考链接,日后的工作就是详细学习其中的代码逻辑,让整个框架在脑海中越来越细致、清晰。

AMS与WMS

在没有深入了解AMS与WMS前,对它俩负责的功能一直很模糊,一直搞不清区别。所以在深入理解其中之一时,先对它们在Android中各自负责的任务有个基本的了解和区分。

此外,AMS和WMS都属于Android中的系统服务,系统服务有很多,它们在Android体系架构中都属于同一层次,所以最好在深入了解它们各自的运行机理前,对系统的宏观架构能够有所掌握,也就是在自己的脑海中能够搭建一个简单的模型和框架,搞清楚它们在系统中所扮演的角色。每当我们学习了一个新的知识点,都是对这个模型的填充和细化,并能够较好的与之前所学的知识结合起来,既有利于理解,也有利于记忆,而且还能够感受到自己的积累与进步。

下面先简单对AMS与WMS作个简单的介绍,以解我之前的疑惑。

Activity与WIndow:

  • Activity只负责生命周期和事件处理
  • Window只控制视图
  • 一个Activity包含一个Window,如果Activity没有Window,那就相当于Service

AMS与WMS:

  • AMS统一调度所有应用程序的Activity
  • WMS控制所有Window的显示与隐藏以及要显示的位置

在视图层次中,Activity在WIndow之上,如下图,直接截取自我的另一篇博客:

 
Android应用程序窗口模型

下面进入到对WMS的介绍。

WMS

基础了解

WindowManagerService服务的实现是相当复杂的,毕竟它要管理的整个系统所有窗口的UI,而在任何一个系统中,窗口管理子系统都是极其复杂的。

作用

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

什么是Window

“Window”表明它是和窗口相关的,“窗口”是一个抽象的概念,从用户的角度来讲,它是一个“界面”;从SurfaceFlinger的角度来看,它是一个Layer,承载着和界面有关的数据和属性;从WMS角度来看,它是一个WIndowState,用于管理和界面有关的状态。

在《深入理解Android内核设计思想》一书中看到一个比喻非常好,整个界面就像由N个演员参与的话剧:SurfaceFling是摄像机,它只负责客观的捕捉当前的画面,然后真实的呈现给观众;WMS就是导演,它要负责话剧的舞台效果、演员站位;ViewRoot就是各个演员的长相和表情,取决于它们各自的条件与努力。可见,WMS与SurfaceFling的一个重要区别就是——后者只做与“显示”相关的事情,而WMS要处理对输入事件的派发。

Android支持的窗口类型很多,统一可以分为三大类,另外各个种类下还细分为若干子类型,且都在WindowManager.java中有定义。

  • Application Window
  • SystemWindow
  • Sub Window

类间关系

上面那些都是对WMS相关功能的介绍,对WMS有个感性的认识,现在开始进入相关类。

使用的设计模式

  • 桥接模式

关于桥接模式这里就不再讲解,参考《Android源码设计模式》第24章。

UML

 
 

代码逻辑

启动流程

………………
………………
………………

工作流程

  • 窗口大小和位置(X轴和Y轴)的计算过程
  • 窗口的组织方式
  • 输入法窗口的调整过程
  • 壁纸窗口的调整过程
  • 窗口Z轴位置的计算和调整过程
  • Activity窗口的启动窗口的显示过程
  • Activity窗口的切换过程
  • Activity窗口的动画显示过程

解惑

Q:WMS是系统服务,有SystemServer负责启动,启动时机相对较晚,那么在WMS运行之前,终端显示屏就一团黑?

A:在WMS启动之前,系统只需显示开机动画,它们都有特殊的方式来向屏幕输出图像,比如直接通过OpenGL ES与SurfaceFling的配合来完成。这也从侧面告诉我们,要想在Android上显示UI,并不一定要通过WMS。

AMS

基础了解

作用

  • 统一调度所有应用程序的Activity的生命周期
  • 启动或杀死应用程序的进程
  • 启动并调度Service的生命周期
  • 注册BroadcastReceiver,并接收和分发Broadcast
  • 启动并发布ContentProvider
  • 调度task
  • 处理应用程序的Crash
  • 查询系统当前运行状态

类间关系

设计模式

  • 代理模式

关于代理模式这里就不再讲解,参考《Android源码设计模式》第18章。

WMS与AMS设计模式的不同的思考…………

UML(类间关系)

 
 

从类图可以看出,ActivityManagerProxyActivityManagerNative都实现了IActivityManagerActivityManagerProxy就是代理部分,ActivityManagerNative就是实现部分,但ActivityManagerNative是个抽象类,并不处理过多的具体逻辑,大部分具体逻辑是由ActivityManagerService承担,这就是为什么我们说真实部分应该为ActivityManagerService

代码逻辑

启动流程

  • 第一阶段:启动ActivityManagerService
  • 第二阶段:调用setSystemProcess
  • 第三阶段:调用installSystemProviders方法。
  • 第四阶段:调用systemReady方法。

这里只给出了非常粗糙的整体流程,也没有深入的去了解,是因为觉得目前还用不着去理解这些内容,工作时用不到,而且即使现在明白了,如果不用,很快也会忘记。

如果想深入了解,可以参考《Android的设计与实现》,讲的挺好的,思路非常清晰。

工作流程

AMS的工作流程,其实就是Activity的启动和调度的过程,所有的启动方式,最终都是通过Binder机制的Client端,调用Server端的AMS的startActivityXXX()系列方法。所以可见,工作流程又包括Client端和Server端两个。

Client端流程

  • Launcher主线程捕获onClick()点击事件后,调用Launcher.startActivitySafely()方法。Launcher.startActivitySafely()内部调用了Launcher.startActivity()方法,Launcher.startActivity()内部调用了Launcher的父类Activity的startActivity()方法。
  • Activity.startActivity()调用Activity.startActivityForResult()方法,传入该方法的requestCode参数若为-1,则表示Activity启动成功后,不需要执行Launcher.onActivityResult()方法处理返回结果。
  • 启动Activity需要与系统ActivityManagerService交互,必须纳入Instrumentation的监控,因此需要将启动请求转交instrumentation,即调用Instrumentation.execStartActivity()方法。
  • Instrumentation.execStartActivity()首先通过ActivityMonitor检查启动请求,然后调用ActivityManagerNative.getDefault()得到ActivityManagerProxy代理对象,进而调用该代理对象的startActivity()方法。
  • ActivityManagerProxy是ActivityManagerService的代理对象,因此其内部存储的是BinderProxy,调用ActivityManagerProxy.startActivity()实质是调用BinderProxy.transact()向Binder驱动发送START_ACTIVITY_TRANSACTION命令。Binder驱动将处理逻辑从Launcher所在进程切换到ActivityManagerService所在进程。

Server端流程

启动Activity的请求从Client端传递给Server端后,便进入了启动应用的七个阶段,这里也是整理出具体流程,细节可以参考《Android的设计与实现》第十一章内容。

1)预启动

  • ActivityManagerService.startActivity()
  • ActivityStack.startActivityMayWait()
  • ActivityStack.startActivityLocked()
  • ActivityStack.startActivityUncheckedLocked()
  • ActivityStack.startActivityLocked()(重载)
  • ActivityStack.resumeTopActivityLocked()

2)暂停

  • ActivityStack.startPausingLocked()
  • ApplicationThreadProxy.schedulePauseActivity()
  • ActivityThread.handlePauseActivity()
  • ActivityThread.performPauseActivity()
  • ActivityManagerProxy.activityPaused()
  • completePausedLocked()

3)启动应用程序进程

  • 第二次进入ActivityStack.resumeTopActivityLocked()
  • ActivityStack.startSpecificActivityLocked()
  • startProcessLocked()
  • startProcessLocked()(重载)
  • Process.start()

4)加载应用程序Activity

  • ActivityThread.main()
  • ActivityThread.attach()
  • ActivityManagerService.attachApplication()
  • ApplicationThread.bindApplication()
  • ActivityThread.handleBindApplication()

5)显示Activity

  • ActivityStack.realStartActivityLocked()
  • ApplicationThread.scheduleLaunchActivity()
  • ActivityThead.handleLaunchActivity()
  • ActivityThread.performLaunchActivity()
  • ActivityThread.handleResumeActivity()
  • ActivityThread.performResumeActivity()
  • Activity.performResume()
  • ActivityStack.completeResumeLocked()

6)Activity Idle状态的处理

7)停止源Activity

  • ActivityStack.stopActivityLocked()
  • ApplicationThreadProxy.scheduleStopActivity()
  • ActivityThread.handleStopActivity()
  • ActivityThread.performStopActivityInner()


作者:thinkChao
链接:https://www.jianshu.com/p/47eca41428d6
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
author-avatar
mobiledu2502886443
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有