一、WMS的職責(zé)
WMS是Android中重要的服務(wù),它是WindowManager的管理者,WMS無(wú)論對(duì)于應(yīng)用開(kāi)發(fā)還是Framework開(kāi)發(fā)都是重要的知識(shí)點(diǎn),究其原因是因?yàn)閃MS有很多職責(zé),每個(gè)職責(zé)都會(huì)涉及重要且復(fù)雜的系統(tǒng),這使得WMS就像一個(gè)十字路口的交通燈一樣,沒(méi)有了這個(gè)交通燈,十字路口就無(wú)法正常通車(chē),WMS的職責(zé)只要有以下幾點(diǎn)。
1、窗口管理
WMS是窗口的管理者,它負(fù)責(zé)窗口的啟動(dòng)、添加和刪除,另外窗口的大小和層級(jí)也是由WMS進(jìn)行管理的。窗口管理的核心成員由DisplayContent、WindowToken和WindowState。
2、窗口動(dòng)畫(huà)
窗口間進(jìn)行切換時(shí),使用窗口動(dòng)畫(huà)可以顯得更炫一些,窗口動(dòng)畫(huà)由WMS的動(dòng)畫(huà)子系統(tǒng)來(lái)負(fù)責(zé),動(dòng)畫(huà)子系統(tǒng)的管理者為WindowAnimator。
3、輸入系統(tǒng)的中轉(zhuǎn)站
通過(guò)對(duì)窗口的觸摸從而產(chǎn)生觸摸事件,InputManagerService(IMS)會(huì)對(duì)觸摸事件進(jìn)行處理,它會(huì)尋找一個(gè)最合適的窗口來(lái)處理觸摸反饋信息,WMS是窗口的管理者,它作為輸入系統(tǒng)的中轉(zhuǎn)站再合適不過(guò)。
4、Surface管理
窗口并不具備繪制的功能,因此每個(gè)窗口都需要有一塊Surface來(lái)供自己繪制,為每個(gè)窗口分配Surface時(shí)由WMS來(lái)完成的。

