进阶之光笔记二

第五章 理解上下文Context

Context的关联类

Context使用场景:
1.使用Context调用方法,比如启动Activity、访问资源、调用系统级服务
2.调用方法时传入Context,比如弹出Toast、创建Dialog
Activity/Service/Application都间接的继承自Context,所以我们熟知的计算一个项目中多少个Context = Activity个数+Service个数+1(Application)
Context是一个抽象类,其实现是ContextImpl。与Context相关联的类,除了ContextImpl,还有ContextWrapper/ContextThemeWrapper/Activity等,其继承关系如下:


ContextImpl使用了装饰模式,ContextWrapper是其装饰类,其作用是方法传递,其中几乎所有的方法都是ContextImpl里定义好的。 ContextThemeWrapper、Service和Application都继承自ContextWrapper,因为Activity需要主题,所以继承了ContextThemeWrapper。
Context的关联类采用了装饰模式,主要有一下几个优点:
1.使用者,比如Service能够能方便的使用Context
2.如果ContextImpl发生了变化,它的装饰类ContextWrapper不需要做任何修改。
3.通过组合而非继承的方式,扩展了ContextImpl的功能。在运行时选择不同的装饰类、实现不同的功能,解耦。

Application Context的创建过程[也就是Application创建过程]

要看Context的创建过程,那么首选肯定是Application Context。
Activity在启动首个Activity的时候,会调用ActivityThread内部类ApplicationThread里的scheduleLaunchActivity方法。该方法内部会向H类发送LAUNCH_ACTIVITY类型的消息,目的就是为了将启动Activity的逻辑放在主线程中的消息队列中。接下来得处理逻辑也肯定就是H类中handleMessage里的LAUNCH_ACTIVITY分支了。

image.png

接着调用handleLaunchActivity方法,其内部调用的performLaunchActivity的方法中有一行代码:
image.png

调用LoadedApk中的makeApplication方法来创建Application
image.png

接着调用ContextImpl的createAppContext方法来创建ContextImpl,接着在ActivityThread里Instrumentation的newApplication方法中传入ClassLoader和我们刚创建好的ContextImpl,创建Application对象,接着app.setOuterContext中传入我们创建好的Application。这样ContextImpl中也会包含Application的引用。
newAppliaction中通过反射来创建Application,并调用了Application的attach方法,将ContextImpl传进去,最后返回新创建的Application。attach方法的作用就是使Application可以使用Context的方法,这样Application才可以用来代表Application Context。

Application Context的创建流程如上所述。

Application Context的获取过程

我们通过getApplicationContext方法来获得Application Context:

image.png

这里的mBase其实就是ContextImpl,但是此文件属于保护文件,在as中看不到:
image.png

只能下载下来源码,或者在线上看了
image.png

所以getApplicationContext实际就是调用ContextImpl里的getApplicationContext,此方法中如果LoadedApk类型的mPackageInfo不为空,则调用LoadedApk的getAppliaction,否则调用ActivityThread里的同名方法。因为应用程序已经启动,LoadedApk不为空,所以最后取的还是LoadedApk里的getApplication。就是之前LoadedApk的makeAppliaction创建出来的Application。

Activity的Context创建过程

Activity的Context的创建过程就是在启动过程中的一部分:

image.png

Activity启动过程中到了应用程序主进程时,会调用ActivityThread的内部类ApplicationThread的scheduleLaunchActivity,发LAUNCH_ACTIVITY消息给H类,再其handleMessage方法中调用ActivityThread的handleLaunchActivity,接着就是之前说的performLaunchActivity了,这里面进行了很多操作:
image.png

调用Instrumentation的newActivity方法来创建Activity。
通过createBaseContextForActivity方法来创建Activity的ContextImpl.其内部会调用ContextImpl的createActivityContext。

image.png

接着调用ContextImpl的setOuterContext方法将刚才创建的Activity实例赋值到ContextImpl的成员变量中去,这样ContextImpl也能访问Activity的变量了。
image.png

接着调用Instrumentation的callActivityOnCreate方法来调用Activity的onCreate方法。
回到performLaunchActivity方法中,看一下Activity的attach方法执行了哪些重要逻辑:
image.png

image.png

