相關文章
Android系統啓動系列
Android深刻四大組件系列
Android應用進程啓動過程系列
Android解析WindowManager系列html
此前我用多篇文章介紹了WindowManager,這個系列咱們來介紹WindowManager的管理者WMS,首先咱們先來學習WMS是如何產生的。本文源碼基於Android 8.0,與Android 7.1.2相比有一個比較直觀的變化就是Java FrameWork採用了Lambda表達式。
java
WMS是系統的其餘服務,不管對於應用開發仍是Framework開發都是重點的知識,它的職責有不少,主要有如下幾點:android
WMS是窗口的管理者,它負責窗口的啓動、添加和刪除,另外窗口的大小和層級也是由WMS進行管理的。窗口管理的核心成員有DisplayContent、WindowToken和WindowState。git
窗口間進行切換時,使用窗口動畫能夠顯得更炫一些,窗口動畫由WMS的動畫子系統來負責,動畫子系統的管理者爲WindowAnimator。數組
經過對窗口的觸摸從而產生觸摸事件,InputManagerService(IMS)會對觸摸事件進行處理,它會尋找一個最合適的窗口來處理觸摸反饋信息,WMS是窗口的管理者,所以,WMS「理所應當」的成爲了輸入系統的中轉站。ide
窗口並不具有有繪製的功能,所以每一個窗口都須要有一塊Surface來供本身繪製。爲每一個窗口分配Surface是由WMS來完成的。oop
WMS的職責能夠簡單總結爲下圖。post
WMS的知識點很是多,在瞭解這些知識點前,咱們十分有必要知道WMS是如何產生的。WMS是在SyetemServer進程中啓動的,不瞭解SyetemServer進程的能夠查看在Android系統啓動流程(三)解析SyetemServer進程啓動過程這篇文章。
先來查看SyetemServer的main方法:
frameworks/base/services/java/com/android/server/SystemServer.java學習
public static void main(String[] args) {
new SystemServer().run();
}複製代碼
main方法中只調用了SystemServer的run方法,以下所示。
frameworks/base/services/java/com/android/server/SystemServer.java動畫
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。從註釋三、四、5的方法名稱能夠看出,官方把大概80多個系統服務分爲了三種類型,分別是引導服務、核心服務和其餘服務,其中其餘服務爲一些非緊要和一些不須要當即啓動的服務,WMS就是其餘服務的一種。
咱們來查看startOtherServices方法是如何啓動WMS的:
frameworks/base/services/java/com/android/server/SystemServer.java
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的啓動邏輯,剩餘的其餘服務的啓動邏輯也都大同小異。
在註釋一、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方法,以下所示。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java
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;
}複製代碼
在註釋1處調用了DisplayThread的getHandler方法,用來獲得DisplayThread的Handler實例。DisplayThread是一個單例的前臺線程,這個線程用來處理須要低延時顯示的相關操做,並只能由WindowManager、DisplayManager和InputManager實時執行快速操做。註釋1處的runWithScissors方法中使用了Java8中的Lambda表達式,它等價於以下代碼:
DisplayThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy);//2
}
}, 0);複製代碼
在註釋2處建立了WMS的實例,這個過程運行在Runnable的run方法中,而Runnable則傳入到了DisplayThread對應Handler的runWithScissors方法中,說明WMS的建立是運行在「android.display」線程中。須要注意的是,runWithScissors方法的第二個參數傳入的是0,後面會提到。來查看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) {//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的內部類,代碼以下所示。
frameworks/base/core/java/android/os/Handler.java
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_server"線程,這是由於"android.display"線程內部執行了WMS的建立,顯然WMS的建立優先級更高些。
WMS的建立就講到這,最後咱們來查看WMS的構造方法:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java
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方法,以下所示。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
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方法的實現相似,註釋1處執行了WMP的init方法,WMP是一個接口,init方法的具體實如今PhoneWindowManager(PWM)中。PWM的init方法運行在"android.ui"線程中,它的優先級要高於initPolicy方法所在的"android.display"線程,所以"android.display"線程要等PWM的init方法執行完畢後,處於等待狀態的"android.display"線程纔會被喚醒從而繼續執行下面的代碼。
在本文中共提到了3個線程,分別是"system_server"、"android.display"和"android.ui",爲了便於理解,下面給出這三個線程之間的關係。
"system_server"線程中會調用WMS的main方法,main方法中會建立WMS,建立WMS的過程運行在"android.display"線程中,它的優先級更高一些,所以要等建立WMS完畢後纔會喚醒處於等待狀態的"system_server"線程。
WMS初始化時會執行initPolicy方法,initPolicy方法會調用PWM的init方法,這個init方法運行在"android.ui"線程,而且優先級更高,所以要先執行完PWM的init方法後,纔會喚醒處於等待狀態的"android.display"線程。
PWM的init方法執行完畢後會接着執行運行在"system_server"線程的代碼,好比本文前部分提到WMS的
systemReady方法。
參考資料
《深刻理解Android內核設計思想》第二版
《深刻理解Android:卷III》
WMS—啓動過程
Android Watchdog源碼簡析--Based on Android 6.0.1
Watchdog實現分析