作为Android应用程序开发者,平时接触最多的就是Activity,而很少用到ActivityManagerService和WindowManagerService。本文,通过应用程序开始启动到第一个Activity的View内容在手机屏幕上完全展示出来的过程讲述Activity、ActivityManagerService、WindowManagerService三者之间如何发生关系的。
Activity运行在应用程序进程中,ActivityManagerService和WindowManagerService运行在SystemServer进程中,所以Activity与ActivityManagerService和WindowManagerService联系就需要跨进程通信,这里用的跨进程通信方式是Android系统提供的Binder通信方式;读者需要对Binder通信有一个基本的了解才能更好的理解Activity、ActivityManagerService、WindowManagerService他们三者之间是如何联系的。
一 Activity、ActivityManagerService、WindowMangaService发生联系相关的类
首先,看一下从开始启动应用程序到第一个Activity的View内容在手机屏幕上完全展示出来的过程中遇到的相关的类。
红色框里面的类是在Application进程中用到的,绿色框里面的类是在WindowManagerService中用到的类,蓝色框里面的类是在ActivityManagerService中用到的类。下面结合Android提供的官方文档和笔者的个人理解对图中的各个类先做个简单的描述。
1.Application进程中相关的类:
1).Activity 大家最了解,是我们在Android应用程序中处理业务逻辑的地方,对应于MVVC模式中的VC。
2).ActivityThread 官方解释This manages the execution of the main thread in an application process, scheduling and executing activities, broadcasts, and other operations on it as the activity manager requests。就是在主线程中运行这个类,按照ActivityManagerService的要求来调度执行activity、broadcasts以及其它操作。
3).ApplicationThread 用来进行跨进程通信的,在一个应用启动的时候需要把ApplicationThread的对象传递给ActivityManagerService.
4).ContextImpl 官方解释Common implementation of Context API, which provides the base context object for Activity and other application components。实现了Context的接口,提供一些公共的操作,Context中的大部分逻辑都是由ContextImpl来完成的。
5).Instrumentation 监控Activity与系统的交互操作,相当于是系统运行日志。
6).ViewRootImpl 官方解释The top of a view hierarchy, implementing the needed protocol between View and the WindowManager. This is for the most part an internal implementation
detail of {@link WindowManagerGlobal}。主要用来管理Activity里View树的绘制。
7).W是ViewRootImpl的一个内部类,继承自IWindow.Stub主要用于WindowManagerService和Application进程通信,同时也用来标识Application进程里的一个对应的Window。
8).PhoneWindow 官方解释很短 Android-specific Window。用来表示Android系统指定的一个window,对应于一个指定的屏幕。
9).DecorView 继承自FrameLayout,是PhoneWindow的一个成员对象用来放置Activity的一个View树。
10).ActivityClientRecord 在Application进程内描述一个Activity相关的信息,与ActivityManagerService里的ActivityRecord一一对应。
11).WindowManagerImpl 官方解释Provides low-level communication with the system window manager for operations that are bound to a particular context, display or parent window.
Instances of this object are sensitive to the compatibility info associated with the running application.Android系统提供的与WindowManagerService的低层的通信,他需要绑定上下文环境、显示屏幕等。
12).WindowManagerGlobal 官方解释 Provides low-level communication with the system window manager for operations that are not associated with any particular context. This class is only used internally to implement global functions where the caller already knows the display and relevant compatibility information for the operation. For most purposes, you should use {@link WindowManager} instead since it is bound to a context. WindowManagerGlobal与WindowManagerImpl 的区别是不需要绑定上下文环境、显示屏幕等,WindowManagerGlobal是具体干活的,WindowManagerImpl 绑定了相关的上下文环境、显示屏幕等后会调用WindowManagerGlobal进行具体的处理。一个Application进程中分别有一个WindowManagerImpl实例和WindowManagerGloba实例。
2.AMS(下面ActivityManagerService都简称为AMS)中相关的类:
1).ActivityManagerService 负责管理Activity的生命周期的,AMS还借助ActivityStack是来把所有的Activity按照后进先出的顺序放在一个堆栈中。在Android系统中只有一个AMS的实例,他负责管理系统中所有的Activity,管理、调度这些Activity的生命周期。在Android系统系统的过程中,在SystemServer进程中把AMS服务启动起来,注册到ServiceManager中。
2).ProcessRecord 官方解释 Full information about a particular process that is currently running。用来描述一个Activity所运行在的进程的信息。
3).ActivityRecord 官方解释 An entry in the history stack, representing an activity。在AMS中描述一个Activity.
4).Token 是ActivityRecord的一个内部类,继承自IApplicationToken.Stub,在AMS、WMS、以及应用程序进程中都此对象标识一个Activity。
5).TaskRecord Activity栈,内部维护一个ArrayList。
6).ActivityStack 并不是一个Activity栈,真正意义上的Activity栈是TaskRecord,这个类是负责管理各个Activity栈,内部维护一个ArrayList。
7).ActivityStackSupervisor 内部持有一个ActivityStack,而ActivityStack内部也持有ActivityStackSupervisor,相当于ActivityStack的辅助管理类。
3.WMS(下面WindowManagerService都简称为WMS)中相关的类:
1).WindowManagerService 负责管理系统中所有的窗口,包括Activity的窗口、壁纸窗口、输入法窗口、弹窗子窗口等,即管理屏幕上展示上的一切窗口。在Android系统系统的过程中,在SystemServer进程中也把WMS服务启动起来,注册到ServiceManager中。
2).Session 官方解释 This class represents an active client session. There is generally one Session object per process that is interacting with the window manager。应用程序进程通过Session对象与WMS进行通信,每个应用程序进程中有一个Session对象。
3).WindowState 官方解释 A window in the window manager。在WMS中描述一个Window。
4).WindowToken 官方解释 Container of a set of related windows in the window manager. Often this is an AppWindowToken, which is the handle for an Activity that it uses to display windows. For nested windows, there is a WindowToken created for the parent window to manage its children.用来描述WMS中一个Window的信息。
5).AppWindowToken 官方解释 Version of WindowToken that is specifically for a particular application (or really activity) that is displaying windows.用来描述一个Activity在WMS中对应的Window的信息。
6).SurfaceSession 官方解释 An instance of this class represents a connection to the surface flinger, from which you can create one or more Surface instances that will be composited to the screen.通过该对象能与SurfaceFlinger服务通信,来创建一个Surface.
二 Activity AMS WMS之间的通信模型
前面讲了,Activity运行在应用程序进程中,而AMS、WMS运行在SystemServer进程中,他们之间的通信是跨进程通信,这里的跨进程通信使用的是Binder通信方式。
图中,灰色椭圆形描述的是Binder的实体,白色椭圆形描述的是Binder实体的引用,每个白色的椭圆形都要指向一个灰色的椭圆形,即每个Binder实体的引用都要指向一个Binder实体。由于Binder通信是单向的,所以在如图所示的通信模型中会双向的持有不同Binder实体的引用。
在两个进程间通信的时候,发起请求方在请求之前需要先拿到被请求方的一个Binder实体的引用。一个进程拿到Binder实体的引用有两种方式:
1) 通过ServiceManager查找,例如在应用程序进程中就是通过这种方式持有AMS实体的引用的。
2) 被请求方向请求方注册,例如在应用程序的主线程启动时, ActivityThread 会把ApplicationThread实体的引用注册到AMS中。
为什么会有两种方式呢?这与各个进程启动的顺序有关,Android系统启动的时候会启动SystemServer进程,在SystemServer进程中把AMS、WMS等所有的服务启动起来分别注册到ServiceManager中;此时第一个应用程序进程(Launcher进程)还没有启动,所以在应用程序进程启动的时候可以通过第一种方式获得各个服务的Binder实体的引用。在应用程序进程启动起来后,新建的Binder实体,已经启动起来的系统服务是没有办法通过第一种方法获得其引用的,所以需要通过第二种方法,把其引用注册到请求方。
三 Activity AMS WMS之间具体是如何发生关系的
下面通过Activity开始启动到Activity的整个View在屏幕上展示出来的过程,讲述一下Activity AMS WMS之间具体是如何发生关系的。
图中红色字体表示的是一些重要对象的创建时机。
下面简单描述一下这个过程:
1.在Launcher上点击一个应用图标,即启动一个App。Launcher的Activity则调用startActitity()方法,一步步的处理后会通过AMS的引用告诉AMS他要启动一个新的Activity。
2.在AMS中首先会创建一个ActivityRecord对象,以及一个Token对象,然后进行一些准备工作,并检查是否需要新建一个任务,由于我们是启用了一个新的App,所以需要新创建一个TaskRecord对象,然后把新创建的Token对象传给WMS,调用到WMS中。
3.在WMS中根据穿过来的Token引用,创建一个AppWindowToken对象,又返回到AMS中。
4.在AMS中,发现当前任务栈最顶端的Activity是Launcher的Activity, AMS通过Launcher进程的ApplicationThread的引用通知Launcher进程当前Activity要进入到paused状态。
5.在Launcher进程中,binder线程池收到信息后,把消息传递到主线程中,调用Launcher当前Activity的onPause()方法,然后通过AMS的引用告诉AMS他已经把Activity进入到Paused状态了。
6.在ActivityStack中首先修改一下全局的ActivityRecord对象的状态,然后AMS判断是否启动一个新的进程,由于启动了一个新的App,所以需要启动一个新的进程,即启动MyApplication进程,并把ActivityThread类装载到新的进程中。
7.在MyApplication进程的主线程中运行ActivityThread类的main()函数,初始化一些全局的信息,新建一个ApplicationThread对象,通过AMS的引用通知AMS要把ApplicationThread的引用注册到AMS中。
8.AMS把MyApplication进程的ApplicationThread引用注册后,调用realStartActivityLocked()方法继续启动MyApplicaton里默认的Activity,在这个函数中调用WMS的setAppVisibility()方法。
9.在WMS中设置新的Activity的可见性,然后返回到AMS中。
10.在AMS中执行完realStartActivityLocked()方法后,通过MyApplication进程的ApplicationTread的引用,通知MyApplication要启动默认的Activity。
11.在MyApplication进程中,binder线程根据AMS传过来的ActivityRecord对象创建一个ActivityClientRecord对象,在应用进程中表示要启动的Activity。然后把消息转给主线程,开始启动一个Activity。首先对要启动的Activity实例化,接着为该Activity新建一个PhoneWindow对象,接下来调用Activity的onCreate()和onResume()方法。然后在ViewRootImpl中获取Session实体的引用,通过该Session引用告诉WMS添加该Activity的Window,同时要把ViewRootImpl的W对象注册到WMS中。
12.在WMS中,首先把W实体的引用注册到其中,然后创建一个WindowState对象。
13.回到MyApplication进程中,ViewRootImpl开始执行performTraversals() ,在其中通过Session引用通知WMS要布局窗口。
14.在WMS中,执行relayoutWindow(),然后创建一个Surface。
15.在MyApplication进程中,ViewRootImpl根据返回的Surface对象,也创建一个Surface对象,这里的Surface以及WMS中的Surface,共同指向SurfaceFlinger中的一块内存。接着执行measure、layout、draw等方法,最后通过Surface把绘制好的画布传递到SurfaceFlinger中进行在屏幕上展示。
四 整体UML图
按照Activity启动这条主线,整理了相关类的UML图,有助于从宏观上理解这三部分之间以及每一部分内部的联系。遗憾的是,图压缩后有点不清晰,有想要大图的同学,可以留言单独发大图哈。