在attach方法中创建了PhoneWindow,并为其设置WindowManager。这样Activity就可以通过getWindowManager来获取WindowManager。
总而言之:
在启动Activity的过程中创建ContextImpl,并赋值给ContextWrapper的成员变量mBase。Activity继承自ContextWrapper的子类ContextThemeWrapper,这样Activity中就可以使用Context中定义的方法了。

Service的Context创建过程

Service的Context创建过程与Activity的Context创建过程类似,是在Service的启动过程中被创建的。之前在分析Service的创建过程中,ActivityThread的内部类ApplicationThread会调用scheduleCreateService方法来启动Service,此方法内部会向H类发送CREATE_SERVICE类型的消息,在其handleMessage中对此类型的消息进行处理,调用ActivityThread的handleCreateService方法:


image.png

其内部会调用ContextImpl的createAppCnotext方法创建ContextImpl,并将其传入service的attach方法中:


image.png

将ContextImpl赋值给ContextWrapper的Context类型的mBase,这样在ContextWrapper中就可以使用Context的方法,而Service继承自ContextWrapper,同样可以使用Context方法。Service和ContextImpl相互持有,可以互相调用了。

第六章 理解ActivityManagerService

AMS处理的逻辑多复杂,并不是孤军奋战,而是有一些类和它并肩作战,这些类会帮助AMS完成相关逻辑,AMS和这些共同奋战的类就称为AMS家族。7.0和8.0相关处理有很大区别,我们主要看8.0。

8.0 AMS家族

我们以Activity启动过程为例,在Activity的启动过程中会调用到Instrumentation的execStartActivity方法:

image.png

其中会调用到ActivityManager的getService方法:
image.png

getService方法调用了IActivityManagerSingleton的get方法,IActivityManagerSingleton是一个Singleton类。在Singleton的create方法中,采用AIDL.获取到IBinder类型的AMS引用。然后转换成IActivityManager类型的对象。IActivityManager.java类是有AIDL工具在编译时自动生成的,AMS只需要继承IActivityManger.Stub类并实现对应的方法就可以了。IActivityManager就是AMS的本地代理。
image.png

一句话总结:
ActivityManager的getService方法会得到IActivityManager,AMS只需要继承IActivityManger.Stub类,就可以和ActivityManger实现进程间通信了。

AMS的启动过程

AMS的启动是在SystemServer进程中启动的,我们直接从SystemServer的main方法开始讲起。

image.png

image.png

之前讲过SystemServer的run方法,这里我们再看一下。
首先通过System.loadLibrary("android_servers")加载动态库libandroid_servers.so.接下来创建SystemServiceManager,此类会对系统的服务进行创建、启动和生命周期管理。startBootstrapServices方法会用我们上面创建的SystemServiceManager启动ActivityManagerService/PowerManagerService/PackageManagerService等服务。 startCoreServices方法则启动了BatteryService/DropBoxManagerService/UsageStatsService和WebViewUpdateService.
startOtherService则启动了CameraService、AlarmMangerService等服务。
官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务。
我们主要看引导服务AMS是如何启动的,也就是startBootstrapServices方法:
image.png

image.png

其内部调用了SystemServiceManger的startService方法,传了一个SystemService类型的参数ActivityManagerService.Lifecycle.class,并调用此参数的onStart方法来启动service对象。这个service对象也就是Lifecyle里的具体实现,可以看一下:

image.png

在Lifecycle的构造方法中创建了AMS实例。当调用SystemService类型的service的onStart方法时,实际上就是调用了AMS的start方法。此类中getService方法返回的就是AMS实例。所以我们最初的SystemServer的startBootstrapServices里的
mSystemServiceManager.startSerivce(ActivityManagerService.Lifecycle.class).getService()实际上得到的就是AMS实例。

AMS与应用程序进程

这里做一下简单总结,代码就不跟了哈,之前也讲过了。
① 启动应用程序进程时AMS会检查这个应用程序需要的应用程序进程是否存在。
②如果需要的应用程序进程不存在,AMS就会请求Zygote进程创建需要的应用程序进程。

AMS重要的数据结构

image.png

