1.WMS概述
WMS是系统的其他服务,无论对于应用开发还是Framework开发都是重点的知识,它的职责有很多,主要有以下几点:
-
窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由WMS的动画子系统来负责,动画子系统的管理者为WindowAnimator。
-
输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS是窗口的管理者,因此,WMS“理所应当”的成为了输入系统的中转站。
-
Surface管理
窗口并不具备有绘制的功能,因此每个窗口都需要有一块Surface来供自己绘制。为每个窗口分配Surface是由WMS来完成的。
WMS的诞生
WMS是在SyetemServer进程中启动的,先看SyetemServer的方法frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
run方法中的代码如下所示
private void run() {
try {
System.loadLibrary("android_servers");//1
...
mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();//3
startCoreServices();//4
startOtherServices();//5
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
}
run方法代码很多,这里截取了关键的部分,在注释1处加载了libandroid_servers.so
。在注释2处创建SystemServiceManager
,它会对系统的服务进行创建、启动和生命周期管理。接下来的代码会启动系统的各种服务,在注释3中的startBootstrapServices
方法中用SystemServiceManager
启动了ActivityManagerService、PowerManagerService、PackageManagerService
等服务。在注释4处的方法中则启动了BatteryService、UsageStatsService和WebViewUpdateService
。注释5处的startOtherServices
方法中则启动了CameraService、AlarmManagerService、VrManagerService
等服务,这些服务的父类为SystemService。从注释3、4、5的方法名称可以看出,官方把大概80多个系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务为一些非紧要和一些不需要立即启动的服务,WMS就是其他服务的一种。
接下来我们来查看startOtherServices
方法是如何启动WMS的:
private void startOtherServices() {
...
traceBeginAndSlog("InitWatchdog");
final Watchdog watchdog = Watchdog.getInstance();//1
watchdog.init(context, mActivityManagerService);//2
traceEnd();
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);//3
traceEnd();
traceBeginAndSlog("StartWindowManagerService");
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());//4
ServiceManager.addService(Context.WINDOW_SERVICE, wm);//5
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);//6
traceEnd();
...
try {
wm.displayReady();//7
} catch (Throwable e) {
reportWtf("making display ready", e);
}
...
try {
wm.systemReady();//8
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
...
}
startOtherServices
方法用于启动其他服务,其他服务大概有70多个,上面的代码只列出了WMS以及和它相关的IMS的启动逻辑,剩余的其他服务的启动逻辑也都大同小异。
在注释1、2处分别得到Watchdog
实例并对它进行初始化,Watchdog
用来监控系统的一些关键服务的运行状况,后文会再次提到它。在注释3处创建了IMS,并赋值给IMS类型的inputManager
对象。注释4处执行了WMS的main方法,其内部会创建WMS,需要注意的是main方法其中一个传入的参数就是注释1处创建的IMS,WMS是输入事件的中转站,其内部包含了IMS引用并不意外。结合上文,我们可以得知WMS的main方法是运行在SystemServer
的run方法中,换句话说就是运行在system_server
线程”中,后面会再次提到system_server
线程。
注释5和注释6处分别将WMS和IMS注册到ServiceManager
中,这样如果某个客户端想要使用WMS,就需要先去ServiceManager中查询信息,然后根据信息与WMS所在的进程建立通信通路,客户端就可以使用WMS了。注释7处用来初始化显示信息,注释8处则用来通知WMS,系统的初始化工作已经完成,其内部调用了WindowManagerPolicy
的systemReady
方法。
接下来我们来查看注释4处WMS的main方法:
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
DisplayThread.getHandler().runWithScissors(() ->//1
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}
在注释2处创建了WMS的实例,这个过程运行在Runnable
的run方法中,而Runnable
则传入到了DisplayThread
对应Handler
的runWithScissors
方法中,说明WMS的创建是运行在android.display
线程中。需要注意的是,runWithScissors
方法的第二个参数传入的是0,后面会提到。来查看Handler
的runWithScissors
方法里做了什么:
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) {//1
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
开头对传入的Runnable
和timeout
进行了判断,如果Runnable
为null
或者timeout
小于0则抛出异常。注释1处根据每个线程只有一个Looper
的原理来判断当前的线程(system_server
线程)是否是Handler
所指向的线程(android.display
线程),如果是则直接执行Runnable
的run
方法,如果不是则调用BlockingRunnable
的postAndWait
方法,并将当前线程的Runnable
作为参数传进去 ,BlockingRunnable
是Handler
的内部类,代码如下所示。
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();//1
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) {//2
return false;
}
synchronized (this) {
if (timeout > 0) {
final long expirationTime = SystemClock.uptimeMillis() + timeout;
while (!mDone) {
long delay = expirationTime - SystemClock.uptimeMillis();
if (delay <= 0) {
return false; // timeout
}
try {
wait(delay);
} catch (InterruptedException ex) {
}
}
} else {
while (!mDone) {
try {
wait();//3
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
注释2处将当前的BlockingRunnable
添加到Handler
的任务队列中。前面runWithScissors
方法的第二个参数为0,因此timeout
等于0,这样如果mDone
为false
的话会一直调用注释3处的wait
方法使得当前线程(”system_server
”线程)进入等待状态,那么等待的是哪个线程呢?我们往上看,注释1处,执行了传入的Runnable
的run
方法(运行在”android.display
”线程),执行完毕后在finally
代码块中将mDone
设置为true
,并调用notifyAll
方法唤醒处于等待状态的线程,这样就不会继续调用注释3处的wait
方法。因此得出结论,”system_server
”线程线程等待的就是”android.display
”线程,一直到”android.display
”线程执行完毕再执行”system_serve
r”线程,这是因为”android.display
”线程内部执行了WMS的创建,显然WMS的创建优先级更高些。
WMS的创建就讲到这,最后我们来查看WMS的构造方法:
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
...
mInputManager = inputManager;//1
...
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mDisplays = mDisplayManager.getDisplays();//2
for (Display display : mDisplays) {
createDisplayContentLocked(display);//3
}
...
mActivityManager = ActivityManagerNative.getDefault();//4
...
mAnimator = new WindowAnimator(this);//5
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();//6
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);//7
...
}
注释1处用来保存传进来的IMS
,这样WMS
就持有了IMS
的引用。注释2处通过DisplayManager
的getDisplays
方法得到Display
数组(每个显示设备都有一个Display
实例),接着遍历Display
数组,在注释3处的createDisplayContentLocked
方法会将Display
封装成DisplayContent
,DisplayContent
用来描述一快屏幕。
注释4处得到AMS
实例,并赋值给mActivityManager
,这样WMS
就持有了AMS
的引用。注释5处创建了WindowAnimator
,它用于管理所有的窗口动画。注释6处初始化了窗口管理策略的接口类WindowManagerPolicy(WMP)
,它用来定义一个窗口策略所要遵循的通用规范。注释7处将自身也就是WMS
通过addMonitor
方法添加到Watchdog
中,Watchdog
用来监控系统的一些关键服务的运行状况(比如传入的WMS的运行状况),这些被监控的服务都会实现Watchdog.Monitor
接口。Watchdog
每分钟都会对被监控的系统服务进行检查,如果被监控的系统服务出现了死锁,则会杀死Watchdog
所在的进程,也就是SystemServer
进程。
查看注释6处的initPolicy
方法,如下所示。
private void initPolicy() {
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);//1
}
}, 0);
}