從上圖可以看出WMS很復(fù)雜,與它關(guān)聯(lián)的由窗口管理、窗口動(dòng)畫(huà)、輸入系統(tǒng)和Surface,它們每一個(gè)都是重要且負(fù)責(zé)的系統(tǒng)。
二、WMS的創(chuàng)建過(guò)程
1)WMS涉及的知識(shí)點(diǎn)非常多,但是無(wú)論這些知識(shí)點(diǎn)如何多,我們還是十分有必要先知道WMS時(shí)如何創(chuàng)建的。WMS時(shí)在SystemServer進(jìn)程中創(chuàng)建的,SystemServer的run方法關(guān)鍵代碼如下所示:
frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
try {
...代碼省略...
Looper.prepareMainLooper();//1創(chuàng)建消息Looper
System.loadLibrary("android_servers");//2加載動(dòng)態(tài)庫(kù)libandroid_servers.so
performPendingShutdown();
createSystemContext();//3初始化系統(tǒng)的Context
mSystemServiceManager = new SystemServiceManager(mSystemContext);//4創(chuàng)建系統(tǒng)服務(wù)管理者
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
SystemServerInitThreadPool.get();
} finally {
traceEnd();
}
// 開(kāi)啟服務(wù)
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();//5啟動(dòng)引導(dǎo)服務(wù)
startCoreServices();//6啟動(dòng)核心服務(wù)
startOtherServices();//7啟動(dòng)其他服務(wù),WMS在該方法中被啟動(dòng)
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...代碼省略...
}
SystemServer的run方法中會(huì)調(diào)用startOtherServices方法,WMS就是在該方法中被啟動(dòng)的。
2)SystemServer的startOtherServices方法如下所示:
private void startOtherServices() {
...代碼省略...
traceBeginAndSlog("InitWatchdog");
final Watchdog watchdog = Watchdog.getInstance();//1得到Watchdog實(shí)例,該對(duì)象可以用來(lái)監(jiān)視系統(tǒng)的一些關(guān)鍵服務(wù)的運(yùn)行狀況。
watchdog.init(context, mActivityManagerService);//2對(duì)Watchdog實(shí)例進(jìn)行初始化
traceEnd();
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);//3創(chuàng)建InputManagerService
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執(zhí)行WMS的main方法,其內(nèi)部會(huì)創(chuàng)建WMS,
ServiceManager.addService(Context.WINDOW_SERVICE, wm);//5將WMS注冊(cè)到服務(wù)管理器中
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);//6將IMS注冊(cè)到服務(wù)管理器中
traceEnd();
...代碼省略...
try {
wm.displayReady();//7初始化屏幕顯示信息
} catch (Throwable e) {
reportWtf("making display ready", e);
}
...代碼省略...
try {
wm.systemReady();//8通知WMS,系統(tǒng)的初始化工作已經(jīng)完成,其內(nèi)部調(diào)用了WindowManagerPolicy的systemReady方法
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
...代碼省略...
}
startOtherServices會(huì)獲取Watchdog實(shí)例并對(duì)實(shí)例進(jìn)行初始化,創(chuàng)建InputManagerService實(shí)例,并在注釋4處將該實(shí)例作為參數(shù)傳遞給WindowManagerService的main方法。
3)WindowManagerService 的main方法如下:
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
//1這里使用了java8中的Lambda表達(dá)式
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs, onlyCore, policy)
, 0);//2創(chuàng)建WMS實(shí)例對(duì)象
return sInstance;
}
DisplayThread是一個(gè)單例的前臺(tái)線程,這個(gè)線程用來(lái)處理需要低延時(shí)顯示的相關(guān)操作,并只能由WindowManager、DisplayManager和InputManager實(shí)時(shí)執(zhí)行快速操作。正是在DisplayThread的run方法中創(chuàng)建了WMS的實(shí)例,這就意味著WMS的創(chuàng)建時(shí)運(yùn)行在android.display線程中的。
4)來(lái)看下Handler的runWithScissors方法:
frameworks/base/core/java/android/os/Handler.java
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) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
- 對(duì)傳入的Runnable的timeout進(jìn)行判斷,如果Runnable為null或者timeout小于0則拋出異常。
- 根據(jù)每個(gè)線程只有一個(gè)Looper的原理來(lái)判斷當(dāng)前線程(system_server線程)是否是Handler所指向的線程(android.display線程),如果是則直接執(zhí)行Runnable的run方法,否則調(diào)用BlockingRunnable的postAndWait方法,并將當(dāng)前線程的Runnable作為參數(shù)傳遞進(jìn)去。
5)BlockingRunnable是Handler的內(nèi)部類(lèi)。
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處將當(dāng)前的BlockingRunnable添加到Handler的任務(wù)隊(duì)列中,上面第3步我們知道runWithScissors方法的第二個(gè)參數(shù)為0,因此timeout等于0,這樣如果mDone為false的話會(huì)一直調(diào)用注釋3處的wait方法使得當(dāng)前線程(system_server線程)進(jìn)入等待狀態(tài)。
- 在注釋1處執(zhí)行了傳入的Runnable的run方法(運(yùn)行在android.display線程中),執(zhí)行完畢后finally代碼塊中將mDone設(shè)置為true,并調(diào)用noifyAll方法喚醒處于等待狀態(tài)的線程,這樣就不會(huì)繼續(xù)調(diào)用注釋3處的wait方法。
結(jié)合以上兩點(diǎn)我們可以得出一個(gè)結(jié)論,system_server線程會(huì)一直等待android.display線程執(zhí)行完畢才開(kāi)始執(zhí)行system_server線程,這是因?yàn)閍ndroid.display線程內(nèi)部執(zhí)行了WMS的創(chuàng)建,而WMS的創(chuàng)建優(yōu)先級(jí)要更高。
6)接下來(lái)我們來(lái)查看一下WMS的構(gòu)造方法。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
...代碼省略...
mInputManager = inputManager; // 注釋1
...代碼省略...
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mDisplays = mDisplayManager.getDisplays(); // 注釋2
for (Display display : mDisplays) {
createDisplayContentLocked(display); // 注釋3
}
...代碼省略...
mActivityManager = ActivityManager.getService(); // 注釋4
...代碼省略...
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
...代碼省略...
mAnimator = new WindowAnimator(this); // 注釋5
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy(); // 注釋6
Watchdog.getInstance().addMonitor(this); // 注釋7
...代碼省略...
}
- 注釋1處保存?zhèn)鬟f進(jìn)來(lái)的IMS,這樣WMS就持有了IMS的引用。
- 注釋2處通過(guò)DisplayManager的getDisplay方法得到Display數(shù)組(每個(gè)顯示設(shè)備都有一個(gè)Display實(shí)例),接著遍歷Display數(shù)組。
- 注釋3處的createDisplayContentLocked方法將Display封裝成DisplayContent,DisplayContent用來(lái)描述一塊屏幕。
- 注釋4處得到AMS實(shí)例,并賦值給mActivityManager,這樣WMS就持有了AMS的引用。
- 注釋5處創(chuàng)建WindowAnimator,用于管理所有的窗口動(dòng)畫(huà)。
- 注釋6處初始化了窗口管理策略的接口類(lèi)WindowManagerPolicy(WMP),它用來(lái)定義一個(gè)窗口策略所要遵循的通用規(guī)范。
- 注釋7處調(diào)用addMonitor方法將自身添加到watchdog中,Watchdog用來(lái)監(jiān)控系統(tǒng)的一些關(guān)鍵服務(wù)的運(yùn)行狀況,這些被監(jiān)控的服務(wù)都會(huì)實(shí)現(xiàn)Watchdog.Monitor接口。Watchdog每分鐘都會(huì)對(duì)被監(jiān)控的系統(tǒng)服務(wù)進(jìn)行檢查,如果被監(jiān)控的系統(tǒng)服務(wù)出現(xiàn)了死鎖,就會(huì)殺死Watchdog所在的進(jìn)程,也就是SystemServer進(jìn)程。
6)繼續(xù)來(lái)看注釋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);
}
initPolicy方法和此前講的WMS的main方法的實(shí)現(xiàn)類(lèi)似,在注釋1處執(zhí)行了WMP的init方法,WMP是一個(gè)接口,init方法具體在PhoneWindowManager(PWM)中實(shí)現(xiàn)。PWM的init方法運(yùn)行在android.ui線程中,它的優(yōu)先級(jí)要高于initPolicy方法所在的android.display線程,因此android.display線程要等PWM的init方法執(zhí)行完畢后,處于等待狀態(tài)的android.display線程才會(huì)被喚醒從而繼續(xù)執(zhí)行下面的代碼。
三、WMS的創(chuàng)建過(guò)程的3個(gè)線程
上面WMS創(chuàng)建的過(guò)程中有提到3個(gè)線程,分別是system_server、android.display和android.ui,下圖是關(guān)于這三個(gè)線程的三個(gè)步驟。