AMS涉及到了很多数据结构,我们主要看一下ActivityRecord/TaskRecord/ActivityStack这些是Activty任务栈模型的基础。
1.ActivityRecord
用来描述一个Activity,其内部记录了Activity的所有信息,它是在Activity启动时创创建的。具体是在ActivityStarter的startActivity方法里。
其存储的信息里包括:AMS的引用、AndroidManifest节点信息、Activity状态、Acitivty资源信息和Activity进程相关信息。以及该ActivityRecord所在的TaskRecord!

2.TaskRecord
TaskRecord用来描述一个Activity任务栈,其内部存储了任务栈的所有信息。包括任务栈的唯一标识符、任务栈中的Activity记录和AMS的引用等。需要注意的是其中含有ActivityStack。也就是当前Activity任务栈所属的ActivityStack.
3.ActivityStack
此类是一个管理类,用来管理系统的所有Activity。其内部维护了Activity的所有状态、特殊状态的Activity以及和Activity相关的列表等数据。ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建。

image.png

image.png

ActivityStackSupervisor中有多种ActivityStack实例!ActivityStack并不是只有一个!
image.png

其中mHomeStack用来存储Launcher App的所有Activity。mFocusedStack表示当前正在接收输入或启动下一个Activity的所有Activity。mLastFocusedStack表示此前接收输入的所有Activity。

①在ActivityStack中通过枚举存储了Activity的所有的状态。也就是ActivittState。
②ActivityStack中定义了一些特殊状态的activity

image.png

比如正在暂停的activity、上一个已经暂停的activity,最近一次没有历史记录的activity。
这些特殊状态都是ActivityRecord类型的。
③在ActivityStack中维护了很多ArrayList,这些ArrayList中的元素类型主要有ActivityRecord和TaskRecord.
ActivityStack维护了元素类型为TaskRecord的列表,这样ActivityStack和TaskRecord就有了关联。TaskRecord中又有ActivityStack。

Activity栈管理

1.Activity任务栈模型
Activity任务栈并不是凭空想象的,它是由多种数据结构共同组成的。之前说的ActivityRecord、TaskRecord和ActivityStack,它们就是Activity任务栈模型的重要组成部分。

image.png

ActivityRecord用来记录一个Activity的所有信息,TaskRecord中包含了一个或多个ActivityRecord。TaskRecord用来表示Activity的任务栈,用来管理栈中的ActivityRecord,ActivityStack又包含了一个或多个TaskRecord。它是TaskRecord的管理者。Activity栈管理就是建立在Activity任务栈模型之上的。有了栈管理,我们可以对应用程序进行操作,应用可以复用自身应用中以及其他应用的Activity,节省了资源。
2.Launch Mode (启动模式)
四种启动模式:
①standard:默认模式,每次启动Activity都会创建一个新的Activity实例。
②singleTop:栈顶复用.如果要启动的Activity在栈顶,直接复用,并调用onNewIntent方法。如果要启动的Activity不在栈顶,则会重新创建Activity的实例。
③singleTask:栈内复用。如果Activity已经存在于它想要归属的栈内,不会重新创建实例,而是将栈内该Activity上的所有Activity出栈,同时调用该Activity的onNewIntent方法。如果要启动的Activity不存在于它想在的栈内中,并且该栈存在,则会重新创建该Activity的实例。如果要启动的Activity想要归属的栈不存在,则先创建新栈,然后创建该Activity实例并压入到新栈中。
④singleInstance: 启动Activity时,首先创建一个新栈,然后创建该Activity实例并压入新栈中。
3.Intent的FLAG
在Intent中定义了很多FLAG,其中有几个Flag也可以设定Activity的启动方式.如果Launch Mode和FLAG设定的Activity的启动方式有冲突,则以FLAG设定的为准。
FLAG_ACTIVITY_SINGLE_TOP:和Launch Mode中的singleTop效果一样
FLAG_ACTIVITY_NEW_TASK:和Launch Mode中的singleTask效果一行
FLAG_ACTIVITY_CLEAR_TOP:Launch Mode没有与此对应的模式,如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity出栈。singleTask默认有此标记位的效果。
除了这三个,还有很多:
FLAG_ACTIVITY_NO_HISTORY
FLAG_ACTIVITY_MULTIPLE_TASK
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
FLAG_ACTIVITY_BROUGHT_TO_FRONT
FLAG_ACTIVITY_CLEAR_TASK:这个需要和FLAG_ACTIVITY_NEWt_TASK一同使用才有效果,用于清除与启动的Activity相关栈的所有其他 Activity。

taskAffinity ????

我们可以在AndroidManifest.xml中设置android:taskAffinity,用来指定Activity希望归属的栈,在默认情况下,同一个应用程序的所有的Activity都有着相同的taskAffinity。taskAffinity在下面两种情况中会产生效果:
1.taskAffinity与FLAG_ACTIVITY_NEW_TASK或者singleTask配合。如果新启动的Activity的taskAffinity和栈的taskAffinity相同则加入到该栈中;如果不同,就会创建新栈。
2.taskAffinity与allowTaskReparenting配合。如果allowTaskReparenting为true,说明Activity具有转移的能力。

第七章 理解WindowManager

为了更好地理解WMS,我们需要先了解WindowManager的相关知识。

Window、WindowManager和WMS

Window是一个抽象类,具体实现是PhoneWindow,对View进行管理。
WindowManager是一个接口类,继承自接口ViewManager,用来管理Window,实现类是WindowManagerImpl.


image.png

image.png

如果需要对Window(View)进行添加、更新和删除操作就可以使用WindowManager。WindowManager会将具体的工作交给WMS来处理。WindowManager和WMS通过Binder来进行跨进程通信!WindowManager所提供的功能最终都会由WMS进行处理!
Window的实体其实也是View。

WindowManager的管理类

上面说过,WindowManager是一个接口类,继承自接口ViewManager。ViewManager中定义了三个方法,分别用来添加、更新和删除View.:

image.png

Window是一个抽象类,其具体实现是PhoneWindow。 在Activity启动过程中会调用ActivityThread的performLaunchActivity方法,performLaunchActivity方法中又会调用Activity的attach方法,PhoneWindow就是在Activity的PhoneWindow中创建的:
image.png

image.png

image.png

image.png

如上图所示,在Activity的attach方法中创建了PhoneWindow,并调用setWindowManager方法,此方法实现在父类Window中:
image.png

如果传进来的WindowManager为空,会调用Context.getSystemService方法,并传入服务的名称Context.WINDOW_SERVICE.具体实现也就在ContextImpl中了:
image.png

内部会调用SystemServiceRegistry的getSystemServiceName方法:
image.png

从一个名为SYSTEM_SERVICE_FETCHERS的HashMap中获取对应名字的Service。
在SystemServiceRegistry的静态代码块中,会多次调用registerService将系统服务的名字和对应的实现类存到此HashMap中。
image.png

image.png

这里可以看到创建一个WindowManagerImpl。
接着回到setWindowManager中,获取到WindowManager实现类后,调用其createLocalWindowManager方法,将当前window作为参数传入。这样WindowManagerImpl中也就持有了Window.可以对Window进行各种操作。
比如调用addView方法:
image.png

image.png

调用的就是WindowManagerImpl的addView方法,而WindowManagerImpl作为WindowManager的实现类,其实没有实现什么功能,而是将功能委托给了WindowManagerGlobal,这里用到的是桥接模式。
这里WindowManagerGlobal是一个单例,一个进程中只有一个实例。

通过上面分析,简单的整理一下:


image.png

PhoneWindow继承自Window,Window通过setWindowManager方法与WindowManager发生关联。WindowManager继承自接口ViewManager,WindowManagerImpl是WindowManager接口的实现类,但是具体的功能都会委托给WindowManagerGlobal,这里用到的是桥接模式。

Window的属性

WMS是Window的最终管理者,Window好比是员工,WMS是老板。为了方便管理员工,老板制定的规章制度就是Window的属性,它们被定义在WindowManager的内部类LayoutParams中。其中与实际开发最密切的有3种:
Type(Window的类型)
Flag(Window的标志)
SoftInputMode(软键盘相关模式)

Window分为3大类型:
Application Window(应用程序窗口)
Sub Window(子窗口)
System Window(系统窗口)

Window类型及显示次序

1.应用程序窗口:
应用程序窗口的Type值范围为1~99.
2.子窗口
顾名思义,不能独立存在,必须依附在其他窗口上才行,PopupWindow就属于子窗口。Type值范围在1000~1999之间。
3.系统窗口
Toast/输入法窗口/系统音量窗口/系统错误窗口,都属于系统窗口。Type值范围为2000~2999之间。
4.窗口显示次序。
一般情况下,Type值越大则Z-Oder排序越靠前,就越靠近用户。实际情况比这要复杂,比如多个窗口的Type相同时,WMS会结合各种情况给出最终的排序。