1)首先在system_server線程中執(zhí)行了SystemServer的startOtherServices方法,在startOtherServices方法中會(huì)調(diào)用WMS的main方,main方法會(huì)創(chuàng)建WMS,創(chuàng)建的過(guò)程是在android.display線程中實(shí)現(xiàn)的,由于創(chuàng)建WMS的優(yōu)先級(jí)更高,因此system_server線程要等WMS創(chuàng)建完成后,處于等待狀態(tài)的system_server線程才會(huì)被喚醒從而繼續(xù)執(zhí)行下面的代碼。
2)在WMS的構(gòu)造方法中會(huì)調(diào)用WMS的initPolicy方法,在initPolicy方法中又會(huì)調(diào)用PWM的init方法,PWM的init方法在android.ui線程中運(yùn)行,它的優(yōu)先級(jí)要高于android.display線程,因此"android.display"線程要等PWM的init方法執(zhí)行完畢后,處于等待狀態(tài)的android.display線程才會(huì)被喚醒從而繼續(xù)執(zhí)行下面的代碼。
3)PWM的init方法執(zhí)行完畢后,android.display線程就完成了WMS的創(chuàng)建,等待的system_server線程被喚醒后繼續(xù)執(zhí)行WMS的main方法后的代碼邏輯,比如在前面第二部分第2步的注釋7的地方,WMS的displayReady方法用來(lái)初始化屏幕顯示信息。