Window的标志

Window的标志就是Flag,用于控制Window的显示,定义在WindowManager的内部类LayoutParams,一共有20多个。这里说几个常用的。

FLAG_KEEP_SCREEN_ON:只要窗口可见,屏幕就会一直亮着。
FLAG_FULLSCREEN: 隐藏所有的屏幕装饰窗口,比如在游戏,播放器中的全屏显示。
FLAG_SHOW_WHEN_LOCKED:窗口可以在锁屏的窗口之上显示。
FLAG_IGNORE_CHEEK_PRESSES:当用户的脸贴近屏幕时(比如打电话),不会去响应此事件。

getWindow()是Activity里的方法。Window的Flag有3种方法:
①Window的addFlags方法:

Window mWindow = getWindow();
mWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

②Window的setFlags方法(addFlags方法内部也会调用setFlags方法)
③给LayoutParams设置Flag,并通过WindowManager的addView方法进行添加。

WindowManger.LayoutParams params = new WindowManager.LayoutParams();
params.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN;
WindowManager mWindowManager = (WindowManager) getSystemServices(Context.WINDOW_SERVICE);
TextView mTextView = new TextView(this);
mWindowManager.addView(mTextView,params);
软键盘相关模式

有六种,这里只提两种最常用的:
①SOFT_INPUT_ADJUST_RESIZE:当软键盘弹出时,窗口会调整大小
②SOFT_INPUT_ADJUST_PAN:当软键盘弹出时,窗口不需要调整大小,要确保输入焦点是可见的。

软键盘的模式可以在清单文件中标明,也可以在代码中手动添加.
1.在清单文件中添加:
android:windowSoftInputMode
2.在代码中添加
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

Window的操作

Window的添加、更新和删除的操作,统称为Window的操作。对Window的操作分为两部分:
1.WindowManager处理部分
2.WMS处理部分
对于Window的操作,最终都会交由WMS来进行处理。

本节就是简单说一下WindowManager的处理部分,我们主要看窗口的添加过程:
可以以状态栏StatusBar为例。
在StatusBarWindowManager的add方法里:

image.png

调用了WindowManager的addView方法,最终会调用到WindowManagerGlobal的addView方法:
image.png

在此方法里会创建ViewRootImpl,添加窗口这一操作是通过ViewRootImpl来进行的。
ViewRootImpl身负了很多职责:
①View树的根并管理View树
②触发View的测量、布局和绘制
③输入事件的中转站
④管理Surface
⑤负责和WMS进行进程间通信

可以看到,每一项都十分重要!!!!!
接下来就可以查看ViewRootImpl的setView方法了:
image.png

image.png

可以看到这里面是个同步代码块,setView方法中会调用IWindowSession的addToDisplay方法,这个一个Binder对象,是Client端的代理,用于进程间通信。Server端的实现为Session。之前的逻辑都是本地进程的,而Session的addToDisplay方法则运行在WMS所在的进程(SystemServer进程)中。

image.png

在addToDisplay方法中调用WMS的addWindow方法,WMS会为这个添加的窗口分配Surface,并确定窗口显示次序。负责显示界面的是画布Surface,而不是窗口本身。WMS会将所管理的Surface交由SurfaceFlinger处理,SurfaceFlinger会将这些Surface混合并绘制到屏幕上。

Activity的添加过程

在Activity启动时,最后会调用到ActivityThread里的handleResumeActivity方法,此方法里:


image.png

会得到ViewManager类型的wm对象,调用addView方法,也就是WindowManager的addView方法,之前说过WindowManager继承ViewManager。其实现就是在WindowManagerImpl中实现的。最后还是会调用WindowManagerGlobal中去。之后的流程就是我们前面分析的那些了。

Window的更新过程

更新过程与添加过程类似。需要调用ViewManager的updateViewLayout方法,实现在WindowManagerImpl里,具体处理还是WindowManagerGlobal.(这个桥接模式搞得Global同学好累)里的updateViewLayout:


image.png

根据索引拿到ViewRootImpl对象,调用其setLayoutParams方法更新参数。


image.png

在setLayoutParams方法的最后会调用scheduleTraversals方法,这个方法最终会调用到ViewRootImpl里的performTraversals()方法:
image.png

800多行的方法...emm...做个简单的总结吧
最终会调用WMS的relayoutWindow方法。同时调用了performMeasure、performLayout、performDraw方法,它们的内部又会调用View的measure、layout和draw方法,这样就完成了View的工作流程。在此方法中更新了Window视图,又执行了Window中的View的工作流程,这样就完成了Window的更新!删除过程留到下一章再讲。

理解WindowManagerService

主要讲解WMS的职责、WMS的创建过程、WMS的重要成员以及Window的添加和删除过程。

WMS的职责

1.窗口管理
WMS是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理的。
2.窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫酷一些。窗口动画由WMS的动画子系统来负责,也就是WindowAnimator.
3.输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理。
4.Surface管理
窗口并不具有绘制的功能,因此每个窗口都需要一块Surface来供自己绘制,为每个窗口分配Surface是由WMS来完成的。

本章主要讲窗口管理。

WMS的创建过程

WMS是在SystemServer进程中创建的。

image.png

image.png

在①处加载了so动态库libandroid_servers.so。在③处创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
image.png

最重要的是这三个方法:
startBootstrapServices:启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。
startCoreServices:启动了BatteryService、WebViewUpdateService等。
startOtherService:启动了CameraService、AlarmManagerService等。
这些服务的父类都是SystemService
这三个方法对应三种服务:引导服务、核心服务和其他服务。
其他服务是一些非紧要和不需要立即启动的服务。WMS就是其他服务中的一种(没想到连个coreService都没混到)
image.png

在startOtherServices中创建的其他服务大概有100多个,上图只借去了WMS相关的代码。
通过调用WMS的main方法,创建WMS,其中的一个参数是我们创建的InputManagerService,也就是IMS。WMS的main方法是运行在SystemServer的run方法中的,换句话说就是运行在"system_server"线程中的。接着调用SystemService的addService方法将WMS和IMS注册到ServiceManager中。这样如果有客户端想要使用WMS,就需要先去ServiceManager中查询信息,然后根据信息与WMS所在的进行建立通信通路,客户端就可以使用WMS了。接下来我们看一下WMS的main方法:
image.png

调用DisplayThread的getHandler方法获取到该线程的handler对象,毫无疑问这个是一个HandlerThread的子类,是一个单例的前台线程。在handler的runWithScissors方法中new了一个WindowManagerService,说明WMS的创建试运行在android.display线程中的。
runWithScissors方法中,根据每个线程只有一个Loopper的原理来判断当前的线程也就是system_server线程是否是Handler所指向的线程,也就是android.display线程。如果是,直接执行run方法;如果不是则调用BlockingRunnable的postAndWait方法。很明显,这里走的是postAndWait方法。
image.png

我们看一下postAndWait里具体的实现:
image.png

image.png

调用handler的post方法,将当前的BlockingRunnable添加到Handler的任务队列中。接着通过判断标志位mDone,为false的时候,会一直调用wait方法使得当前线程也就是system_server线程进入等待状态。而mDone就是在BlockingRunnable的的run方法执行完毕后,在finally中将mDone置为true,同时调用notifyAll方法唤醒处于等待状态的线程。这样下面的wait方法就会停止调用。简而言之,system_server线程等待的就是android.diaplay线程,一直等到android.display线程执行完毕后,再执行system_serve线程。这是因为android.display线程内部执行了WMS的创建,而WMS的创建优先级更高。WMS的创建就到此为止。接下来看一下WMS的构造方法里做了哪些工作:
image.png

image.png

image.png

保存了传递进来的IMS,这样WMS就持有了IMS的引用。同时通过ActivityManger.getService()方法获得了AMS的引用。在8.0的时候还会在构造方法中直接调用initPolicy方法初始化窗口管理策略的接口类:WindowManagerPolicy(WMP),定义一个窗口策略所要遵守的通用规范。但是在9.0中的构造方法中并没有调用此方法,而是在所有与WMS相关联的实体类都创建好之后(例如AMS)才会调用:
image.png

通过通过addMonitor方法将WMS添加到WatchDog中,WatchDog每分钟都会对被监控的系统服务进行检查,如果被监控的系统服务出现了死锁,则会杀死WatchDog所在进程,也就是SystemServer进程。
看一下initPolicy方法:
image.png

与WMS的main方法类似,执行WMP的init方法,此方法运行在android.ui线程中,android.ui线程优先级又比android.display优先级高,所以android.display需要等android.ui线程执行完毕后才能继续执行。WMS的启动过程中涉及到了三个线程:
system_server、android.display和android.ui。这三个线程的联系如下:
QQ图片20210330233232.jpg

1.首先在system_server线程中执行SystemServer的startOtherService方法,在startOtherService方法中调用WMS的main方法,会创建WMS,创建过程在android.display线程中,此线程优先级比system_server优先级高,所以system_server会等待android.display线程执行完毕再执行。
2.在WMS的构造方法中调用WMS的initPolicy方法,initPolicy方法会调用PMS(PhoneWindowManager)的init方法,此方法运行在android.ui线程中,此线程优先级比android.display优先级高,所以android.display需要等待android.ui线程执行完毕后再执行。
3.PWM的init方法执行结束后,继续执行android.display方法,android.display线程执行完毕就完成了WMS的创建。等待system_server线程被唤醒后继续执行WMS的main方法之后的逻辑。

WMS的重要成员

image.png

1.mPolicy:WindowManagerPolicy
前面也说了,WindowManagerPolicy是窗口管理策略的接口类,具体实现是PhoneWindowManager.
2.mSessions:ArraySet
mSessions是ArraySet类型的变量,元素类型为Session,它主要用于进程间通信,其他的应用程序进程想要和WMS的进程进行通信就必须通过Session。并且每个应用程序都会对应一个Session。
3.mWindowMap:WindowHashMap
key类型是IBinder,value值类型是WindowState。WindowState用来描述一个窗口。此hashMap就是用来保存WMS中各种窗口的集合。
4.mFinishedStartinga:ArrayList
5.mResizingWindows:ArrayList
6.mAnimator:WindowAnimator
用来管理窗口的动画以及特效动画。
7.mH:H
mH是H类型的变量,系统的Handler类,用于将任务加入到主线程的消息队列中。这样代码逻辑就会在主线程中运行。
8.mInputManager:InputManagerService
mInputManager是InputManagerService类型的变量,输入系统的管理者。IMS会对触摸事件进行管理,它会寻找一个最合适的窗口来处理触摸反馈信息。

Window的添加过程(WMS处理部分)

Window的操作分为两部分,一部分是WindowManager处理部分,另一部分是WMS处理部分;WindowManager处理部分之前说过了,我们主要看WMS处理的部分,在其addWindow方法中:


image.png

这个方法里逻辑比较重,但重要程度没有那么高,暂不贴源码,先做一些摘要:
addWindow方法会返回addWindow操作的各种状态。主要做了以下4件事情:
①对所要添加的窗口进行检查,在WindowManagerPolicy的checkAddPermission方法中进行判断,如果窗口不满足一些条件,就不会执行下面的代码。
②WindowToken相关处理,根据父窗口的rootType来判断当前窗口是否需要提供WindowToken,没有提供的就不会执行下面的逻辑;而有的窗口类型需要WMS隐式创建WindowToken
③WindowState的创建和相关处理,将WindowToken和WindowState相关联。WindowState存有窗口的所有的状态信息。
④创建和配置DisplayContent,完成窗口添加到系统前的准备工作。DisplayContent用来描述一块屏幕,里面存着屏幕id、动画、状态等信息。


image.png

Window的删除过程

和Window的创建与更新过程一样,要删除Window需要先调用WindowManagerImpl的removeView方法,在removeView方法中又会调用WindowManagerGlobal的removeView方法。
还是做一些摘要:
①检查线程的安全性,如果不正确就抛出异常。执行ViewRootImpl的doDie方法来判断删除Window的线程是否是创建此Window的原始线程,因为只有创建Window的原始线程才能够操作Window。
②从ViewRootImpl列表、布局参数列表和View列表中删除和Window对应的元素
③判断是否可以执行删除操作,如果不能就推迟删除操作,比如当前Window在执行动画,就等动画执行完成后再执行删除操作
④执行删除操作,清理和释放与Window相关的一切资源。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容